diff --git a/app_main/src/main/AndroidManifest.xml b/app_main/src/main/AndroidManifest.xml
index 24d5e6a2..45cb0fe8 100644
--- a/app_main/src/main/AndroidManifest.xml
+++ b/app_main/src/main/AndroidManifest.xml
@@ -92,7 +92,6 @@
-
{
callback.onDetach(getDevice());
}
- @Override
- public int getUniqueId() {
- return UNIQUE_ID;
- }
-
@Override
public void unregister() {
//解注册广播监听事件!
@@ -108,22 +105,12 @@ public class StandardDriver implements DriverInterface {
}
@Override
- public int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException {
- throw new IOException("can't invoke");
+ public OutputStream getOutput() {
+ return null;
}
@Override
- public int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException {
- throw new IOException("can't invoke");
- }
-
- @Override
- public void flush() throws IOException {
- throw new IOException("can't invoke");
- }
-
- @Override
- public void close() throws IOException {
- throw new IOException("can't invoke");
+ public InputStream getInput() {
+ return null;
}
}
diff --git a/app_main/src/main/java/cn/rrg/rdv/fragment/tools/Proxmark3Rdv4RRGMFRWOperateFragment.java b/app_main/src/main/java/cn/rrg/rdv/fragment/tools/Proxmark3Rdv4RRGMFRWOperateFragment.java
deleted file mode 100644
index 76bf6266..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/fragment/tools/Proxmark3Rdv4RRGMFRWOperateFragment.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package cn.rrg.rdv.fragment.tools;
-
-import cn.rrg.rdv.presenter.AbsTagKeysCheckPresenter;
-import cn.rrg.rdv.presenter.AbsTagReadPresenter;
-import cn.rrg.rdv.presenter.AbsTagStatePresenter;
-import cn.rrg.rdv.presenter.AbsTagWritePresenter;
-import cn.rrg.rdv.presenter.Proxmark3Rdv4RRGTagKeysCheckPresenter;
-import cn.rrg.rdv.presenter.Proxmark3Rdv4RRGTagReadPresenter;
-import cn.rrg.rdv.presenter.Proxmark3Rdv4RRGTagStatePresenter;
-import cn.rrg.rdv.presenter.Proxmark3Rdv4RRGTagWritePresenter;
-
-public class Proxmark3Rdv4RRGMFRWOperateFragment extends AbsMfOperatesFragment {
- @Override
- protected AbsTagStatePresenter getTagStatePresenter() {
- return new Proxmark3Rdv4RRGTagStatePresenter();
- }
-
- @Override
- protected AbsTagKeysCheckPresenter getKeysCheckPresenter() {
- return new Proxmark3Rdv4RRGTagKeysCheckPresenter();
- }
-
- @Override
- protected AbsTagReadPresenter getTagReadPresenter() {
- return new Proxmark3Rdv4RRGTagReadPresenter();
- }
-
- @Override
- protected AbsTagWritePresenter getTagWritePresenter() {
- return new Proxmark3Rdv4RRGTagWritePresenter();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/fragment/tools/Proxmark3Rdv4RRGShowInformationFragment.java b/app_main/src/main/java/cn/rrg/rdv/fragment/tools/Proxmark3Rdv4RRGShowInformationFragment.java
deleted file mode 100644
index bd3ff8e8..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/fragment/tools/Proxmark3Rdv4RRGShowInformationFragment.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.rrg.rdv.fragment.tools;
-
-import cn.rrg.rdv.presenter.AbsTagInformationsPresenter;
-import cn.rrg.rdv.presenter.Proxmark3Rdv4RRGTagInformationsPresenter;
-
-public class Proxmark3Rdv4RRGShowInformationFragment extends AbsShowInformationFragment {
- @Override
- protected AbsTagInformationsPresenter getPresenter() {
- return new Proxmark3Rdv4RRGTagInformationsPresenter();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/AbsUsb2UartModel.java b/app_main/src/main/java/cn/rrg/rdv/models/AbsUsb2UartModel.java
index 25b2ca6e..8477462f 100644
--- a/app_main/src/main/java/cn/rrg/rdv/models/AbsUsb2UartModel.java
+++ b/app_main/src/main/java/cn/rrg/rdv/models/AbsUsb2UartModel.java
@@ -17,7 +17,7 @@ public abstract class AbsUsb2UartModel extends AbstractDeviceModel getDriverInterface() {
- return DriverSource.driverMap.get(0x04);
+ return UsbSerialControl.get();
}
@Override
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/AbstractDeviceModel.java b/app_main/src/main/java/cn/rrg/rdv/models/AbstractDeviceModel.java
index 744a8ca5..72ac2041 100644
--- a/app_main/src/main/java/cn/rrg/rdv/models/AbstractDeviceModel.java
+++ b/app_main/src/main/java/cn/rrg/rdv/models/AbstractDeviceModel.java
@@ -13,7 +13,6 @@ import cn.dxl.common.util.LogUtils;
import cn.rrg.com.DevCallback;
import cn.rrg.com.DriverInterface;
-import cn.dxl.com.ComBridgeAdapter;
import cn.dxl.com.DeviceChecker;
import cn.rrg.rdv.javabean.DevBean;
import cn.rrg.rdv.callback.ConnectCallback;
@@ -173,10 +172,9 @@ public abstract class AbstractDeviceModel
public void run() {
//直接连接,有需要时可重写!
try {
- if (mDeviceChecker.working()) {
+ if (mDeviceChecker.check()) {
callback.onInitSuccess();
} else {
-
LogUtils.d("初始化失败,将会调用设备封装类关闭设备!");
// close device!
mDeviceChecker.close();
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/Acr122uUsbRawModel.java b/app_main/src/main/java/cn/rrg/rdv/models/Acr122uUsbRawModel.java
index 00bca44f..79301ce0 100644
--- a/app_main/src/main/java/cn/rrg/rdv/models/Acr122uUsbRawModel.java
+++ b/app_main/src/main/java/cn/rrg/rdv/models/Acr122uUsbRawModel.java
@@ -18,7 +18,7 @@ import cn.rrg.rdv.util.Commons;
public class Acr122uUsbRawModel extends AbstractDeviceModel {
@Override
public DriverInterface getDriverInterface() {
- return DriverSource.driverMap.get(0x03);
+ return UsbAcr122Raw.get();
}
@Override
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/DriverSource.java b/app_main/src/main/java/cn/rrg/rdv/models/DriverSource.java
deleted file mode 100644
index 9dca39b0..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/models/DriverSource.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cn.rrg.rdv.models;
-
-import android.util.SparseArray;
-
-import cn.rrg.com.DriverInterface;
-import cn.rrg.com.SppHasBlock;
-import cn.rrg.com.SppNonBlock;
-import cn.rrg.rdv.driver.StandardDriver;
-import cn.rrg.com.UniversalBulkTransfer;
-import cn.rrg.com.UsbAcr122Raw;
-import cn.rrg.com.UsbSerialControl;
-
-/*
- * 驱动池,所有的驱动最终加载成功后都将被打进当前的实例进行缓存!!!
- * Datasource, all driver from here.
- * */
-public class DriverSource {
- //一个驱动实体的映射表,当匹配到对应的驱动时将会把驱动打进或者取出!
- public static SparseArray driverMap = new SparseArray<>();
-
- static {
- /*
- * 放入SPP非堵塞不缓存实现驱动! code 0x01
- * 适用于不需要堵塞读取,不需要缓存发送帧的设备
- * 已知适用设备:
- * 1. PM3 RDV4 蓝牙模组
- * */
- driverMap.put(SppNonBlock.get().getUniqueId(), SppNonBlock.get());
- /*
- * 放入SPP堵塞缓存实现驱动! code 0x02
- * 适用于需要堵塞读取,在数据异常时需要发送缓存包重新请求的设备
- * 已知适用设备:
- * 1. PN532 + 蓝牙SPP
- * */
- driverMap.put(SppHasBlock.get().getUniqueId(), SppHasBlock.get());
- // 放入USB 122u原生字节实现, code 0x03
- driverMap.put(UsbAcr122Raw.get().getUniqueId(), UsbAcr122Raw.get());
- /*
- * 放入USB 转串口实现! code 0x04
- * 适用于市场上大部分USB转串口实现,该实现为ControlTransfer函数实现,速度较慢
- * 已知适用设备:
- * 1. PM3 RDV4 CDC
- * 2. PN532 Usb 2 Serial
- * 3. Chameleon CDC
- * */
- driverMap.put(UsbSerialControl.get().getUniqueId(), UsbSerialControl.get());
- // 放入标准NFC设备到驱动映射表,只适用标准NFC! code 0x05
- driverMap.put(StandardDriver.get().getUniqueId(), StandardDriver.get());
- // 通用USB RAW驱动!
- driverMap.put(UniversalBulkTransfer.getTransfer().getUniqueId(), UniversalBulkTransfer.getTransfer());
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/PN532SppUartModel.java b/app_main/src/main/java/cn/rrg/rdv/models/PN532SppUartModel.java
index 86bc9a74..490a0a50 100644
--- a/app_main/src/main/java/cn/rrg/rdv/models/PN532SppUartModel.java
+++ b/app_main/src/main/java/cn/rrg/rdv/models/PN532SppUartModel.java
@@ -5,6 +5,7 @@ import android.bluetooth.BluetoothDevice;
import cn.rrg.com.DriverInterface;
import cn.dxl.com.DeviceChecker;
+import cn.rrg.com.SppHasBlock;
import cn.rrg.devices.PN53X;
/*
@@ -13,7 +14,7 @@ import cn.rrg.devices.PN53X;
public class PN532SppUartModel extends AbstractSppDeviceModel {
@Override
public DriverInterface getDriverInterface() {
- return DriverSource.driverMap.get(0x02);
+ return SppHasBlock.get();
}
@Override
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagInformationsModel.java b/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagInformationsModel.java
deleted file mode 100644
index 8fd46967..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagInformationsModel.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package cn.rrg.rdv.models;
-
-import android.nfc.tech.MifareClassic;
-import android.util.Log;
-
-import java.io.File;
-import java.io.IOException;
-
-import cn.dxl.common.application.App;
-import cn.dxl.common.util.AppUtil;
-import cn.dxl.common.util.FileUtils;
-import cn.dxl.common.util.HexUtil;
-import cn.rrg.natives.PM3Rdv4RRGMifare;
-import cn.rrg.rdv.R;
-import cn.rrg.rdv.callback.TagInformationsCallback;
-import cn.rrg.rdv.util.Paths;
-
-public class Proxmark3Rdv4RRGTagInformationsModel {
- private String LOG_TAG = "Proxmark3Rdv4RRGTagInformationsModel";
- private PM3Rdv4RRGMifare spclMf = PM3Rdv4RRGMifare.get();
- private App application = AppUtil.getInstance().getApp();
-
- public void collect(TagInformationsCallback callback) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- if (spclMf.scanning() && spclMf.connect()) {
- byte[] uidBytes = spclMf.getUid();
- String uid = "unknown";
- if (uidBytes != null)
- uid = HexUtil.toHexString(uidBytes);
- String size = "" + spclMf.getSize();
- String atqa = HexUtil.toHexString(spclMf.getAtqa());
- String sak = HexUtil.toHexString(spclMf.getSak());
- String sectorCount = "" + spclMf.getSectorCount();
- String blockCount = "" + spclMf.getBlockCount();
- String ats = "-";
- String tagType = application.getString(R.string.tag_unknown_mf_classic);
-
- File template_mifare_info = new File(Paths.COMMON_DIRECTORY + "/" + "template_mifare_info_en.html");
-
- try {
- //读取本地的HTML模板文件!
- byte[] templateBytes = FileUtils.readBytes(template_mifare_info);
- String htmlSr = new String(templateBytes);
- //替换信息!
- htmlSr = htmlSr.replaceAll("\\$\\{UID\\}", uid);
- htmlSr = htmlSr.replaceAll("\\$\\{Tech\\}", "ISO/IEC 14443, Type A");
- htmlSr = htmlSr.replaceAll("\\$\\{ATQA\\}", atqa);
- htmlSr = htmlSr.replaceAll("\\$\\{SAK\\}", sak);
- htmlSr = htmlSr.replaceAll("\\$\\{ATS\\}", ats);
-
- htmlSr = htmlSr.replaceAll("\\$\\{TM\\}", tagType);
- htmlSr = htmlSr.replaceAll("\\$\\{MS\\}", size + " byte");
- htmlSr = htmlSr.replaceAll("\\$\\{BS\\}", MifareClassic.BLOCK_SIZE + " byte");
- htmlSr = htmlSr.replaceAll("\\$\\{SC\\}", sectorCount);
- htmlSr = htmlSr.replaceAll("\\$\\{BC\\}", blockCount);
-
- callback.onInformationsShow(htmlSr);
- spclMf.close();
- } catch (IOException e) {
- e.printStackTrace();
- callback.onInformationsShow("Template file no exists!");
- }
- } else {
- Log.d(LOG_TAG, "collect调用,卡片不存在!");
- callback.onInformationsShow(application.getString(R.string.tag_not_found));
- }
- }
- }).start();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagReadModel.java b/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagReadModel.java
deleted file mode 100644
index b1b6cf8f..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagReadModel.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.rrg.rdv.models;
-
-import cn.dxl.mifare.MifareAdapter;
-import cn.rrg.natives.PM3Rdv4RRGMifare;
-
-public class Proxmark3Rdv4RRGTagReadModel extends AbsTagReadModel {
- @Override
- protected MifareAdapter getTag() {
- return PM3Rdv4RRGMifare.get();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagStateModel.java b/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagStateModel.java
deleted file mode 100644
index eadc61e2..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagStateModel.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package cn.rrg.rdv.models;
-
-import cn.rrg.natives.PM3Rdv4RRGMifare;
-
-public class Proxmark3Rdv4RRGTagStateModel extends AbsTagStateModel {
- private PM3Rdv4RRGMifare mifare = PM3Rdv4RRGMifare.get();
-
- @Override
- protected boolean checkTagState() {
- if (mifare.scanning()) {
- if (mifare.connect()) {
- mifare.close();
- return true;
- } else {
- mifare.close();
- return false;
- }
- } else {
- mifare.close();
- return false;
- }
- }
-
- @Override
- protected boolean checkTagMagic() {
- if (!mifare.scanning()) {
- mifare.close();
- return false;
- }
- if (mifare.connect()) {
- mifare.close();
- if (mifare.unlock()) {
- mifare.close();
- return true;
- }
- }
- mifare.close();
- return false;
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagWriteModel.java b/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagWriteModel.java
deleted file mode 100644
index 7afaef6c..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4RRGTagWriteModel.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.rrg.rdv.models;
-
-import cn.dxl.mifare.MifareAdapter;
-import cn.rrg.natives.PM3Rdv4RRGMifare;
-
-public class Proxmark3Rdv4RRGTagWriteModel extends AbsTagWriteModel {
- @Override
- protected MifareAdapter getTag() {
- return PM3Rdv4RRGMifare.get();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4SppModel.java b/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4SppModel.java
index 6ec3a908..b8b9b530 100644
--- a/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4SppModel.java
+++ b/app_main/src/main/java/cn/rrg/rdv/models/Proxmark3Rdv4SppModel.java
@@ -5,6 +5,7 @@ import android.bluetooth.BluetoothDevice;
import cn.rrg.com.DriverInterface;
import cn.dxl.com.DeviceChecker;
+import cn.rrg.com.SppNonBlock;
import cn.rrg.devices.Proxmark3RRGRdv4;
/*
@@ -14,7 +15,7 @@ public class Proxmark3Rdv4SppModel extends AbstractSppDeviceModel {
@Override
public DriverInterface getDriverInterface() {
- return DriverSource.driverMap.get(0x01);
+ return SppNonBlock.get();
}
@Override
diff --git a/app_main/src/main/java/cn/rrg/rdv/models/UniversalBulkPN53XRawModel.java b/app_main/src/main/java/cn/rrg/rdv/models/UniversalBulkPN53XRawModel.java
index 12bbb859..4133e392 100644
--- a/app_main/src/main/java/cn/rrg/rdv/models/UniversalBulkPN53XRawModel.java
+++ b/app_main/src/main/java/cn/rrg/rdv/models/UniversalBulkPN53XRawModel.java
@@ -10,6 +10,7 @@ import cn.rrg.com.DevCallback;
import cn.dxl.com.DeviceChecker;
import cn.rrg.com.DriverInterface;
import cn.rrg.com.UniversalBulkTransfer;
+import cn.rrg.com.UsbBulkTransferRaw;
import cn.rrg.devices.PN53X;
import cn.rrg.rdv.callback.ConnectCallback;
import cn.rrg.rdv.javabean.DevBean;
@@ -26,7 +27,7 @@ public class UniversalBulkPN53XRawModel extends AbstractDeviceModel getDriverInterface() {
- return DriverSource.driverMap.get(0x06);
+ return UniversalBulkTransfer.getTransfer();
}
@Override
diff --git a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagInformationsPresenter.java b/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagInformationsPresenter.java
deleted file mode 100644
index e9f91323..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagInformationsPresenter.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cn.rrg.rdv.presenter;
-
-import cn.rrg.rdv.callback.TagInformationsCallback;
-import cn.rrg.rdv.models.Proxmark3Rdv4RRGTagInformationsModel;
-
-public class Proxmark3Rdv4RRGTagInformationsPresenter extends AbsTagInformationsPresenter {
- @Override
- public void show() {
- if (isViewAttach()) {
- new Proxmark3Rdv4RRGTagInformationsModel().collect(new TagInformationsCallback() {
- @Override
- public void onInformationsShow(CharSequence charSequence) {
- view.onInformationsShow(charSequence);
- }
- });
- }
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagKeysCheckPresenter.java b/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagKeysCheckPresenter.java
deleted file mode 100644
index 1ddbd096..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagKeysCheckPresenter.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cn.rrg.rdv.presenter;
-
-import cn.dxl.mifare.MifareAdapter;
-import cn.rrg.natives.PM3Rdv4RRGMifare;
-import cn.rrg.rdv.models.AbsTagKeysCheckModel;
-
-public class Proxmark3Rdv4RRGTagKeysCheckPresenter extends TagKeysCheckPresenterImpl {
-
- @Override
- public AbsTagKeysCheckModel getTagKeysCheckModel() {
- return new AbsTagKeysCheckModel(this) {
- @Override
- public MifareAdapter getTag() {
- return PM3Rdv4RRGMifare.get();
- }
- };
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagReadPresenter.java b/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagReadPresenter.java
deleted file mode 100644
index 53af725e..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagReadPresenter.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.rrg.rdv.presenter;
-
-import cn.rrg.rdv.models.AbsTagReadModel;
-import cn.rrg.rdv.models.Proxmark3Rdv4RRGTagReadModel;
-
-public class Proxmark3Rdv4RRGTagReadPresenter extends AbsTagReadPresenter {
- @Override
- protected AbsTagReadModel getTagReadModel() {
- return new Proxmark3Rdv4RRGTagReadModel();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagStatePresenter.java b/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagStatePresenter.java
deleted file mode 100644
index 084bb646..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagStatePresenter.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.rrg.rdv.presenter;
-
-import cn.rrg.rdv.models.AbsTagStateModel;
-import cn.rrg.rdv.models.Proxmark3Rdv4RRGTagStateModel;
-
-public class Proxmark3Rdv4RRGTagStatePresenter extends AbsTagStatePresenter {
- @Override
- protected AbsTagStateModel getModel() {
- return new Proxmark3Rdv4RRGTagStateModel();
- }
-}
diff --git a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagWritePresenter.java b/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagWritePresenter.java
deleted file mode 100644
index f33004e6..00000000
--- a/app_main/src/main/java/cn/rrg/rdv/presenter/Proxmark3Rdv4RRGTagWritePresenter.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.rrg.rdv.presenter;
-
-import cn.rrg.rdv.models.AbsTagWriteModel;
-import cn.rrg.rdv.models.Proxmark3Rdv4RRGTagWriteModel;
-
-public class Proxmark3Rdv4RRGTagWritePresenter extends AbsTagWritePresenter {
- @Override
- protected AbsTagWriteModel getWriteModel() {
- return new Proxmark3Rdv4RRGTagWriteModel();
- }
-}
diff --git a/app_main/src/main/res/layout/act_main_proxmark3_rdv4_rrg.xml b/app_main/src/main/res/layout/act_main_proxmark3_rdv4_rrg.xml
index 05ebe367..b5600db0 100644
--- a/app_main/src/main/res/layout/act_main_proxmark3_rdv4_rrg.xml
+++ b/app_main/src/main/res/layout/act_main_proxmark3_rdv4_rrg.xml
@@ -25,33 +25,6 @@
android:paddingEnd="28dp"
android:text="@string/function_name_red_team" />
-
-
-
-
-
-
\ No newline at end of file
diff --git a/chameleon/src/main/java/cn/rrg/chameleon/utils/ChameleonVCUtil.java b/chameleon/src/main/java/cn/rrg/chameleon/utils/ChameleonVCUtil.java
index d3035399..cb7bb882 100644
--- a/chameleon/src/main/java/cn/rrg/chameleon/utils/ChameleonVCUtil.java
+++ b/chameleon/src/main/java/cn/rrg/chameleon/utils/ChameleonVCUtil.java
@@ -369,12 +369,12 @@ public class ChameleonVCUtil {
String cmdStr = ChameleonCMDStr.getCMD4E(ChameleonCMDSet.DETECTION);
try {
//执行命令
- executor.requestChameleon(cmdStr, 1000);
+ executor.requestChameleon(cmdStr);
//接收指定长度的数据
Communication com = executor.getCom();
byte[] buf = new byte[218];
//开始接收!
- com.read(buf, 0, buf.length, 3000);
+ com.getInput().read(buf, 0, buf.length);
//开始进行解密!
new ChameleonDetection(new ChameleonDetection.DecryptCallback() {
@Override
diff --git a/communication/ReadMe.txt b/communication/ReadMe.txt
deleted file mode 100644
index 99e2785f..00000000
--- a/communication/ReadMe.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @author DXL
- * Created by DXL on 2019/8/26.
- */
-
-此模块用于解决底层数据与上层数据的映射传输需求。
-工作原理:
- 利用JNI在Jvm与Native内存中间分配两段大小为1MB的缓冲区,上层读到的数据放在recv缓冲区,
-底层需要读取的数据间接从此缓冲区读取! 底层将需要发送的数据放到send缓冲区,上层从此缓冲区读取数据出来,送到到相关的通信接口!
-
-使用步骤:
- 1、引入module, 设置好需要使用的abi版本!
-
- 2、拷贝module中include文件夹里面的头文件到需要使用映射的目标模块
-
- 3、配置依赖者module的参数传递,在externalNativeBuild -> cmake区域:
- String projectDirString = getRootDir().getPath().replaceAll("\\\\","/")
- arguments "-DPROJECTDIR=${projectDirString}"
-
- 4、在依赖者module中的cmake配置文件里配置so路径,参考:
- #声明变量
- set(DEPENDENT ${PROJECTDIR}/libdependent/src/main/jniLibs/${ANDROID_ABI}/libdependent.so)
-
- #进行最终动态库的链接!
- target_link_libraries(soname ${DEPENDENT} android log)
diff --git a/communication/include/com.h b/communication/include/com.h
deleted file mode 100644
index fd832776..00000000
--- a/communication/include/com.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __NFC_BUS_UART_H__
-# define __NFC_BUS_UART_H__
-
-#include
-#include
-#include
-#include
-#include
-
-// can't use, he always is null!
-typedef void *serial_port;
-
-jint initBuffer(JNIEnv *env, jclass type, jobject send_buffer, jobject recv_buffer);
-
-jint syncLength(JNIEnv *env, jclass type);
-
-jint syncTimeout(JNIEnv *env, jclass type);
-
-int c_open();
-
-int c_close();
-
-int c_flush();
-
-int c_read(uint8_t *pbtRx, const size_t szRx, int timeout);
-
-int c_write(const uint8_t *pbtTx, const size_t szTx, int timeout);
-
-#endif // __NFC_BUS_UART_H__
diff --git a/communication/namespace.txt b/communication/namespace.txt
new file mode 100644
index 00000000..0b7553bb
--- /dev/null
+++ b/communication/namespace.txt
@@ -0,0 +1 @@
+CN.DXL.ComBridgeAdapter.2020_0413
\ No newline at end of file
diff --git a/communication/src/main/java/cn/dxl/com/ComBridgeAdapter.java b/communication/src/main/java/cn/dxl/com/ComBridgeAdapter.java
index d6af7690..e96a6642 100644
--- a/communication/src/main/java/cn/dxl/com/ComBridgeAdapter.java
+++ b/communication/src/main/java/cn/dxl/com/ComBridgeAdapter.java
@@ -1,6 +1,10 @@
package cn.dxl.com;
import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.util.Log;
+
+import com.felhr.utils.HexData;
import java.io.IOException;
import java.io.InputStream;
@@ -13,7 +17,6 @@ import java.io.Serializable;
* 通信控制映射类,直接实现进程间通信!
*/
public final class ComBridgeAdapter implements Serializable {
-
/*
* Warning!!!
* If your implementation does not need to be mapped to the c/c++ (only Java exists), please do not use this tool class!
@@ -24,29 +27,97 @@ public final class ComBridgeAdapter implements Serializable {
// The namespace of the LocalServerSocket
public static final String NAMESPACE = "CN.DXL.ComBridgeAdapter.2020_0413";
+ // The tag of the log.
+ public static final String LOG_TAG = "ComBridgeAdapter";
// 本地套接字服务!
- private static LocalServerSocket serverSocket;
+ private LocalServerSocket serverSocket;
// 单例!
private static ComBridgeAdapter instance;
// 输入流!
- public InputStream mInputStream;
+ private InputStream mInputStream;
// 输出流!
- public OutputStream mOutputStream;
+ private OutputStream mOutputStream;
+ // 是否已经连接!
+ private volatile boolean isHasClient = false;
+ // 暂停转发!
+ private boolean pause = false;
- /*
- * 静态块初始化区域
- */
- static {
- instance = new ComBridgeAdapter();
- try {
- serverSocket = new LocalServerSocket(NAMESPACE);
- } catch (IOException e) {
- e.printStackTrace();
+ // No instantiation is required
+ private ComBridgeAdapter() {
+ synchronized (ComBridgeAdapter.class) {
+ try {
+ serverSocket = new LocalServerSocket(NAMESPACE);
+ new WorkThread().start();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
- // No instantiation is required
- private ComBridgeAdapter() { /*This constructor can't using*/ }
+ /**
+ * Data forward thread!
+ * data will from a InputStream to a OutputStream!
+ */
+ private class WorkThread extends Thread {
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ LocalSocket socket = serverSocket.accept();
+ if (isHasClient) {
+ Log.e(LOG_TAG, "The server only once online supported.");
+ Log.e(LOG_TAG, "please disconnect your previous con.");
+ continue;
+ }
+ new DataThread(mOutputStream, socket.getInputStream()).start();
+ new DataThread(socket.getOutputStream(), mInputStream).start();
+ isHasClient = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ isHasClient = false;
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ isHasClient = false;
+ }
+
+ class DataThread extends Thread {
+ private OutputStream os;
+ private InputStream is;
+
+ DataThread(OutputStream os, InputStream is) throws IOException {
+ this.os = os;
+ this.is = is;
+ }
+
+ @Override
+ public void run() {
+ while (isHasClient) {
+ try {
+ if (pause) {
+ Log.e(LOG_TAG, "暂停中!");
+ continue;
+ }
+ if (os != null && is != null) {
+ Log.d(LOG_TAG, "接收中");
+ byte b = (byte) is.read();
+ os.write(b);
+ os.flush();
+ Log.e(LOG_TAG, "数据: " + HexData.hexToString(new byte[]{b}));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ isHasClient = false;
+ break;
+ }
+ }
+ }
+ }
public static ComBridgeAdapter getInstance() {
return instance;
@@ -56,17 +127,25 @@ public final class ComBridgeAdapter implements Serializable {
return mInputStream;
}
- public void setInputStream(InputStream mInputStream) {
+ public ComBridgeAdapter setInputStream(InputStream mInputStream) {
this.mInputStream = mInputStream;
+ return this;
}
public OutputStream getOutputStream() {
return mOutputStream;
}
- public void setOutputStream(OutputStream mOutputStream) {
+ public ComBridgeAdapter setOutputStream(OutputStream mOutputStream) {
this.mOutputStream = mOutputStream;
+ return this;
}
+ public void pause() {
+ pause = true;
+ }
+ static {
+ instance = new ComBridgeAdapter();
+ }
}
diff --git a/communication/src/main/java/cn/dxl/com/DeviceChecker.java b/communication/src/main/java/cn/dxl/com/DeviceChecker.java
index f6e70b53..4ba6d25e 100644
--- a/communication/src/main/java/cn/dxl/com/DeviceChecker.java
+++ b/communication/src/main/java/cn/dxl/com/DeviceChecker.java
@@ -15,8 +15,14 @@ public abstract class DeviceChecker implements Serializable, Closeable {
public DeviceChecker(Communication communication) {
this.communication = communication;
+ initCom();
+ }
+
+ private void initCom(){
// Auto init communication to mapper.
- ComBridgeAdapter.initCom(communication);
+ ComBridgeAdapter.getInstance()
+ .setInputStream(communication.getInput())
+ .setOutputStream(communication.getOutput());
}
/**
@@ -24,7 +30,10 @@ public abstract class DeviceChecker implements Serializable, Closeable {
*
* @return if can work return true, if no, return false
*/
- public abstract boolean working() throws IOException;
+ public boolean check() throws IOException {
+ initCom();
+ return false;
+ }
/**
* Close the device(Should no close communication. only close device!)
diff --git a/communication/src/main/java/cn/rrg/com/UsbSerialControl.java b/communication/src/main/java/cn/rrg/com/UsbSerialControl.java
index d30035ae..15defcd0 100644
--- a/communication/src/main/java/cn/rrg/com/UsbSerialControl.java
+++ b/communication/src/main/java/cn/rrg/com/UsbSerialControl.java
@@ -163,12 +163,16 @@ public class UsbSerialControl implements DriverInterface {
@Override
public OutputStream getOutput() {
- return mPort.getOutputStream();
+ if (mPort != null)
+ return mPort.getOutputStream();
+ return null;
}
@Override
public InputStream getInput() {
- return mPort.getInputStream();
+ if (mPort != null)
+ return mPort.getInputStream();
+ return null;
}
private boolean init1() {
diff --git a/communication/src/main/java/cn/rrg/devices/EmptyDeivce.java b/communication/src/main/java/cn/rrg/devices/EmptyDeivce.java
index 44e2d6f0..f87ee3c3 100644
--- a/communication/src/main/java/cn/rrg/devices/EmptyDeivce.java
+++ b/communication/src/main/java/cn/rrg/devices/EmptyDeivce.java
@@ -12,7 +12,7 @@ public class EmptyDeivce extends DeviceChecker {
}
@Override
- public boolean working() throws IOException {
+ public boolean check() throws IOException {
return true;
}
diff --git a/libnfc_pn53x/src/main/cpp/libnfc/CMakeLists.txt b/libnfc_pn53x/src/main/cpp/libnfc/CMakeLists.txt
index c3f078dd..b04da78d 100644
--- a/libnfc_pn53x/src/main/cpp/libnfc/CMakeLists.txt
+++ b/libnfc_pn53x/src/main/cpp/libnfc/CMakeLists.txt
@@ -21,8 +21,5 @@ target_include_directories(nfc PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include/
${CMAKE_CURRENT_SOURCE_DIR}/include/nfc/)
-#声明变量
-set(COMMAPPING_FILE ${PROJECTDIR}/communication/src/main/jniLibs/${ANDROID_ABI}/libcommapping.so)
-
#进行最终动态库的链接!
-target_link_libraries(nfc ${COMMAPPING_FILE} android log)
\ No newline at end of file
+target_link_libraries(nfc android log)
\ No newline at end of file
diff --git a/libnfc_pn53x/src/main/cpp/libnfc/drivers/pn53x_usb.c b/libnfc_pn53x/src/main/cpp/libnfc/drivers/pn53x_usb.c
index 4bcc255b..8c8d6374 100644
--- a/libnfc_pn53x/src/main/cpp/libnfc/drivers/pn53x_usb.c
+++ b/libnfc_pn53x/src/main/cpp/libnfc/drivers/pn53x_usb.c
@@ -62,6 +62,18 @@ Thanks to d18c7db and Okko for example code
#define DRIVER_DATA(pnd) ((struct pn53x_usb_data*)(pnd->driver_data))
+// 暂时处理
+
+int c_open(){}
+
+int c_close(){}
+
+int c_flush(){}
+
+int c_read(uint8_t *pbtRx, const size_t szRx, int timeout){}
+
+int c_write(const uint8_t *pbtTx, const size_t szTx, int timeout){}
+
const nfc_modulation_type no_target_support[] = {0};
typedef enum {
diff --git a/libnfc_pn53x/src/main/java/cn/rrg/devices/PN53X.java b/libnfc_pn53x/src/main/java/cn/rrg/devices/PN53X.java
index 96680b55..774da158 100644
--- a/libnfc_pn53x/src/main/java/cn/rrg/devices/PN53X.java
+++ b/libnfc_pn53x/src/main/java/cn/rrg/devices/PN53X.java
@@ -32,7 +32,8 @@ public class PN53X extends DeviceChecker {
}
@Override
- public boolean working() throws IOException {
+ public boolean check() throws IOException {
+ super.check();
return testPN53x(name);
}
diff --git a/pm3flasher/src/main/cpp/CMakeLists.txt b/pm3flasher/src/main/cpp/CMakeLists.txt
index bfb0feda..e71080e8 100644
--- a/pm3flasher/src/main/cpp/CMakeLists.txt
+++ b/pm3flasher/src/main/cpp/CMakeLists.txt
@@ -39,8 +39,5 @@ target_include_directories(pm3_flasher PRIVATE
${PM3_ROOT}/client
${PM3_ROOT}/client/uart)
-#声明变量
-set(COMMAPPING_FILE ${PROJECTDIR}/communication/src/main/jniLibs/${ANDROID_ABI}/libcommapping.so)
-
#添加动态库链接!
-target_link_libraries(pm3_flasher ${COMMAPPING_FILE} android log z)
\ No newline at end of file
+target_link_libraries(pm3_flasher android log z)
\ No newline at end of file
diff --git a/pm3flasher/src/main/cpp/client/uart/uart_posix.c b/pm3flasher/src/main/cpp/client/uart/uart_posix.c
index bbc78634..177c41e0 100644
--- a/pm3flasher/src/main/cpp/client/uart/uart_posix.c
+++ b/pm3flasher/src/main/cpp/client/uart/uart_posix.c
@@ -561,6 +561,18 @@ int uart_reconfigure_timeouts(uint32_t value) {
return PM3_SUCCESS;
}
+// 暂时处理
+
+int c_open(){}
+
+int c_close(){}
+
+int c_flush(){}
+
+int c_read(uint8_t *pbtRx, const size_t szRx, int timeout){}
+
+int c_write(const uint8_t *pbtTx, const size_t szTx, int timeout){}
+
serial_port uart_open(const char *pcPortName, uint32_t speed) {
serial_port_unix *sp = malloc(sizeof(serial_port_unix));
if (sp == 0) return INVALID_SERIAL_PORT;
diff --git a/pm3rdv4rrg/build.gradle b/pm3rdv4rrg/build.gradle
index 356fe9e4..ee2ca9b4 100644
--- a/pm3rdv4rrg/build.gradle
+++ b/pm3rdv4rrg/build.gradle
@@ -12,8 +12,7 @@ android {
externalNativeBuild {
cmake {
- String projectDirString = getRootDir().getPath().replaceAll("\\\\", "/")
- arguments '-DANDROID_STL=c++_static', "-DPROJECTDIR=${projectDirString}"
+ arguments '-DANDROID_STL=c++_static'
abiFilters "x86", "x86_64", "armeabi-v7a", "arm64-v8a"
}
}
@@ -25,7 +24,7 @@ android {
externalNativeBuild {
cmake {
version '3.10.2'
- path 'src/main/cpp/CMakeLists.txt'
+ path 'src/main/cpp/proxmark3/client/android/CMakeLists.txt'
}
}
diff --git a/pm3rdv4rrg/src/main/cpp/.coverity.conf.sample b/pm3rdv4rrg/src/main/cpp/.coverity.conf.sample
deleted file mode 100644
index 5caf5d6f..00000000
--- a/pm3rdv4rrg/src/main/cpp/.coverity.conf.sample
+++ /dev/null
@@ -1,40 +0,0 @@
-COVLOGIN=myemail@corp.com
-COVTOKEN=aAbBcCdDeEfFgGhHiIjJkK
-# Toolchain available at https://scan.coverity.com/download
-COVBINDIR="/opt/cov-analysis-linux64-2019.03/bin"
-# Nickname included in scan description:
-NICKNAME=myself
-# cov can't read gcov from gcc > 7
-HOSTCC=gcc-7
-HOSTCXX=g++-7
-HOSTLD=g++-7
-
-# Do not change it:
-COVDIR=cov-int
-
-# Depending if your kernel > 4.8.x, you might need to activate this to run Coverity executables
-# (but latest tools with kernel 5.2 run fine)
-#sysctl vsyscall=emulate
-
-export PATH="$PATH:$COVBINDIR"
-
-function pre_build_hook() {
- # tmp dir will be /tmp/cov-$username/
- # It's the good place if you need to redirect to elsewhere with a symlink
- return 0
-}
-
-function post_build_hook() {
- return 0
-}
-
-function pre_submit_hook() {
- return 0
-}
-
-function post_submit_hook() {
- # Clean up build folders?
- rm -rf "$COVDIR"
- echo "Coverity build cleaned"
- return 0
-}
diff --git a/pm3rdv4rrg/src/main/cpp/.gitattributes b/pm3rdv4rrg/src/main/cpp/.gitattributes
deleted file mode 100644
index c695ce49..00000000
--- a/pm3rdv4rrg/src/main/cpp/.gitattributes
+++ /dev/null
@@ -1,16 +0,0 @@
-# .gitattributes
-
-# prevent binary files from CRLF handling, diff and merge:
-fpga/fpga.bit -crlf -diff
-*.bin -crlf -diff
-*.z -crlf -diff
-
-# Force LF
-*.c text=auto eol=lf
-*.cpp text=auto eol=lf
-*.h text=auto eol=lf
-*.lua text=auto eol=lf
-*.py text=auto eol=lf
-*.pl text=auto eol=lf
-*.dic text=auto eol=lf
-Makefile text=auto eol=lf
diff --git a/pm3rdv4rrg/src/main/cpp/.gitignore b/pm3rdv4rrg/src/main/cpp/.gitignore
deleted file mode 100644
index 092ad961..00000000
--- a/pm3rdv4rrg/src/main/cpp/.gitignore
+++ /dev/null
@@ -1,83 +0,0 @@
-# .gitignore
-# don't push these files to the repository
-
-.history
-.bash_history
-.bash_profile
-.bash_logout
-.bashrc
-.inputrc
-.profile
-*.log
-*.eml
-*.o
-*.a
-*.d
-*.elf
-*.s19
-*.map
-*.bin
-*.dll
-*.moc.cpp
-*.z
-*.Td
-*.DS_Store
-*.exe
-*.dsym
-version.c
-*.json
-*.old
-*.swp
-
-# new build file for add-ons.
-Makefile.platform
-# Cache for detecting platform def changes
-.Makefile.options.cache
-
-!client/hardnested/*.bin
-!client/hardnested/tables/*.z
-client/ui/ui_overlays.h
-client/reveng/bmptst
-
-hardnested_stats.txt
-proxmark3
-proxmark3-flasher
-flasher
-!flasher/
-lua
-luac
-fpga_compress
-mfkey32
-mfkey64
-tools/nonce2key/nonce2key
-
-fpga/*
-!fpga/tests
-!fpga/fpga_lf.bit
-!fpga/fpga_hf.bit
-!fpga/*.v
-!fpga/Makefile
-!fpga/fpga.ucf
-!fpga/xst_lf.scr
-!fpga/xst_hf.scr
-!fpga/go.bat
-!fpga/sim.tcl
-
-#client/*
-# my own traces folder
-client/traces/*
-*.ice
-*.new
-armsrc/TEMP EMV/*
-tools/mf_nonce_brute/*
-tools/andrew/*
-tools/jtag_openocd/openocd_configuration
-ppls patches/*
-*- Copy.*
-
-client/lualibs/mfc_default_keys.lua
-client/lualibs/pm3_cmd.lua
-# recompiled
-fpga_version_info.c
-
-.proxmark3/*
diff --git a/pm3rdv4rrg/src/main/cpp/.travis.yml b/pm3rdv4rrg/src/main/cpp/.travis.yml
deleted file mode 100644
index 1cb60f8e..00000000
--- a/pm3rdv4rrg/src/main/cpp/.travis.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-# Travis-CI Build for RfidResearchGroup/Proxmark3
-language: c
-
-#default linux build env is: xenial
-compiler: gcc
-
-# move some env variables to homebrew env
-env:
- global:
- - HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH
- - HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT
-
-# Test on Linux and MacOS
-matrix:
- include:
- - os: osx
- osx_image: xcode11
- env: MAKE_PARAMS='PLATFORM_EXTRAS='
- - os: osx
- osx_image: xcode11
- env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
- - os: linux
- dist: xenial
- sudo: required
- env: MAKE_PARAMS='PLATFORM_EXTRAS='
- - os: linux
- dist: xenial
- sudo: required
- env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
-
-addons:
- apt:
- packages:
- - gcc-arm-none-eabi
- - libnewlib-dev
- - libsndfile1-dev
- homebrew:
- packages:
- - readline
- - libsndfile
- - qt5
- - RfidResearchGroup/proxmark3/arm-none-eabi-gcc
- taps: RfidResearchGroup/proxmark3
-
-install:
- if ! arm-none-eabi-gcc -v; then
- echo "arm-none-eabi-gcc [ERROR]";
- travis_terminate 1;
- fi
-
- make clean;
- make all V=1 "$MAKE_PARAMS";
-
-script:
-## start and run a test script
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
- ./pm3test.sh;
- elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
- ./pm3test.sh;
- fi
diff --git a/pm3rdv4rrg/src/main/cpp/CHANGELOG.md b/pm3rdv4rrg/src/main/cpp/CHANGELOG.md
deleted file mode 100644
index 8a36b58d..00000000
--- a/pm3rdv4rrg/src/main/cpp/CHANGELOG.md
+++ /dev/null
@@ -1,702 +0,0 @@
-# Change Log
-All notable changes to this project will be documented in this file.
-This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
-
-## [unreleased][unreleased]
- - Added `hf lto restore` - restore LTO cartridge memory from dump file [.bin|.eml] (@Kevin-Nakamoto)
- - Added `LF_ICEHID` standalone mode which searches for lf HID credentials and store to RDV4 flashmem (@iceman1001)
- - Added `HF_14ASNIFF` standalone mode with storing trace to RDV4 flashmem (@micolous)
- - Added `hf lto dump` - dump 8160 bytes of data from LTO cartridge memory and save to file (@Kevin-Nakamoto)
- - Change `data plot` - write serial port name in window title for plot / slider window (@iceman1001)
- - Added `hf lto wrbl` - write block support for LTO Cartridge memory (@Kevin-Nakamoto)
- - Fix compilation under openSUSE (@hsanjuan)
- - Added `lf nexwatch sim` - use raw hex to simulate (@iceman1001)
- - Fix `lf indala read` - long id 224bits preamble identification less strict (@iceman1001)
- - Added `hf mf staticnested` - useful when targeting the strange cards with a static nonce. (@iceman100) Thanks to @xtigmh @uzlonewolf for their solutions.
- - Added `hf plot` (@pwpiwi)
- - Fix `lf config` - when called with no params, it no longer mess up all device lf config settings. (@iceman1001)
- - Change `lf indala clone` - new option `--Q5` writes to q5/T5555 tags. (@iceman1001)
- - Change `lf indala clone` - new option `-c ` allows cloning INDALA tag from Heden2L/Hedengren ID format (@iceman1001) - Thanks to @randomdude42 for solution
- - Change `lf indala demod` - added decode Heden2L/Hedengren format (@iceman1001) - Thanks to @randomdude42 for solution
- - Added `commands.md` - document with all proxmark client commands. Generated with XX_internal_command_dump_markdown_XX. (@iceman1001)
- - Change `lf pac clone` - new option `c ` to allow cloning PAC/Stanley tag from card ID (@danshuk)
- - Change `lf pac read` - decoded PAC/Stanley card ID (@danshuk)
- - Change mifare classic keytable output refactored and uses colors (@iceman1001)
- - Fix `hf mf nested` - now writes the correct blockno (@iceman1001)
- - Change `lf t55xx dump` - now supports saving to JSON (@iceman1001)
- - Change `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi)
- - Change `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001)
- - Change `hf mf csave` - now uses UID in filename (@iceman1001)
- - Fix `hf mf chk` - read block B logical error. #489 (@iceman1001)
- - Added `hf mf ekeyprn d` - new parameter to save keys to file (@iceman1001)
- - Added `mfu_magic.lua` - script to interact with your magic NTAG tag. (@iceman1001)
- - Added `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld)
- - Added `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk)
- - Added `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk)
- - Change `hf 14a info` - now detects "static / fixed" nonce tags (@iceman1001)
- - Change `data save f w` - params reworked. (@iceman1001)
- - Change `hf search` - now should detect LTO-CM tags (@iceman1001)
- - Added `hf lto info` - skeleton support for LTO Cartridge memory (@iceman1001)
- - Added saving as wave format (@anon)
- - Added ISO15_WRITE annotation (@pwipiw)
- - Added `lto_dump.lua` @kevin
- - Added `hf mf cwipe` magic chinese card (gen1a) wipe to default state (@merlokk)
- - Added `pm3_mf7b_wipe.py` python script. Wipes magic S70 7B Gen2 card. (@vulnersCom)
- - Added `hf mfp chk` Mifare plus command for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk)
- - Change `hf 15` - some refactoring (@grspy)
- - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy)
- - Added detailed info for SLIX2 tags in `hf 15 info` (@grspy)
- - Fix `hf list felica` and `hf felica sniff` (@7homasSutter)
- - Added `hf felica wrunencrypted` (@7homasSutter)
- - Added `hf felica rdunencrypted` (@7homasSutter)
- - Added `hf felica rqresponse` (@7homasSutter)
- - Added `hf felica rqservice` (@7homasSutter)
- - Added polling for felica standard (@7homasSutter)
- - Added `lf t55xx dump save` and `lf t55xx restore` for .bin and .eml files (@mwalker33)
- - Added `lf t55xx detected` to try without password first (@mwalker33)
- - Change `lf indala read` - added indala 26bit decoding (@martinbeier)
- - Change `lf t55xx detect` to try without password first (@mwalker33)
- - Display high bit for detected Kastle HIDs to allow `lf hid clone [id]` to work properly (@swg0101)
- - Added option `-n` to scripts pm3* (@doegox)
- - Added `wiegand list/encode/decode` - wiegand format manipulation. Adapted to fit here. (@grauerfuchs)
- - Added support for color text on windows 10 (@mwalker33)
- - Added `s` to `lf config` / `lf sniff` to skip samples when sniffing based on same option in Proxmark/proxmark3 by @marshmellow42. (@mwalker33)
- - Added save to .eml and .bin for `em 4x05_dump` (@mwalker33)
- - Added option `-n` to scripts pm3* (@doegox)
- - Fix `em 4x05_dump` to print all blocks read (@mwalker33)
- - Fix T55xx config getting displayed when using password when no password needed on read. (@mwalker33)
- - Added T55x7 downlink mode auto usage via mode detected (lf t55 detect) (@mwalker33)
- - Added `lf t55xx protect` - sets password and enables password protection on t55x7 tag (@iceman1001)
- - Change `lf t55xx wipe` - now accepts user provided configuration block (@iceman1001)
- - Added T55x7 downlink mode support r 0 Default, 1 Long Leading 0, 2 Leading 0, 3 1 of 4 and 4 (in some commands) try all. (@mwalker33)
- - Change proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox)
- - Change `hf iclass clone\dump\rdbl\wrbl` - now uses NG (@iceman1001)
- - Fix `hf iclass clone` - last block always fails (@iceman1001)
- - Change `hf iclass clone` - retries ten times, less output (honor verbose) (@iceman1001)
- - Change `hf iclass dump` - retries ten times, less output (honor verbose) (@iceman1001)
- - Rename `hf iclass writeblk` -> `hf iclass wrbl` to match hf mf wrbl (@iceman1001)
- - Rename `hf iclass readblk` -> `hf iclass rdbl` to match hf mf rdbl (@iceman1001)
- - Added cmdscript example and show usage with shebang (@doegox)
- - Added instructions for Fedora (@doegox)
- - Change reduce the list of requirements to the minimum and move to QT5 (@doegox)
- - Added `make install` and reorganize/rename stuffs accordingly (@doegox)
- - Added searchFile for several types of files (@doegox / @iceman1001)
- - Change posix sh version of mkversion (@doegox)
- - Change remove entirely ncurses, not needed nowadays (@doegox)
- - Change remove deprecated termcap, use ncurses instead (@ZeroChaos-)
- - Change `hf iclass encrypt` - now takes transport key as param. (@iceman1001)
- - Change `hf iclass decrypt` - now takes transport key as param. (@iceman1001)
- - Change `hf mf fchk m` - now secretly dumps card to emul, if all keys are found (@iceman1001)
- - Change history and logfile are now saved into $HOME/.proxmark3/ (@doegox)
- - Change optimization of iclass mac calculations on deviceside (@pwpiwi)
- - Added `hf mf autopwn` - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath)
- - Added Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox)
- - Change Lua directory scripts/ to luascript/ (@doegox)
- - Change non-rdv4 PLATFORM must now use the generic PM3OTHER, simpler (@doegox)
- - Fix reveng integration for all platforms else than WIN32 (@doegox)
- - Added cheat sheet for easy operations of the Proxmark3 (scund00r)
- - Chg commands are now in green in the helptext list (@iceman1001)
- - Fix `script run ndefdump` - better exit messages when failing (@iceman1001)
- - Fix `hf iclass dump` - now also saves in EML format (@iceman1001)
- - Fix `hf iclass sim 3` - now works on legacy readers and legacy SE readers (@iceman1001)
- - Rework hitag2 read/write help (@ViRb3)
- - Added `lf nedap` - encoding / decoding (anon)
- - Added client option `-i` to stay in interactive mode after a script or command (@DidierStevens/@doegox)
- - Added VSCode tasks (@ViRb3)
- - Better warn user of hardcoded hitag info (@ViRb3)
- - Format and docs hitag (@ViRb3)
- - Fix hitag password write offset by 1 (@ViRb3)
- - Fix momentarily flash read/write of dicts (@doegox/@cjbrigato)
- - Added some more default keys (@anon)
- - Added `hf thinfilm sim` simulating Thinfilm NFC barcode tags (@doegox)
- - Added `hf thinfilm list` specific trace decoding (Thinfilm NFC barcode tags) (@doegox)
- - Fix `hf topaz reader` - don't crash when trying to read a Thinfilm tag (@iceman1001)
- - Added `hf thinfilm info` - read / decode Kovio Thinfilm NFC barcode tags (@iceman1001)
- - Added FPGA LF adc path (@anon)
- - Added ECC support / check for NID_secp128r1 (@pwpiwi)
- - Added some more default keys (ollibolli)
- - Fix T55x7 Downlink timings backward compatible (@mwalker33)
- - Added proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox)
- - Added T55x7 Downlink mode support (@mwalker33)
- - Added SPIFFS Flash filesystem support (@cjbrigato)
- - Fix support for flashing 512K units with old bootrom (@slurdge/@doegox)
- - Fix `hf mf sim` - wrong access rights to write key B in trailer (@McEloff)
- - Added option -i to flasher to query Pm3 for its memory size (@doegox)
- - Added support for flashing 512K units (@slurdge)
- - Added a simple python tool to check the elf sizes (@slurdge)
- - Change: new keys for Vigik badges in default_keys.dict (@luminouw)
- - Added `hw standalone` to jump to standalone mode from command line or script (@doegox)
- - Added to `hf 14a apdu` print apdu and compose apdu (@merlokk)
- - Change: buggy `mem read` removed, `mem save` renamed `mem dump`, can now display too (@doegox)
- - Fix: timeout for mem wipe was too short, thanks @cjbrigato (@doegox)
- - Fix `hf mf sim` - Mifare Classic simulation more flexible anti-collision check (@McEloff)
- - Change: `hf mf sim` - Mifare Classic simulation not respond NACK on invalid authentication request (@McEloff)
- - Change: `read_pwd_mem.lua` now handles Mifare Classic dictionaries large than 4096 bytes (@iceman1001)
- - Change: Do not clear trace log during `hf mf chk`, to save whole process history (@McEloff)
- - Added `msleep` command, for pauses in scripts (@doegox)
- - Added support for WSL in proxmark.sh (@doegox)
- - Added documentation for usage of Proxmark3 under WSL (@doegox)
- - Change: replace aes.c with mbedtls version (@slurdge)
- - Change: replace ukbhit by kbd_enter_pressed, not requiring tcgetattr (@xianglin1998/@doegox)
- - Added config for RaspberryPi in JTAG tools (@doegox)
- - Added config for FTDI C232HM-DDHSL-0 in JTAG tools (@doegox)
- - Fix compilation under MacOSX with binutils (@matrix)
- - Added dynamic report of the chipID for flashing purposes (@slurdge)
- - Fix Clang warnings (@matrix)
- - Fix EMVGPO bug (@matrix)
- - Added hitag2 write password auth (@ViRb3)
- - Added check if bootloader segment is within bounds (@slurdge)
- - Added `hf 15 csetuid` - set UID on ISO-15693 Magic tags (@t0m4-null)
- - Change: Print help if unknown arg for hitag reader/writer (@ViRb3)
- - Fix clock deadlock in hitag sniff (@ViRb3)
- - Added compiler info in client & ARM sections (@slurdge)
- - Added support for automatic COM detection on Windows (@slurdge)
- - Added support for compilation on RaspberryPiZero (armv6) (@doegox)
- - Change: updates to README (@iceman1001)
- - Change: `hf mf/mfu dbg` => `hw dbg` (@doegox)
- - Change: replace usb_poll_validate_length() by data_available() that supports USART too (@doegox)
- - Make sure standalone modes can be launched when connected on USB without client (@doegox)
- - Change: cleaner makefile execution, use `make V=1` if you want to see full lines (@doegox)
- - Change: automate make clean when platform definitions are changed (@doegox)
- - Added STANDALONE option to Makefile.hal (@Fl0-0)
- - Change: mem info - production public key to verify rdv4.0 flash signature (@iceman1001)
- - Fix specify that we need TCP and not UDP connection (@phcoder)
- - Change: lf cotag demod - adjusted error trigger (@iceman1001)
- - Added documentation on BT add-on (@iceman1001/@doegox)
- - Change: new button behaviour in bootloader mode, no need to keep it pressed, press again to interrupt (@doegox)
- - Change: new keys in dicts, new mem layout to accomodate them (@iceman1001/various)
- - Fix lf sim - if called with empty graphbuffer all strange things happend, like turning on HF field (@iceman1001)
- - Change: hf 14a sim / hf mf sim - check buttonpress/usb frame fewer times in order not to disrupt simulation (@McEloff)
- - Change: data convertbitstream - converts bit to max/min in order to facilitate demodulation of simulation data (@iceman1001)
- - Change: lf em 410x_demod - now can demod the simulation data (@iceman1001)
- - Added HC-06 scripts for BT add-on (@doegox)
- - Fix lf nedap sim - error when adding parity (@iceman1001)
- - Added documentation on UART and baudrates (@doegox/@iceman1001)
- - Change: prompt now shows which channel is used (@iceman1001)
- - Change: USART baudrates computation, up to 6Mbps (@iceman1001/@doegox)
- - Change: hf mf nack - keep sync if started without card over antenna
- - Added usart btfactory - to reset a misconfigured BT add-on (@doegox)
- - Change: hw status - now prints number of dictionary keys loaded (@iceman1001)
- - Added home, end, pageup, and pagedown keybinds to the plot GUI. Also fix paged movement in GUI. (@mcd1992)
- - Change legic.lua saves data in EML and BIN formats (@iceman1001)
- - Change hf tune - is now synchronous (for BT add-on) and can be interrupted by kbd (@doegox)
- - Change: update macOS install instruction (@ Uli Heilmeier)
- - Added trace ouput in hexdump format for Wireshark import (@ Uli Heilmeier)
- - Added usart btpin - to change BT add-on PIN (@doegox)
- - Added reconnection support (@iceman1001/@doegox)
- - Added usart tx/rx/... - USART developer commands (@doegox)
- - Added PLATFORM_EXTRAS, WITH_FPC_USART_HOST, BTADDON Makefile configuration (@doegox)
- - Fix slow reconfigure on mingw of serial port (@iceman1001)
- - Fix cross thread communictions of timeout variable (@iceman1001)
- - Change: client is now "universal", adapting to Proxmark3 capabilities (@doegox)
- - Added disconnect support to Lua (@iceman1001)
- - Change: handles FPC/FLASH FW more gracefully on non-RDV4 pm3 (@doegox)
- - Added JTAG support for Shikra (@NinjaStyle82)
- - Change: smart color handling: only if linux and on real term (@doegox)
- - Change: reconfigure uart timeouts when compiled for FPC and connecting over USB (@iceman1001)
- - Change: fast push for many commands (@iceman1001/@doegox)
- - Added: fast push for Lua (@iceman1001)
- - Added NDEF parser in Lua (@iceman1001)
- - Change: improve NDEF parser (@iceman1001)
- - Change: all commands got migrated to MIX/NG packet format (@iceman1001/@doegox)
- - Fix: Mifare Ultralight read block missing bytes (@doegox)
- - Added support new frame format in all Lua scripts (@iceman1001)
- - Added CMD_CAPABILITIES for pm3 to inform dynamically the client (@doegox)
- - Change baudrate handling, make it clear it is only indicative for USB-CDC & BT (@doegox)
- - Change: new progressive light scheme for `hw detectreader` (@doegox)
- - Added common error definitions system for retvals (@doegox)
- - Change USART RX & TX code and fix delays handling to make it more robust, especially over BT (@doegox)
- - Added support for new frames format, speedup & huge changes, see doc/new_frame_format.txt (@doegox)
- - Change: loadFile* & saveFile* accept filenames with (or still without) extension (@doegox)
- - Fix LoadEML to accept final "\n", e.g. from pm3_mfd2eml.py (@doegox)
- - Change: rework shell scripts for easy client or flasher (@doegox)
- - Fix: stop poking Internet when compiling (@doegox)
- - Added support for multiple commands to "-c", e.g. proxmark3 -c "hw ping;hw version" (@doegox)
- - Fix external flash writing bitflips issues at 24MHz (@doegox)
- - Added color support to Dbprintf & alike and rework Dbprintf flags (@doegox)
- - Change: archive (and fix) hid-flasher (@doegox)
- - Added standalone placeholder to simplify new standalone integration (@doegox)
- - Change: refactor standalone mode info string (@iceman1001)
- - Added iceman skeleton standalone mode for ppl to use as base for their new modes (@iceman1001)
- - Change: move compilation options to Makefile.hal (@doegox)
- - Fix compilation under OSX (@iceman1001)
- - Added openocd config files for JLink (@doegox)
- - Fix compilation dependencies for recovery (@doegox)
- - Fix segfault when loading a file (@doegox)
- - Change/Add new dump format for Ultralight/NTAG, counters support, simulation (@mceloff)
- - Added `hf mf sim` full-byte split anticollision support (@mceloff)
- - Fix/Add `hf mf sim` bugs fix, RATS support, etc (@mceloff)
- - Fix serial of FPC. (@ryan)
- - Fix `data shiftgraphzero` corrupting end of GraphBuffer (@doegox)
- - Fix `hf legic info` - unsegmented card now uses card size to calc remaining length (@iceman1001)
- - Added 36bit HID format, extend calcWiegand() to include oem bits (@davidbeauchamp)
- - Fix `hf mf hardnested` - not verify key when reading nonce file (@iceman1001)
- - Change optimizations for ask/bi (@iceman1001)
- - Fix `hf mf sim` - bugs fix, refactoring (@mceloff)
- - Added WRITE and COMPATIBLE_WRITE support to Mifare Ultralight/NTAG simulation (@mceloff)
- - Change installation instructions and add video links (@5w0rdfish)
- - Change `hf mf sim` to support more types (@vratiskol)
- - Change better strong wave detection for biphase (@iceman1001)
- - Added `script run test_t55x7` (@iceman1001)
- - Added new lua scripting support for some t55xx commands (@iceman1001)
- - Added FPC USART for BT add-on with pm3 client. (@doegox)
- - Added `-b baudrate` option to the pm3 client. (@doegox)
- - Change `lf t55xx info`: tell if known configuration block0. (@iceman1001)
- - Fix/Add FPC usart: fix TX, bring RX, full speed. (@doegox)
- - Change `lf t55xx config` options: allow to toggle on/off i/q5/st
- - Change `lf t55xx info`: support offline block0, Q5, fix extended, add warns. (@doegox)
- - Avoid race condition when flasher finds the not yet closed pm3 port. (@doegox)
- - Fix `lf t55xx trace`: read the proper block. (@doegox)
- - Fix Indala 64 on T55xx: use PSK1. (@doegox)
- - Force proper Linefeed (LF) handling in ProxSpace. (@vratiskol)
- - Fix Makefiles race conditions to allow parallel compilation, e.g. `make -j8`. (@doegox)
- - Added - dictionary key file for MFU. (not in use at the moment) (@mazodude)
- - Change `lf fdx demod` - better biphase maxerrors. (@MalteHillmann)
- - Change `hf mf sim` - now works better against android (@mceloff)
- - Fix `lf t55xx brute` - now works after aquiredata adaptations (@iceman1001)
- - Fix `lf t55xx chk` - now works after aquiredata adaptations (@iceman1001)
- - Fix `lf t55xx recoverpwd` - now works after aquiredata adaptations (@iceman1001)
- - Fix `data detect p` - reverted bad clock detection (@iceman1001)
- - Change `data detect a` - better clock detection (@iceman1001)
- - Added `hf 14a info` - now detects some magic card Gen2 (@iceman1001)
- - Removed `LCD` code in armsrc compilation (@iceman1001)
- - Change - Generic fixes of codestyle (@doegox) (@iceman1001)
- - Change `lf indala demod` - refactoring (@iceman1001)
- - Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox)
- - Change - printing of fault bit markers (7) using a dot (@doegox)
- - Change `sc upgrade` - firmware file integrity check (@pwpiwi)
- - Fix `data rawdemod am` - last bit was missing (@doegox)
- - Fix `hf 15 dump f` - also selects tag first (@iceman1001)
- - Fix `hf iclass clone` - missing fileclose (@iceman1001)
- - Added `trace list hitag` - old hitag annotations now use the new trace (@iceman1001)
- - Change `lf hitag sim` - loads bin/eml/json (@iceman1001)
- - Change `lf hitag reader 21` - saves in bin/eml/json (@iceman1001)
- - Change `lf hitag` - refactoring (@iceman1001)
- - Change `lf hitag` - refactoring (@pwpiwi)
- - Fix `lf hitag` - generic fix for missing clock init (@pwpiwi)
- - Fix fsk sim operations on deviceside - avoid division by zero (@doegox)
- - Fix `hf mf fchk` - condition always false (@doegox)
- - Fix `lf t55xx recoverpw` - shift as u32 (@doegox)
- - Fix `lf ti demod` - shift as u32 (@doegox)
- - Fix `lf ti read` - shift as u32 (@doegox)
- - Fix `lf t55xx chk` - condition always false (@doegox)
- - Change `lf sim` - ledcontrol refactoring (@doegox)
- - Fix `hf mf nack` - signedness bug (@doegox)
- - Fix `hf epa cnonce` - check return value (@doegox)
- - Fix `lf hitag write` - condition always true (@doegox)
- - Fix `mem write` - added extra check (@doegox)
- - Fix `iso15693` - bad string cpy (@doegox)
- - Fix `make style` - EOF LF support (@doegox)
- - Added `hf 14b raw` - added -t for timeout (@iceman1001)
- - Rename `lf hitag snoop` - renamed to `lf hitag sniff` (@iceman1001)
- - Rename `lf snoop` - renamed to `lf sniff` (@iceman1001)
- - Rename `hf snoop` - renamed to `hf sniff` (@iceman1001)
- - Fix `hf mfp wrbl` - more blocks available (@merlokk)
- - Added `make platform` - compile for non-rdv4 devices made simpler (@doegox)
- - Change Makefiles optimizations when recompiling (@doegox)
- - Fix `data load` - loads TITEST.txt again (@iceman1001)
- - Change `lf search` - now detects TI (@iceman1001)
- - Change fixing signal cleaning for LF (@doegox)
- - Fix `lf paradox demod` - wrong check (@iceman1001)
- - Change `lf t55xx` - aquiredata uses getsamples (@iceman1001)
- - Fix `lf search` - chipset detection restore demod buffer again (@iceman1001)
- - Added `make style` (@doegox)
- - Fix mixed tabs vs spaces. Now only use 4 space as tab. (@doegox)
- - Fix `lf visa2000 read` - too few samples (@iceman1001)
- - Fix `lf t55xx bruteforce` - infinity loop (@doegox)
- - Fix `analyse nuid` - correct crc (@doegox)
- - Added command history not repeating logged commands (@doegox)
- - Fix path for aidjson (@doegox)
- - Fix missing init i2x (@doegox)
- - Fix `14b select card` - (@doegox)
- - Added `hf mf ndef` - parsing of NDEF messages (@merlokk)
- - Added `hf mf mad` - parsing of Mifare Application Directory (@merlokk)
- - Rename `lf snoop` -> `lf sniff` (@iceman1001)
- - Rename `hf snoop` -> `hf sniff` (@iceman1001)
- - Change generally added more colors (@iceman1001)
- - Change `sc upgrade` updated firmware v3.11 (RDV40) (@sentiprox)
- - Change `data autocorrelate` - better visual representation and added extra peak detection (@iceman1001)
- - Fix `lf search` - false positive indala identification fixed (@iceman1001)
- - Added `lf keri` - basic support for Keri tags (@iceman1001)
- - Added `hf mf list` - re-added it again (@iceman1001)
- - Fix - A lot of bugfixes, like memory leaks (@iceman1001)
- - Change `hf 14a antifuzz` - original implementation (@asfabw), reworked a bit
- - Fix `hf mf fchk` (@iceman1001)
- - Fix `usb slow on posix based systems` (@fl0-0)
- - Change `lf pcf7931` - improved read code (@sguerrini97)
- - Change `hf felica list` - started with some FeliCa annotations (@iceman1001)
- - Fix `hf tune` - now works as expected (@iceman1001)
- - Added `option to use flash memory to upload dictionary files` (RDV40) (@iceman1001)
- - Fix `printing percentage now standard compliant` (@fabled)
- - Added `emv roca` - command to test for ROCA vuln in public RSA modulus (@merlokk / @iceman1001)
- - Added TCP ports support (on linux) (@phcoder)
- - Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton)
- - Fix `Lining up plot and control window` (@anticat)
- - Fix `annoying focus behaviour` on OSX (@Anticat)
- - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (@AntiCat)
- - Added `sc brute` - a naive SFI bruteforcer for contact smartcards (RDV40) (@iceman1001)
- - Change `lf t55xx detectconfig` - now optional to persist settings to flashmem (RDV40) (@iceman1001)
- - Change `hf mf csave` - now saves both EML/BIN formats (@iceman1001)
- - Change `hf mf esave` - now saves both EML/BIN formats (@iceman1001)
- - Fix `compiler warning on macos and gcc7.1 or higher` (@TomHarkness)
- - Fix `crash on Bionic libc if CloseProxmark is called twice` (@micolous)
- - Change `lf hid` - got an updated to Kastle format (@xilni)
- - Added `lf t55xx deviceconfig` - enables custom t55xx timing settings. (RDV40) (@iceman1001)
- - Chg adaptations for FPC communications (work in progress) (@iceman1001)
- - Fix `stand-alone Colin` - remake to benefit from flashmem for persistence. (@cjbrigato)
- - Fix `LEGIC SIM` - remake of legic sim (@drandreas)
- - Changed `proxmark3 client threading` - remake from official repo (@micolous)
- - Added `rem` - new command that adds a line to the log file (@didierStevens)
- - Fix `EM410xdemod empty tag id in lfops.c` (@Defensor7)
- - Fix `usb device descriptor` - some android phones will enumerate better when iSerialnumber is not a multiple of 8 (@micolous, @megabug)
- - Fix `StandaloneMode LF` - when collecting signal, justNoise detection is needed (@didierStevens, @Megabug)
- - Fix `StandAloneMode Colin` - mifare1ksim called with right params (@cjbrigato)
- - Improved `install.sh` to install dependencies for Ubuntu 18.04 and using max number of processors during compilation (@joanbono)
- - Modified `install.sh` script to work in macOS and Linux + added the `update.sh` and `proxmark3.sh` from joanbono (@TomHarkness)
- - Fix `hf emv` - some cards need to have Le=0x00, some do not need to have (@merlokk)
- - Fix `hf legic` enhancement of rx / tx in legic commands (@drandreas)
- - Fix `data buffclear` - now frees bigbuff also (@iceman1001)
- - Fix GET_TICKS and signess while shifting (@drandreas)
- - Added `hf 14b dump` - now dumps to file (bin & eml) (@iceman1001)
- - Fix fixed xcorrelation for strong signal (@drandreas)
- - Fix `hf mf chk` - keytype was reversed (@TomHarkness)
- - Added strange vid/pid found in wild. Could be pm3 easy clones. (@iceman1001)
- - Fix `make udev` - udev filename could be in conflict, renamed. (@blshkv)
- - Fix `lf t55xx config` - wrong sized array disabled FSK1a/FSK2a as options (@grauerfuchs)
- - Added more default keys (@j8048188) (@iceman1001)
- - Added `sc list/info/raw/reader/upgrade` - (RDV40) smart card module functionality (@iceman1001)
- - Fix `download eml buffer` (@drandreas)
- - Changed `exclusion of floatingpoint lib` (@pwpiwi)
- - Changed `lua scripts bit32 calls` (@iceman1001)
- - Changed `hw version` (@pwpiwi), adapted to iceman fork (@iceman1001)
- - Added `amiibo functionality` (@jamchamb), adapted to iceman fork (@iceman1001)
- - Fix `hf legic` (RDV40) adaptations to FPGA HF enhanched reading distance (@iceman1001) Thanks to @drandreas!
- - Added `script run mifare_acces` - script to decode Mifare classic accessbits (@Neuromancer)
- - Added `mem load/save/wipe` - commands to upload / download to new RDV40 onboard flashmemory (@iceman1001)
- - Added `script run mifareplus` - script to communicate with a mifare plus tag (@dceliano)
- - Added FlashMemory functionality (RDV40) (@willok)
- - Fix `hf mfu dump` - partial reads lead to corrupt data (Thanks @elafargue for pointing it out)
- - Changed `hf mfu dump / read` - now retries five times. (@jamchamb)
- - Added `hf list mf` - deciphers crypto1 stream and works with first authentication and weak nested authentications (@Merlok)
- - Adjusted `lf cmdread` to respond to client when complete and the client will then automatically call `data samples` (@marshmellow42)
- - Added a bitbang mode to `lf cmdread` if delay is 0 the cmd bits turn off and on the antenna with 0 and 1 respectively (@marshmellow42)
- - dump / restore now uses custom filenames (@brianpow)
- - Removed `hf mf sniff` , (@iceman1001), use HF 14A SNIFF instead
- - Added `hf iclass lookup` (@iceman1001)
- - Added `hf iclass chk` (@iceman1001)
- - Fixed ADC mux all closed push-pull state (@iceman1001)
- - Fix `hf mf darkside` - speed fixes (@pwpiwi)
- - Fix `hw tune` - now compensates for 3% error in output, also measure full 140v using ADC channel 5 and 7. (@iceman1001)
- - Updated loclass gpl license (@holiman)
- - Fix Antenna on after changed FPGA Mode. (@iceman1001)
- - Added `hf mf nack` - Mifare NACK bug detection (@iceman1001) (@doegox)
- - Fix `hf mf mifare` - zero parity works, no more double runs for normal darkside (@iceman1001)
- - Added `hf mf fchk` - the fastest check keys implementation tothisday (@iceman1001)
- - Fix `hf iclass` - more stable demod (@iceman1001)
- - Added `hf iclass chk` - check keys from default_iclass_keys.dic file (@iceman1001)
- - Fix `hf 15 dump` - no more crc faults (@iceman1001)
- - Fix `hf 15 read` - no more crc faults (@iceman1001)
- - Fix `hf 15 readmulti` - no more crc faults (@iceman1001)
- - Changed proxmark command line parameter `flush` to `-f` or `-flush` (@merlokk)
- - Added to proxmark command line parameters `w` - wait 20s for serial port (@merlokk)
- - Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (@merlokk)
- - Added to proxmark ability to execute commands from stdin (pipe) (@merlokk)
- - Added new standalone mode "HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN" (@cjbrigato)
- - Added to `hf 14a apdu` - exchange apdu via iso14443-4 (@merlokk)
- - Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk)
- - Added `hf emv` commands (@merlokk)
- - lots of bug fixes (many many)
- - Changed hf mfp security. Now it works in all the modes. (@drHatson)
- - Added `hf fido` commands that work with FIDO U2F authenticators (@merlokk)
- - Added mbedtls instead of old polarssl (@merlokk)
- - Added jansson (@merlokk)
- - Added `hf emv scan` - save card data to json file (@merlokk)
- - Added `hf emv` `gpo`, `readrec`, `genac`, `challenge`, `intauth` - separate commands from `hf emc exec` (@merlokk)
- - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk)
- - Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk)
- - Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk)
- - Added `script run luxeodump` (@0xdrrb)
- - Fix `lf hitag reader 02` - print all bytes (@bosb)
-
-
-### Fixed
- - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (@pwpiwi)
- - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (@merlokk)
-
-## [ice.3.1.0][2017-09-26]
- - proxmark3 client can reconnect to device without restart (@iceman1001)
- - lots of bug fixes (many many)
- - trace/securakey-64169.pm3 - trace of a scecurakey (@atyppo)
- - `hf mf decrypt` - got some longer input and helptext parameter (@iceman1001)
- - Updated the Reveng 1.51 sourcecode to 1.52 from Reveng project homepage (@iceman1001)
- - `hf 14a read` - disconnects when failing to read tag (@iceman1001)
- - `hf mf csave` - renamed parameter `i` to `o` as in output (@iceman1001)
-
-## [3.0.0][2017-08-29]
- Notes on this release
- this version includes a merge with the PM3 offical v3.0.1 code, a.k.a the "Monster merge"
- There is a lot of changes, command breaking changes, which is the cause for the JUMP in version number.
- It is set to v3.0.0 to show that it is on par with PM3 Offical v3 release.
-
- - Updated `mkversion.pl` to write a date based on file when repo is downloaded as a zip file from github (@iceman1001)
- - Update `readme.md` to fit GitHubs markup(@joanbono)
- - Added `script run ul_uid`, try to change UID on a magic UL-card. (@iceman1001)
- - Fixed `hf snoop` bug, of wrong bool value (@ikarus23)
- - Fixed fullimage.s19, wrong offsets (@doegox)
- - Updated `77-mm-usb-device-blacklist.rules` for the pid/vid (@iceman1001)
- - `hf 14a sim` now follows Mifare UL-EV1 protocol better (@iceman1001)
- - Updated `fpga_hf.bit` file (@pwpiwi)
- - Added more card detections to `hf mfu info` (@iceman1001)
- - Fixed `hf mfu restore/dump` to use the right struct values in special data in dumpfile. (@iceman1001)
- - Added `hf mfu restore r` new parameter to use the new pwd for all further auths needed when executing (@iceman1001)
- - Added `default_keys_dic2lua.awk` script to generate default_keys file in client/lualibs (@iceman1001)
- - Fixes to lots of lua scripts, among others
- - `mifare_autopwn`, now uses PRNG detection (@iceman1001)
- - `mfkeys`, fixed bug which only tested the first key (@iceman1001)
- - `dumptoemul`, removed last newline (@iceman1001)
- - ...
- - Added USB/SERIAL communication enhancements (@micolous)
- - Change `hf 14a cuids`, to be interrupted with keyboard press (@iceman1001)
- - Change debugstatements for LF to show which function more unified (@iceman1001)
- - Added `script run calc_di` , to calculate some Mifare keys (@iceman1001)
- - Fixed iclass commands never shut down antenna afterwards (@iceman1001)
- - Change 512kb detection when flashing (@iceman1001)
- - Fixed compilation GCC4.9 or higher detection (@winguru)
- - Fixed compiler warnings in Ubuntu 17.04 (@iceman1001)
- - Ripped out `standalone` code into separete folder to be continued. (@iceman1001)
- - `hf mf nested`, added key validation to entered key (@merlokk)
- - `hf mf hardnested`, added key validation to enterd key (@iceman1001)
- - Change a lot of help texts (@iceman1001)
- - Fixed `hf mf chk` - keyblock bug, limited keys to 256. (@iceman1001)
- - Change `hf mf dump` retries three times now before giving up (@marshmellow42)
- - Fixed `mfu authentication`, with pack-len error (@iceman1001)
- - `Script list`, change sortorder to alphabetic order (@iceman1001)
- - Change `hf mfu gen` to read taguid (@iceman1001)
- - Change `hf mfu pwdgen` to read taguid (@iceman1001)
- - Added `hf mf setmod` sets Mifare Classic EV1 load modulation strength to card (@angelsl)
- - Added `hf 14a read` Mifare PRNG detection based on @doegox LIBNFC impl (@iceman1001)
- - Added `hf mf nonces`, collects Mifare Classic nonces for analysing of PRNG (@iceman1001)
- - Added new CSNS in `hf iclass sim 2` attack (@iceman1001)
- - Added more default keys (@iceman1001)
- - Added analyse nuid, enable creation of Mifare NUID (@iceman1001)
- - Updated the Reveng 1.44 sourcecode to 1.51 from Reveng project homepage (@iceman1001)
- - script run formatMifare - got an option to execute the generate strings (@iceman1001)
- - Fix `hf mf cgetsc` (@iceman1001)
- - Fix `hf legic info` (@iceman1001)
- - Change version output (@iceman1001)
- - Added PAC/Stanley detection to lf search (@marshmellow42)
- - Added lf pac demod and lf pac read - extracts the raw blocks from a PAC/Stanley tag (@marshmellow42)
- - Added hf mf csave commands compatibity for 4k (@Fl0-0)
- - Added data fsktonrz, a fsk cleaning/demodulating routine for weak fsk signal. Note: follow this up with a `data rawdemod nr` to finish demoding your signal. (@marshmellow42)
- - Added lf em 410xbrute, LF EM410x reader bruteforce attack by simulating UIDs from a file (@Fl0-0)
- - Compiles on OS X
- - Compiles with gcc 4.9
- - Compiles for non-Intel CPUs
- - Added lf hitag write 24, the command writes a block to hitag2 tags in crypto mode (@henjo)
- - Added the improved `hf mf hardnested`, an attack working for hardened Mifare cards (EV1, Mifare Plus SL1)
- - Added experimental testmode write option for t55xx (danger) (@marshmellow42)
- - Added t55xx p1detect to `lf search` chip detections (@marshmellow42)
- - Added lf t55xx p1detect, detect page 1 of a t55xx tag based on E015 mfg code (@marshmellow42)
- - Added lf noralsy demod, read, clone, sim commands (@iceman1001)
- - Added lf jablotron demod, read, clone, sim commands (@iceman1001)
- - Added lf nexwatch read - reads a nexwatch tag from the antenna
- - Added lf paradox read - reads a paradox tag from the antenna
- - Added lf fdx sim (@iceman1001)
- - Added lf fdx clone - clones an fdx-b animal tag to t55x7 or q5 (@iceman1001)
- - Added lf fdx read - reads a fdx-b tag from the antenna (@iceman1001)
- - Added lf gproxii read - reads a gproxii tag from the antenna (@marshmellow42)
- - Added lf indala read - reads an indala tag from the antenna (@marshmellow42)
- - Added lf visa2000 demod, read, clone, sim commands (@iceman1001)
-
-## [1.7.0 iceman fork] [2017-03-07]
- - hf mf dump - added retry loops to try each read attempt up to 3 times. makes getting a complete dump easier with many antennas. (@marshmellow42)
- - Added markers in the graph around found Sequence Terminator after askmandemod. (@marshmellow42)
- - Added data mtrim command to trim out samples between start and stop. (@marshmellow42)
- - Added data setgraphmarkers command to set two extra markers on the graph (@marshmellow42)
- - added json support in lua (@vitorio)
- - added a buspirate settings file for at91sam7s512 (@adamlaurie)
- - `lf read` timeouts is now depended on what threshold level you set in `lf config` (@marshmellow42)
- - `hf mf sim` fixed a bug which made sim fail auths. (@iceman1001)
- - `hf 14a read` added magic tag generation 1a and 1b detection (@iceman1001)
- - correctly using stdtypes.h printf and scanf format string macros (PRIx64 et al) (@pwpiwi)
- - fix linker warning re missing entry point when linking fullimage.elf (@pwpiwi)
- - small changes to lf psk and fsk demods to improve results when the trace begins with noise or the chip is not broadcasting yet (@marshmellow42)
- - NOTE CHANGED ALL `lf em4x em*` cmds to simpler `lf em ` - example: `lf em4x em410xdemod` is now `lf em 410xdemod`
- - Renamed and rebuilt `lf em readword` && readwordpwd to `lf em 4x05read` - it now demods and outputs the read block (@marshmellow42/@iceman1001)
- - Renamed and rebuilt `lf em writeword` && writewordpwd to `lf em 4x05write` - it now also reads validation output from the tag (@marshmellow42/@iceman1001)
- - Fixed bug in lf sim and continuous demods not turning off antenna when finished
- - Added lua script path fixes (@pwpiwi)
- - `lf search` - Added EM4x05/EM4x69 chip detection (@marshmellow42)
- - Added lf em 4x05dump command to read and output all the blocks of the chip (@marshmellow42)
- - Added lf em 4x05info command to read and display information about the chip (@marshmellow42)
- - `lf em4x em4x50***` refactoring of em4x50 commands. (@iceman1001)
-
-## [1.6.9 iceman fork] [2017-02-06]
- - Serial speedup, if possible 408600baud otherwise default to 115200baud (@iceman1001)
- - `hf emv` - Added Peter Fillmore EMV branch now compiles on iceman fork. See seperate issue. (@iceman1001)
- - `hf 14a reader` - Aztek detection. (@iceman1001)
- - `standalone mode` - added more detection of tags and refactored (@iceman1001)
- - `script run ufodump` - dumps an Aztek tag. (@iceman1001)
- - `script run hard_autopwn` - runs hardnested attack against all sectors on tag (@iceman1001)
- - Added lf cotag read, and added it to lf search (@iceman1001)
- - Added hitag2 read UID only and added that to lf search (@marshmellow42)
- - `lf search` - check for if signal is only noice (@marshmellow42)
- - `hf 14a reader` - fixed a bug when card has sak 0x00 but still is not UL/NTAG etc. (@iceman1001)
- - `hf mf sim` / `hf 14a sim` - use random nonce. (@micolous)
- - `hw tune` - only prints out if voltage is detected from antenna. (@iceman1001)
- - `hf iclass decrypt` - only decrypt Application1 (@iceman1001)
- - `lf t55xx detect` - when finding multiple possible config blocks, see if a known configblock exists and select. (@iceman1001)
-
-## [1.6.7 iceman fork] [2017-01-05]
- - `lf animal` - FDX-B animal commands (@iceman1001)
- - Fixed bugs in `lf sim` and other lf continuous demods not turning off antenna when finished (@marshmellow42)
- - `hf iclass write` - fixed bugs, added crc. (?)
- - `hf iclass dump` - changed layout in dump (@iceman1001)
- - Changed - debug statements are more clear (@iceman1001)
- - `lf search` - fixed the silent option when acquire data. (@iceman1001)
- - `lf search` - added presco, visa2000, noralsy detection (@iceman1001)
- - `lf precso` - fixed some bitsgeneration in precso bits (@iceman1001)
- - Added `lf noralsy` - adds demod/clone/sime of Noralsy LF tags. (@iceman1001)
- - Added `lf visa2000` - adds demod/clone/sim of Visa2000 lF tags. (@iceman1001)
- - Added `hf mf key_brute` - adds J-Runs 2nd phase bruteforce ref: https://github.com/J-Run/mf_key_brute (@iceman1001)
- - Added `lf jablotron` - adds demod/clone/sim of Jablotron LF tags. (@iceman1001)
- - Added `lf t55xx recoverpw` - adds a new password recovery using bitflips and partial flips if password write went bad. (@alexgrin)
- - `hf legic` - added improved legic data mapping. (jason)
- - `hf mf mifare` - added possibility to target key A|B (@douniwan5788)
- - Added `analyse lcr` - added a new main command group, to help analysing bytes & bits & nibbles. (@iceman1001)
- - Added `lf nedap` - added identification of a NEDAP tag. (@iceman1001)
- - `lf viking clone` - fixed a bug. (@iceman1001)
- - Added bitsliced bruteforce solver in `hf mf hardnested` (@Aczid)
- - `hf mf chk` speedup (@iceman1001)
- - `hf 14a/mf sim x` attack mode, now uses also moebius version of mfkey32 to try finding the key. (@iceman1001)
- - `hf 14a sim` Added emulation of Mifare cards with 10byte UID length. (@iceman1001)
- - `hf mf sim` Added emulation of Mifare cards with 10byte UID length. (@iceman1001)
- - Added `lf guard clone/sim` (@iceman1001)
- - Added `lf pyramd clone/sim` (@iceman1001)
- - trying to fix `hf 14b` command to be able to read CALYPSO card. (@iceman1001)
- - `hf legic load`, it now loads faster and a casting bug is gone. (@iceman1001)
- - Added `hf legic calccrc8` added a method to calculate the legic crc-8 value (@iceman1001)
- - `hf legic decode` fixed the output overflow bugs, better printing (@iceman1001)
- - Coverity Scan fixes a lot of resource leaks, etc (@iceman1001)
- - Added `lf presco *` commands started (@iceman1001)
- - Added `lf hid wiegand` added a method to calculate WIEGAND in different formats, (@iceman1001)
- - `hf mf chkkeys` better printing, same table output as nested, faster execution and added Adam Lauries "try to read Key B if Key A is found" (@iceman1001)
- - `hf mf nested` better printing and added Adam Lauries "try to read Key B if Key A is found" (@iceman1001)
- - `hf mf mifare` fixing the zero parity path, which did not get called. (@iceman1001)
- - Updated the @blapost Crapto1 implementation to v3.3 (blapost)
- - `hf mf c*` updated the calling structure and refactored of the chinese magic commands (@iceman1001, @marshmellow42)
- - Started to add Peter Fillmore EMV fork into Iceman fork. ref: https://github.com/peterfillmore/proxmark3 (@peterfillmore, @iceman1001)
- - Added Travis-CI automatic build integration with GitHub fork. (@iceman1001)
- - Updated the Reveng 1.30 sourcecode to 1.31 from Reveng project homepage (@iceman1001)
- - Updated the Reveng 1.31 sourcecode to 1.40 from Reveng project homepage (@iceman1001)
- - Added possibility to write direct to a Legic Prime Tag (MIM256/1024) without using values from the `BigBuffer` -> `hf legic writeRaw ` (@icsom)
- - Added possibility to decrease DCF values at address 0x05 & 0x06 on a Legic Prime Tag
- DCF-value will be pulled from the BigBuffer (address 0x05 & 0x06) so you have to
- load the data into the BigBuffer before with `hf legic load ` & then
- write the DCF-Values (both at once) with `hf legic write 0x05 0x02` (@icsom)
- - Added script `legic.lua` for display and edit Data of Legic-Prime Tags (@icsom)
- - Added the experimental HITAG_S support (@spenneb)
- - Added topaz detection to `hf search` (@iceman1001)
- - Fixed the silent mode for 14b to be used inside `hf search` (@iceman1001)
-
-### Added
- - Added a LF ASK Sequence Terminator detection option to the standard ask demod - and applied it to `lf search u`, `lf t55xx detect`, and `data rawdemod am s` (@marshmellow42)
- - `lf awid bruteforce ` - Simple bruteforce attack against a AWID reader.
- - `lf t55xx bruteforce [i <*.dic>]` - Simple bruteforce attack to find password - (@iceman1001 and others)
- - `lf viking clone`- clone viking tag to t55x7 or Q5 from 4byte hex ID input
- - `lf viking sim` - sim full viking tag from 4byte hex ID input
- - `lf viking read` - read viking tag and output ID
- - `lf t55xx wipe` - sets t55xx back to factory defaults
- - Added viking demod to `lf search` (@marshmellow42)
- - `data askvikingdemod` demod viking id tag from graphbuffer (@marshmellow42)
- - `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (@marshmellow42)
- - `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (@iceman1001, @marshmellow42)
- - `hf mf eload u` added an ultralight/ntag option. (@marshmellow42)
- - `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (@marshmellow42)
- - `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (@marshmellow42)
- - `hf iclass writeblk` to select, authenticate, and write 1 block to an iclass card (or picopass) (@marshmellow42 + others)
- - `hf iclass clone` to take a saved dump file and clone selected blocks to a new tag (@marshmellow42 + others)
- - `hf iclass calcnewkey` - to calculate the div_key change to change a key - (experimental) (@marshmellow42 + others)
- - `hf iclass encryptblk` - to encrypt a data block hex to prep for writing that block (@marshmellow42)
- - ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young)
- - AWID26 command context added as `lf awid` containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young)
- - Added `hw status`. This command makes the ARM print out some runtime information. (@holiman)
- - Added `hw ping`. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (@holiman)
- - Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (@holiman)
- - Added `hf snoop`. This command take digitalized signal from FPGA and put in BigBuffer. (@pwpiwi + enio)
- - Added Topaz (NFC type 1) protocol support (`hf topaz reader`, `hf list topaz`, `hf 14a raw -T`, `hf topaz snoop`). (@pwpiwi)
- - Added option c to `hf list` (mark CRC bytes) (@pwpiwi)
-
-### Changed
- - Added `[l] ` option to data printdemodbuffer
- - Adjusted lf awid clone to optionally clone to Q5 tags
- - Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7
- - Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal)
- - Adjusted lf pskindalademod to reduce false positive reads.
- - Small adjustments to psk, nrz, and ask clock detect routines - more reliable.
- - Adjusted lf em410x em410xsim to accept a clock argument
- - Adjusted lf t55xx dump to allow overriding the safety check and warning text (@marshmellow42)
- - Adjusted lf t55xx write input variables (@marshmellow42)
- - Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (@marshmellow42 & @iceman1001)
- - Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. (@marshmellow42)
- - Adjusted timings for t55xx commands. more reliable now. (@marshmellow42 & @iceman1001)
- - `lf cmdread` adjusted input methods and added help text (@marshmellow42 & @iceman1001)
- - changed `lf config t ` to be 0 - 128 and will trigger on + or - threshold value (@marshmellow42)
- - `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) (@marshmellow42)
- - Revised workflow for StandAloneMode14a (Craig Young)
- - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (@frederikmoellers)
- - `hw version` only talks to ARM at startup, after that the info is cached. (@pwpiwi)
- - Added `r` option to iclass functions - allows key to be provided in raw block 3/4 format
-
-## [2.2.0][2015-07-12]
-
-### Changed
- - Added `hf 14b raw -s` option to auto select a 14b std tag before raw command
- - Changed `hf 14b write` to `hf 14b sriwrite` as it only applied to sri tags (@marshmellow42)
- - Added `hf 14b info` to `hf search` (@marshmellow42)
- - Added compression of fpga config and data, *BOOTROM REFLASH REQUIRED* (@pwpiwi)
- - Implemented better detection of mifare-tags that are not vulnerable to classic attacks (`hf mf mifare`, `hf mf nested`) (@pwpiwi)
-
-### Added
- - Added `hf 14b reader` to find and print general info about known 14b tags (@marshmellow42)
- - Added `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (@marshmellow42)
- - Added PACE replay functionality (@frederikmoellers)
-
-### Fixed
- - t55xx write timing (@marshmellow42)
-
-
-## [2.1.0][2015-06-23]
-
-### Changed
- - Added ultralight/ntag tag type detection to `hf 14a read` (@marshmellow42)
- - Improved ultralight dump command to auto detect tag type, take authentication, and dump full memory (or subset specified) of known tag types (@iceman1001 / @marshmellow42)
- - Combined ultralight read/write commands and added authentication (@iceman1001)
- - Improved LF manchester and biphase demodulation and ask clock detection especially for reads with heavy clipping. (@marshmellow42)
- - Iclass read, `hf iclass read` now also reads tag config and prints configuration. (@holiman)
- - *bootrom* needs to be flashed, due to new address boundaries between os and fpga, after a size optimization (@pwpiwi)
-
-### Fixed
- - Fixed EM4x50 read/demod of the tags broadcasted memory blocks. `lf em4x em4x50read` (not page read) (@marshmellow42)
- - Fixed issue #19, problems with LF T55xx commands (@iceman1001, @marshmellow42)
- - Fixed various problems with iso14443b, issue #103 (@pwpiwi, @marshmellow42)
-
-### Added
- - Added `hf search` - currently tests for 14443a tags, iclass tags, and 15693 tags (@marshmellow42)
- - Added `hf mfu info` Ultralight/NTAG info command - reads tag configuration and info, allows authentication if needed (@iceman1001, @marshmellow42)
- - Added Mifare Ultralight C and Ultralight EV1/NTAG authentication. (@iceman1001)
- - Added changelog
- - Added `data fdxbdemod` - Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer aka ANIMAL TAG (@marshmellow42, @iceman1001)
-
-## [2.0.0] - 2015-03-25
-### Changed
- - LF sim operations now abort when new commands arrive over the USB - not required to push the device button anymore.
-
-### Fixed
- - Mifare simulation, `hf mf sim` (was broken a long time) (@pwpiwi)
- - Major improvements in LF area and data operations. (@marshmellow42, @iceman1001)
- - Issues regarding LF simulation (@pwpiwi)
-
-### Added
- - iClass functionality: full simulation of iclass tags, so tags can be simulated with data (not only CSN). Not yet support for write/update, but readers do not seem to enforce update. (@holiman).
- - iClass decryption. Proxmark can now decrypt data on an iclass tag, but requires you to have the HID decryption key locally on your computer, as this is not bundled with the sourcecode.
diff --git a/pm3rdv4rrg/src/main/cpp/CMakeLists.txt b/pm3rdv4rrg/src/main/cpp/CMakeLists.txt
deleted file mode 100644
index ce5b3c3d..00000000
--- a/pm3rdv4rrg/src/main/cpp/CMakeLists.txt
+++ /dev/null
@@ -1,398 +0,0 @@
-#需要的最cmake版本
-cmake_minimum_required(VERSION 3.4.1)
-
-#设置全局宏定义,开启NDK配置定义!
-add_definitions("-D__ANDROID_NDK__")
-
-#添加预编译宏定义参数,此次的作用是开启配置文件的引入!
-add_definitions(-DANDROID -D "getlocaledecpoint()='.'")
-
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O3 -fvisibility=hidden -w")
-
-#缩短路径定义
-set(PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
-
-#添加动态库定义
-add_library(pm3rrg_rdv4 SHARED
- ${PM3_ROOT}/common/util_posix.c
- ${PM3_ROOT}/common/crapto1/crapto1.c
- ${PM3_ROOT}/common/crapto1/crypto1.c
- ${PM3_ROOT}/common/crc.c
- ${PM3_ROOT}/common/crc16.c
- ${PM3_ROOT}/common/crc32.c
- ${PM3_ROOT}/common/crc64.c
- ${PM3_ROOT}/common/parity.c
- ${PM3_ROOT}/common/commonutil.c
- ${PM3_ROOT}/common/generator.c
- ${PM3_ROOT}/common/lfdemod.c
- ${PM3_ROOT}/common/iso15693tools.c
- ${PM3_ROOT}/common/bucketsort.c
- ${PM3_ROOT}/common/legic_prng.c
- ${PM3_ROOT}/common/mbedtls/aes.c
- ${PM3_ROOT}/common/mbedtls/base64.c
- ${PM3_ROOT}/common/mbedtls/rsa.c
- ${PM3_ROOT}/common/mbedtls/rsa_internal.c
- ${PM3_ROOT}/common/mbedtls/arc4.c
- ${PM3_ROOT}/common/mbedtls/bignum.c
- ${PM3_ROOT}/common/mbedtls/asn1parse.c
- ${PM3_ROOT}/common/mbedtls/asn1write.c
- ${PM3_ROOT}/common/mbedtls/blowfish.c
- ${PM3_ROOT}/common/mbedtls/camellia.c
- ${PM3_ROOT}/common/mbedtls/certs.c
- ${PM3_ROOT}/common/mbedtls/des.c
- ${PM3_ROOT}/common/mbedtls/ecdsa.c
- ${PM3_ROOT}/common/mbedtls/ecp.c
- ${PM3_ROOT}/common/mbedtls/ecp_curves.c
- ${PM3_ROOT}/common/mbedtls/entropy.c
- ${PM3_ROOT}/common/mbedtls/entropy_poll.c
- ${PM3_ROOT}/common/mbedtls/error.c
- ${PM3_ROOT}/common/mbedtls/md.c
- ${PM3_ROOT}/common/mbedtls/md5.c
- ${PM3_ROOT}/common/mbedtls/md_wrap.c
- ${PM3_ROOT}/common/mbedtls/sha1.c
- ${PM3_ROOT}/common/mbedtls/sha256.c
- ${PM3_ROOT}/common/mbedtls/sha512.c
- ${PM3_ROOT}/common/mbedtls/timing.c
- ${PM3_ROOT}/common/mbedtls/cmac.c
- ${PM3_ROOT}/common/mbedtls/oid.c
- ${PM3_ROOT}/common/mbedtls/pem.c
- ${PM3_ROOT}/common/mbedtls/pk.c
- ${PM3_ROOT}/common/mbedtls/pk_wrap.c
- ${PM3_ROOT}/common/mbedtls/pkcs5.c
- ${PM3_ROOT}/common/mbedtls/pkcs12.c
- ${PM3_ROOT}/common/mbedtls/pkparse.c
- ${PM3_ROOT}/common/mbedtls/pkwrite.c
- ${PM3_ROOT}/common/mbedtls/x509.c
- ${PM3_ROOT}/common/mbedtls/x509_crl.c
- ${PM3_ROOT}/common/mbedtls/x509_crt.c
- ${PM3_ROOT}/common/mbedtls/ctr_drbg.c
- ${PM3_ROOT}/common/mbedtls/cipher_wrap.c
- ${PM3_ROOT}/common/mbedtls/cipher.c
- ${PM3_ROOT}/common/mbedtls/platform_util.c
- ${PM3_ROOT}/common//zlib/inflate.c
- ${PM3_ROOT}/common/zlib/inffast.c
- ${PM3_ROOT}/common/zlib/zutil.c
- ${PM3_ROOT}/common/zlib/inftrees.c
- ${PM3_ROOT}/common//zlib/adler32.c
- ${PM3_ROOT}/client/fileutils.c
- ${PM3_ROOT}/client/uart/uart_posix.c
- ${PM3_ROOT}/client/jansson/utf.c
- ${PM3_ROOT}/client/jansson/dump.c
- ${PM3_ROOT}/client/jansson/path.c
- ${PM3_ROOT}/client/jansson/load.c
- ${PM3_ROOT}/client/jansson/error.c
- ${PM3_ROOT}/client/jansson/value.c
- ${PM3_ROOT}/client/jansson/memory.c
- ${PM3_ROOT}/client/jansson/hashtable_seed.c
- ${PM3_ROOT}/client/jansson/strbuffer.c
- ${PM3_ROOT}/client/jansson/strconv.c
- ${PM3_ROOT}/client/jansson/hashtable.c
- ${PM3_ROOT}/client/jansson/hashtable.c
- ${PM3_ROOT}/client/loclass/cipherutils.c
- ${PM3_ROOT}/client/loclass/cipher.c
- ${PM3_ROOT}/client/loclass/ikeys.c
- ${PM3_ROOT}/client/loclass/elite_crack.c
- ${PM3_ROOT}/client/cliparser/cliparser.c
- ${PM3_ROOT}/client/cliparser/argtable3.c
- ${PM3_ROOT}/client/crypto/libpcrypto.c
- ${PM3_ROOT}/client/crypto/asn1utils.c
- ${PM3_ROOT}/client/crypto/asn1dump.c
- ${PM3_ROOT}/client/emv/emvcore.c
- ${PM3_ROOT}/client/emv/cmdemv.c
- ${PM3_ROOT}/client/emv/tlv.c
- ${PM3_ROOT}/client/emv/dol.c
- ${PM3_ROOT}/client/emv/emv_tags.c
- ${PM3_ROOT}/client/emv/emv_roca.c
- ${PM3_ROOT}/client/emv/dump.c
- ${PM3_ROOT}/client/emv/crypto_polarssl.c
- ${PM3_ROOT}/client/emv/crypto.c
- ${PM3_ROOT}/client/emv/emv_pk.c
- ${PM3_ROOT}/client/emv/emv_pki.c
- ${PM3_ROOT}/client/emv/emvjson.c
- ${PM3_ROOT}/client/emv/apduinfo.c
- ${PM3_ROOT}/client/emv/test/cryptotest.c
- ${PM3_ROOT}/client/emv/test/sda_test.c
- ${PM3_ROOT}/client/emv/test/dda_test.c
- ${PM3_ROOT}/client/emv/test/cda_test.c
- ${PM3_ROOT}/client/emv/test/crypto_test.c
- ${PM3_ROOT}/client/emv/test/cryptotest.c
- ${PM3_ROOT}/client/emv/test/sda_test.c
- ${PM3_ROOT}/client/emv/test/dda_test.c
- ${PM3_ROOT}/client/emv/test/cda_test.c
- ${PM3_ROOT}/client/emv/test/crypto_test.c
- ${PM3_ROOT}/client/mifare/mad.c
- ${PM3_ROOT}/client/mifare/mfkey.c
- ${PM3_ROOT}/client/mifare/mifare4.c
- ${PM3_ROOT}/client/mifare/mifarehost.c
- ${PM3_ROOT}/client/mifare/ndef.c
- ${PM3_ROOT}/client/fido/additional_ca.c
- ${PM3_ROOT}/client/fido/cbortools.c
- ${PM3_ROOT}/client/fido/cose.c
- ${PM3_ROOT}/client/fido/fidocore.c
- ${PM3_ROOT}/client/tinycbor/cborencoder.c
- ${PM3_ROOT}/client/tinycbor/cborencoder_close_container_checked.c
- ${PM3_ROOT}/client/tinycbor/cborerrorstrings.c
- ${PM3_ROOT}/client/tinycbor/cborparser.c
- ${PM3_ROOT}/client/tinycbor/cborparser_dup_string.c
- ${PM3_ROOT}/client/tinycbor/cborpretty.c
- ${PM3_ROOT}/client/tinycbor/cborpretty_stdio.c
- ${PM3_ROOT}/client/tinycbor/cbortojson.c
- ${PM3_ROOT}/client/tinycbor/cborvalidation.c
- ${PM3_ROOT}/client/tinycbor/open_memstream.c
- ${PM3_ROOT}/client/mifare/mifaredefault.c
- ${PM3_ROOT}/client/graph.c
- ${PM3_ROOT}/client/ui.c
- ${PM3_ROOT}/client/tools.c
- ${PM3_ROOT}/client/tea.c
- ${PM3_ROOT}/client/util.c
- ${PM3_ROOT}/client/comms.c
- ${PM3_ROOT}/client/cmdcrc.c
- ${PM3_ROOT}/client/cmdanalyse.c
- ${PM3_ROOT}/client/cmddata.c
- ${PM3_ROOT}/client/cmdtrace.c
- ${PM3_ROOT}/client/cmdhf.c
- ${PM3_ROOT}/client/cmdhflto.c
- ${PM3_ROOT}/client/aidsearch.c
- ${PM3_ROOT}/client/cmdhf14a.c
- ${PM3_ROOT}/client/cmdhf14b.c
- ${PM3_ROOT}/client/cmdwiegand.c
- ${PM3_ROOT}/client/wiegand_formatutils.c
- ${PM3_ROOT}/client/wiegand_formats.c
- ${PM3_ROOT}/client/cmdlfmotorola.c
- ${PM3_ROOT}/client/cmdlfgallagher.c
- ${PM3_ROOT}/client/cmdhf15.c
- ${PM3_ROOT}/client/cmdhfepa.c
- ${PM3_ROOT}/client/cmdhflegic.c
- ${PM3_ROOT}/client/cmdhfthinfilm.c
- ${PM3_ROOT}/client/cmdflashmemspiffs.c
- ${PM3_ROOT}/client/cmdhffelica.c
- ${PM3_ROOT}/client/cmdhficlass.c
- ${PM3_ROOT}/client/cmdhflist.c
- ${PM3_ROOT}/client/cmdhfmf.c
- ${PM3_ROOT}/client/cmdhfmfdes.c
- ${PM3_ROOT}/client/cmdhfmfu.c
- ${PM3_ROOT}/client/cmdhfmfp.c
- ${PM3_ROOT}/client/cmdhffido.c
- ${PM3_ROOT}/client/cmdhftopaz.c
- ${PM3_ROOT}/client/cmdhw.c
- ${PM3_ROOT}/client/cmdlf.c
- ${PM3_ROOT}/client/cmdlfkeri.c
- ${PM3_ROOT}/client/cmdlffdx.c
- ${PM3_ROOT}/client/cmdlfio.c
- ${PM3_ROOT}/client/cmdlfem4x.c
- ${PM3_ROOT}/client/cmdlfhid.c
- ${PM3_ROOT}/client/cmdlfnedap.c
- ${PM3_ROOT}/client/cmdlfguard.c
- ${PM3_ROOT}/client/cmdlfhitag.c
- ${PM3_ROOT}/client/cmdlfjablotron.c
- ${PM3_ROOT}/client/cmdsmartcard.c
- ${PM3_ROOT}/client/cmdlfti.c
- ${PM3_ROOT}/client/cmdlfpac.c
- ${PM3_ROOT}/client/cmdlfnoralsy.c
- ${PM3_ROOT}/client/cmdlfnexwatch.c
- ${PM3_ROOT}/client/cmdlfpresco.c
- ${PM3_ROOT}/client/cmdlfindala.c
- ${PM3_ROOT}/client/cmdlfviking.c
- ${PM3_ROOT}/client/cmdlfsecurakey.c
- ${PM3_ROOT}/client/cmdlfpyramid.c
- ${PM3_ROOT}/client/cmdlfparadox.c
- ${PM3_ROOT}/client/cmdlfcotag.c
- ${PM3_ROOT}/client/cmdlfawid.c
- ${PM3_ROOT}/client/cmdparser.c
- ${PM3_ROOT}/client/cmdscript.c
- ${PM3_ROOT}/client/cmdlfvisa2000.c
- ${PM3_ROOT}/client/whereami.c
- ${PM3_ROOT}/client/cmdmain.c
- ${PM3_ROOT}/client/cmdflashmem.c
- ${PM3_ROOT}/client/scripting.c
- ${PM3_ROOT}/client/pm3_binlib.c
- ${PM3_ROOT}/client/proxmark3.c
- ${PM3_ROOT}/client/pm3_bitlib.c
- ${PM3_ROOT}/client/cmdlft55xx.c
- ${PM3_ROOT}/client/cmdlfpcf7931.c
- ${PM3_ROOT}/client/reveng/cli.c
- ${PM3_ROOT}/client/reveng/bmpbit.c
- ${PM3_ROOT}/client/reveng/preset.c
- ${PM3_ROOT}/client/reveng/model.c
- ${PM3_ROOT}/client/reveng/poly.c
- ${PM3_ROOT}/client/reveng/reveng.c
- ${PM3_ROOT}/client/guidummy.c
- ${PM3_ROOT}/client/liblua/lapi.c
- ${PM3_ROOT}/client/liblua/ldo.c
- ${PM3_ROOT}/client/liblua/lgc.c
- ${PM3_ROOT}/client/liblua/ltm.c
- ${PM3_ROOT}/client/liblua/lvm.c
- ${PM3_ROOT}/client/liblua/lzio.c
- ${PM3_ROOT}/client/liblua/lcode.c
- ${PM3_ROOT}/client/liblua/llex.c
- ${PM3_ROOT}/client/liblua/liolib.c
- ${PM3_ROOT}/client/liblua/loslib.c
- ${PM3_ROOT}/client/liblua/lopcodes.c
- ${PM3_ROOT}/client/liblua/lmem.c
- ${PM3_ROOT}/client/liblua/lmathlib.c
- ${PM3_ROOT}/client/liblua/ldump.c
- ${PM3_ROOT}/client/liblua/ldblib.c
- ${PM3_ROOT}/client/liblua/lundump.c
- ${PM3_ROOT}/client/liblua/lcorolib.c
- ${PM3_ROOT}/client/liblua/lauxlib.c
- ${PM3_ROOT}/client/liblua/ltablib.c
- ${PM3_ROOT}/client/liblua/linit.c
- ${PM3_ROOT}/client/liblua/lstring.c
- ${PM3_ROOT}/client/liblua/lctype.c
- ${PM3_ROOT}/client/liblua/ltable.c
- ${PM3_ROOT}/client/liblua/ldebug.c
- ${PM3_ROOT}/client/liblua/lstate.c
- ${PM3_ROOT}/client/liblua/lstrlib.c
- ${PM3_ROOT}/client/liblua/lfunc.c
- ${PM3_ROOT}/client/liblua/lparser.c
- ${PM3_ROOT}/client/liblua/lobject.c
- ${PM3_ROOT}/client/liblua/loadlib.c
- ${PM3_ROOT}/client/liblua/lbaselib.c
- ${PM3_ROOT}/client/liblua/lbitlib.c
- #加入hardnested的支持!
- ${PM3_ROOT}/client/cmdhfmfhard.c
- ${PM3_ROOT}/client/hardnested/hardnested_bruteforce.c
- #蓝牙USART的支持!
- ${PM3_ROOT}/client/cmdusart.c
- #PM3刷写器!
- ${PM3_ROOT}/client/flash.c
- )
-
-#添加头文件配置
-target_include_directories(pm3rrg_rdv4 PRIVATE
- ${PM3_ROOT}/
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/common
- ${PM3_ROOT}/common/zlib
- ${PM3_ROOT}/common/mbedtls
- ${PM3_ROOT}/client
- ${PM3_ROOT}/client/uart
- ${PM3_ROOT}/client/fido
- ${PM3_ROOT}/client/liblua
- ${PM3_ROOT}/client/jansson
- ${PM3_ROOT}/client/tinycbor)
-
-## CPU-specific code
-## These are mostly for x86-based architectures, which is not useful for many Android devices.
-add_library(pm3rrg_rdv4_hardnested_nosimd OBJECT
- ${PM3_ROOT}/client/hardnested/hardnested_bf_core.c
- ${PM3_ROOT}/client/hardnested/hardnested_bitarray_core.c)
-
-target_include_directories(pm3rrg_rdv4_hardnested_nosimd PRIVATE
- ${PM3_ROOT}/common
- ${PM3_ROOT}/client
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/client/hardnested)
-
-set(X86_CPUS x86 x86_64 i686)
-
-message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}")
-
-if ("${CMAKE_SYSTEM_PROCESSOR}" IN_LIST X86_CPUS)
- message(STATUS "Building optimised x86/x86_64 binaries")
- target_compile_options(pm3rrg_rdv4_hardnested_nosimd BEFORE PRIVATE
- -mno-mmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f)
-
- set_property(TARGET pm3rrg_rdv4_hardnested_nosimd PROPERTY POSITION_INDEPENDENT_CODE ON)
-
- ## x86 / MMX
- add_library(pm3rrg_rdv4_hardnested_mmx OBJECT
- ${PM3_ROOT}/client/hardnested/hardnested_bf_core.c
- ${PM3_ROOT}/client/hardnested/hardnested_bitarray_core.c)
-
- target_compile_options(pm3rrg_rdv4_hardnested_mmx BEFORE PRIVATE
- -mmmx -mno-sse2 -mno-avx -mno-avx2 -mno-avx512f)
-
- target_include_directories(pm3rrg_rdv4_hardnested_mmx PRIVATE
- ${PM3_ROOT}/common
- ${PM3_ROOT}/client
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/client/hardnested)
-
- set_property(TARGET pm3rrg_rdv4_hardnested_mmx PROPERTY POSITION_INDEPENDENT_CODE ON)
-
- ## x86 / SSE2
- add_library(pm3rrg_rdv4_hardnested_sse2 OBJECT
- ${PM3_ROOT}/client/hardnested/hardnested_bf_core.c
- ${PM3_ROOT}/client/hardnested/hardnested_bitarray_core.c)
-
- target_compile_options(pm3rrg_rdv4_hardnested_sse2 BEFORE PRIVATE
- -mmmx -msse2 -mno-avx -mno-avx2 -mno-avx512f)
-
- target_include_directories(pm3rrg_rdv4_hardnested_sse2 PRIVATE
- ${PM3_ROOT}/common
- ${PM3_ROOT}/client
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/client/hardnested)
-
- set_property(TARGET pm3rrg_rdv4_hardnested_sse2 PROPERTY POSITION_INDEPENDENT_CODE ON)
-
- ## x86 / AVX
- add_library(pm3rrg_rdv4_hardnested_avx OBJECT
- ${PM3_ROOT}/client/hardnested/hardnested_bf_core.c
- ${PM3_ROOT}/client/hardnested/hardnested_bitarray_core.c)
-
- target_compile_options(pm3rrg_rdv4_hardnested_avx BEFORE PRIVATE
- -mmmx -msse2 -mavx -mno-avx2 -mno-avx512f)
-
- target_include_directories(pm3rrg_rdv4_hardnested_avx PRIVATE
- ${PM3_ROOT}/common
- ${PM3_ROOT}/client
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/client/hardnested)
-
- set_property(TARGET pm3rrg_rdv4_hardnested_avx PROPERTY POSITION_INDEPENDENT_CODE ON)
-
- ## x86 / AVX2
- add_library(pm3rrg_rdv4_hardnested_avx2 OBJECT
- ${PM3_ROOT}/client/hardnested/hardnested_bf_core.c
- ${PM3_ROOT}/client/hardnested/hardnested_bitarray_core.c)
-
- target_compile_options(pm3rrg_rdv4_hardnested_avx2 BEFORE PRIVATE
- -mmmx -msse2 -mavx -mavx2 -mno-avx512f)
-
- target_include_directories(pm3rrg_rdv4_hardnested_avx2 PRIVATE
- ${PM3_ROOT}/common
- ${PM3_ROOT}/client
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/client/hardnested)
-
- set_property(TARGET pm3rrg_rdv4_hardnested_avx2 PROPERTY POSITION_INDEPENDENT_CODE ON)
-
- ## x86 / AVX512
- add_library(pm3rrg_rdv4_hardnested_avx512 OBJECT
- ${PM3_ROOT}/client/hardnested/hardnested_bf_core.c
- ${PM3_ROOT}/client/hardnested/hardnested_bitarray_core.c)
-
- target_compile_options(pm3rrg_rdv4_hardnested_avx512 BEFORE PRIVATE
- -mmmx -msse2 -mavx -mavx2 -mavx512f)
-
- target_include_directories(pm3rrg_rdv4_hardnested_avx512 PRIVATE
- ${PM3_ROOT}/common
- ${PM3_ROOT}/client
- ${PM3_ROOT}/include/
- ${PM3_ROOT}/client/hardnested)
-
- set_property(TARGET pm3rrg_rdv4_hardnested_avx512 PROPERTY POSITION_INDEPENDENT_CODE ON)
-
- set(SIMD_TARGETS
- $
- $
- $
- $
- $)
-else ()
- message(STATUS "Not building optimised targets")
- set(SIMD_TARGETS)
-endif ()
-
-#定义为静态库,被最终的pm3库依赖!
-add_library(pm3rrg_rdv4_hardnested STATIC
- $
- ${SIMD_TARGETS})
-
-#声明变量
-set(COMMAPPING_FILE ${PROJECTDIR}/communication/src/main/jniLibs/${ANDROID_ABI}/libcommapping.so)
-
-#添加动态库链接!
-target_link_libraries(pm3rrg_rdv4 ${COMMAPPING_FILE} pm3rrg_rdv4_hardnested android log z)
\ No newline at end of file
diff --git a/pm3rdv4rrg/src/main/cpp/COMPILING.txt b/pm3rdv4rrg/src/main/cpp/COMPILING.txt
deleted file mode 100644
index 58ee40c0..00000000
--- a/pm3rdv4rrg/src/main/cpp/COMPILING.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-
-Refer to doc/md/Installation_Instructions/ for up-to-date intructions for various platforms.
diff --git a/pm3rdv4rrg/src/main/cpp/HACKING.md b/pm3rdv4rrg/src/main/cpp/HACKING.md
deleted file mode 100644
index dcbdfd34..00000000
--- a/pm3rdv4rrg/src/main/cpp/HACKING.md
+++ /dev/null
@@ -1,273 +0,0 @@
-_"Coding styles are like assholes, everyone has one and no one likes anyone elses."_
---Eric Warmenhoven
-
-# Overview
-
-The Proxmark3 codebase is pretty messy and in the process of being cleaned up,
-so we don't have clear guidelines on how to place new code just yet. However,
-please don't make things worse.
-
-However, we have established a set of coding style guidelines in order to
-clean up the code consistently and keep it consistent in the future.
-Look around and respect the same style.
-
-Helper script to get some uniformity in the style:
-
-`$ make style`
-
-It makes use of `astyle` so be sure to install it first.
-
-
-# Indentation
-
-Don't use tabs, editors are messing them up too easily.
-Increment unit is four spaces.
-
-If you use `make style`, this will be done for you.
-
-# Width
-
-Try to keep lines to a reasonable length. 80 characters is a good mark; using an
-editor that shows a vertical line is a great idea. However, don't break a line
-just because you're slightly over, it's not worth it. No 200-character lines,
-though.
-
-# Macros
-
-`#define`, function-like or not, are all UPPERCASE unless you're emulating a
-well-known function name.
-
-# Identifiers
-
-Functions, local variables, and arguments are all named using
-`underscores_as_spaces`. Global variables are Evil and are prepended with `g_` to
-distinguish them. Avoid them.
-
-Single-character variables are a bad idea. Exceptions: loop iterators and maybe
-simple byte pointers (`*p`) in very obvious places. If you have more than one
-such pointer, use a real name. If you have more than a couple nested loops,
-complex logic, or indices that differ in interpretation or purpose, use real
-names instead of i,j,k.
-
-# Data types
-
-Use `stdint.h` types (`uint32_t` and friends) unless you have a reason not to. Don't
-use microsoft-style `DWORD` and the like, we're getting rid of those. Avoid char
-for buffers, `uint8_t` is more obvious when you're not working with strings. Use
-`const` where things are const. Try to use `size_t` for sizes.
-
-Pointers and reference operators are attached to the variable name:
-```
- void *ptr;
-```
-not:
-```
- void* ptr;
-```
-otherwise you're tempted to write:
-```
- void* in, out;
-```
-and you'll fail.
-
-`make style` will take care of pointers & reference operators.
-
-# Expressions
-
-In general, use whitespace around binary operators - no unspaced blobs of an
-expression. `make style` will take care of whitespaces around operators.
-
-For example,
-```
- if (5 * a < b && some_bool_var)
-```
-but not
-```
- if (5*a= 0x7f)
- return '.';
- else
- return c;
-}
-```
-vs.
-```
-static void hexdump(void *buf, size_t len) {
- ...
-}
-```
-As a general guideline, functions shouldn't usually be much more than 30-50
-lines. Above, the general algorithm won't be easily apparent, and you're
-probably missing some factoring/restructuring opportunity.
-
-# Structs / unions / enums
-
-Use typedefs when defining structs. The type should be named something_t.
-```
-typedef struct {
- blah blah;
-} prox_cmd_t;
-```
-You can use anonymous enums to replace lots of sequential or mostly-sequential
-#defines.
-
-# Switch
-
-Indent once for the `case:` labels, then again for the body. Like this:
-```
-switch(bar) {
- case OPTION_A:
- do_stuff();
- break;
- case OPTION_B:
- do_other_stuff();
- break;
-}
-```
-`make style` will take care of the indentation.
-
-If you fall through into another case, add an explicit comment;
-otherwise, it can look confusing.
-
-If your `switch()` is too long or has too many cases, it should be cleaned up.
-Split off the cases into functions, break the switch() into parent and children
-switches (e.g. command and subcommand), or use an array of function pointers or
-the like. In other words, use common sense and your brain.
-
-If you need local scope variables for a case, you can add braces:
-```
-switch(bar) {
- case OPTION_A: {
- int baz = 5 * bar;
- do_stuff(baz);
- break;
- }
- ...
-```
-But at that point you should probably consider using a separate function.
-
-# Comments
-
-Use //, it's shorter:
-```
-// this does foo
-...
-
-// baz:
-// This does blah blah blah .....
-// blah blah...
-```
-`/* */` can be used to comment blocks of code, but you should probably remove
-them anyway - we have version control, it's easy to fetch old code if needed,
-so avoid committing commented out chunks of code. The same goes for `#if 0`.
-
-# File
-
-Please use common sense and restrain yourself from having a thousands line
-file. Functions in a file should have something *specific* in common. Over time
-sub-categories can arise and should therefore yield to file splitting.
-
-For these reasons, vague and general filenames (e.g. `util.*`, `global.*`, `misc.*`,
-`main.*`, and the like) should be very limited, if not prohibited.
-
-# File headers
-
-License/description header first:
-```
-//-----------------------------------------------------------------------------
-// YOUR COPYRIGHT LINE GOES HERE
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// FILE DESCRIPTION GOES HERE
-//-----------------------------------------------------------------------------
-```
-If you modify a file in any non-trivial way (add code, etc.), add your copyright
-to the top with the current year.
-
-# Header files
-
-Use the following include guard format:
-```
-#ifndef FOOBAR_H__
-#define FOOBAR_H__
-
-...
-
-#endif // FOOBAR_H__
-```
-Keep in mind that `__FOOBAR_H` would be reserved by the implementation and thus
-you shouldn't use it (same for `_FOOBAR_H`).
-
-# Whitespace
-
-Avoid trailing whitespace (no line should end in tab or space).
-Keep a newline (blank line) at the end of each file.
-
-`make style` will take care of both.
diff --git a/pm3rdv4rrg/src/main/cpp/LICENSE.txt b/pm3rdv4rrg/src/main/cpp/LICENSE.txt
deleted file mode 100644
index 7f48bec2..00000000
--- a/pm3rdv4rrg/src/main/cpp/LICENSE.txt
+++ /dev/null
@@ -1,281 +0,0 @@
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
diff --git a/pm3rdv4rrg/src/main/cpp/Makefile b/pm3rdv4rrg/src/main/cpp/Makefile
deleted file mode 100644
index 783b5fa2..00000000
--- a/pm3rdv4rrg/src/main/cpp/Makefile
+++ /dev/null
@@ -1,225 +0,0 @@
-
-include Makefile.defs
--include Makefile.platform
--include .Makefile.options.cache
-include common_arm/Makefile.hal
-
-# preserve relative DESTDIR path for subdir makes
-ifneq (,$(DESTDIR))
- # realpath needs the directory to exist
- $(shell $(MKDIR) $(DESTDIR))
- MYDESTDIR:=$(realpath $(DESTDIR))
- ifeq (,$(MYDESTDIR))
- $(error Can't create $(DESTDIR))
- endif
-endif
-
-all clean install uninstall: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% fpga_compress/%
-
-INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py findbits.py rfidtest.pl xorcheck.py
-INSTALLSIMFW=sim011.bin sim011.sha512.txt
-INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage
-INSTALLSHARES=tools/jtag_openocd traces
-INSTALLDOCS=doc/*.md doc/md
-
-install: all common/install
-
-common/install:
- $(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...)
-ifneq (,$(INSTALLSCRIPTS))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
- $(Q)$(CP) $(INSTALLSCRIPTS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
-endif
-ifneq (,$(INSTALLSHARES))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
- $(Q)$(CP) $(INSTALLSHARES) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
-endif
-ifneq (,$(INSTALLDOCS))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
- $(Q)$(CP) $(INSTALLDOCS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
-endif
-ifneq (,$(INSTALLTOOLS))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
- $(Q)$(CP) $(foreach tool,$(INSTALLTOOLS),tools/$(tool)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
-endif
-ifneq (,$(INSTALLSIMFW))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
- $(Q)$(CP) $(foreach fw,$(INSTALLSIMFW),tools/simmodule/$(fw)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
-endif
-ifeq ($(platform),Linux)
- $(Q)$(MKDIR) $(DESTDIR)$(UDEV_PREFIX)
- $(Q)$(CP) driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
-endif
-
-uninstall: common/uninstall
-
-common/uninstall:
- $(info [@] Uninstalling common resources from $(MYDESTDIR)$(PREFIX)...)
-ifneq (,$(INSTALLSCRIPTS))
- $(Q)$(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script)))
-endif
-ifneq (,$(INSTALLSHARES))
- $(Q)$(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share)))
-endif
-ifneq (,$(INSTALLDOCS))
- $(Q)$(RMDIR) $(foreach doc,$(INSTALLDOCS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)$(PATHSEP)$(notdir $(doc)))
- $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
-endif
-ifneq (,$(INSTALLTOOLS))
- $(Q)$(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
-endif
- $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
-ifneq (,$(INSTALLSIMFW))
- $(Q)$(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
-endif
- $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
-ifeq ($(platform),Linux)
- $(Q)$(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
-endif
- $(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
-
-mfkey/%: FORCE
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR)
-nonce2key/%: FORCE
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@) DESTDIR=$(MYDESTDIR)
-fpga_compress/%: FORCE
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C tools/fpga_compress $(patsubst fpga_compress/%,%,$@) DESTDIR=$(MYDESTDIR)
-bootrom/%: FORCE cleanifplatformchanged
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@) DESTDIR=$(MYDESTDIR)
-armsrc/%: FORCE cleanifplatformchanged fpga_compress/%
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@) DESTDIR=$(MYDESTDIR)
-client/%: FORCE
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR)
-recovery/all: bootrom/all armsrc/all
-recovery/install: bootrom/all armsrc/all
-recovery/%: FORCE cleanifplatformchanged
- $(info [*] MAKE $@)
- $(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR)
-FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
-
-.PHONY: all clean install uninstall help _test bootrom fullimage recovery client mfkey nonce2key style checks FORCE udev accessrights cleanifplatformchanged
-
-help:
- @echo "Multi-OS Makefile"
- @echo
- @echo "Possible targets:"
- @echo "+ all - Make all targets: bootrom, fullimage and OS-specific host tools"
- @echo "+ clean - Clean in all targets"
- @echo "+ .../clean - Clean in specified target and its deps, e.g. bootrom/clean"
- @echo "+ (un)install - Install/uninstall Proxmark files in the system, default to /usr/local/share,"
- @echo " else provide a PREFIX. See Maintainers.md for more options"
- @echo
- @echo "+ bootrom - Make bootrom"
- @echo "+ fullimage - Make armsrc fullimage (includes fpga)"
- @echo "+ recovery - Make bootrom and fullimage files for JTAG flashing"
- @echo
- @echo "+ client - Make only the OS-specific host client"
- @echo "+ mfkey - Make tools/mfkey"
- @echo "+ nonce2key - Make tools/nonce2key"
- @echo "+ fpga_compress - Make tools/fpga_compress"
- @echo
- @echo "+ style - Apply some automated source code formatting rules"
- @echo "+ checks - Detect various encoding issues in source code"
- @echo
- @echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4"
- @echo "To activate verbose mode, use make V=1"
-
-client: client/all
-
-bootrom: bootrom/all
-
-# aliases fullimage = armsrc
-
-fullimage: armsrc/all
-
-fullimage/all: armsrc/all
-
-fullimage/clean: armsrc/clean
-
-fullimage/install: armsrc/install
-
-fullimage/uninstall: armsrc/uninstall
-
-recovery: recovery/all
-
-mfkey: mfkey/all
-
-nonce2key: nonce2key/all
-
-fpga_compress: fpga_compress/all
-
-newtarbin:
- $(RM) proxmark3-$(platform)-bin.tar proxmark3-$(platform)-bin.tar.gz
- @touch proxmark3-$(platform)-bin.tar
-
-tarbin: newtarbin client/tarbin armsrc/tarbin bootrom/tarbin
- $(info GEN proxmark3-$(platform)-bin.tar)
- $(Q)$(GZIP) proxmark3-$(platform)-bin.tar
-
-# detect if there were changes in the platform definitions, requiring a clean
-cleanifplatformchanged:
-ifeq ($(PLATFORM_CHANGED), true)
- $(info [!] Platform definitions changed, cleaning bootrom/armsrc/recovery first...)
- $(Q)$(MAKE) --no-print-directory -C bootrom clean
- $(Q)$(MAKE) --no-print-directory -C armsrc clean
- $(Q)$(MAKE) --no-print-directory -C recovery clean
- $(Q)echo CACHED_PLATFORM=$(PLATFORM) > .Makefile.options.cache
- $(Q)echo CACHED_PLATFORM_EXTRAS=$(PLATFORM_EXTRAS) >> .Makefile.options.cache
- $(Q)echo CACHED_PLATFORM_DEFS=$(PLATFORM_DEFS) >> .Makefile.options.cache
-endif
-
-# configure system to ignore PM3 device as a modem (ModemManager blacklist, effective *only* if ModemManager is not using _strict_ policy)
-# Read doc/md/ModemManager-Must-Be-Discarded.md for more info
-udev:
- sudo cp -rf driver/77-pm3-usb-device-blacklist.rules /etc/udev/rules.d/77-pm3-usb-device-blacklist.rules
- sudo udevadm control --reload-rules
-
-# configure system to add user to the dialout group
-# you need to logout, relogin to get this access right correct.
-# Finally, you might need to run the proxmark3 client under SUDO on some systems
-accessrights:
-ifneq ($(wildcard /etc/arch-release),) #If user is running ArchLinux
- sudo usermod -aG uucp $(USER) #Use specific command and group
-else
- sudo adduser $(USER) dialout
-endif
-
-# easy printing of MAKE VARIABLES
-print-%: ; @echo $* = $($*)
-
-style:
- # Make sure astyle is installed
- @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
- # Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
- find . \( -not -path "./cov-int/*" -and \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \) \
- -exec perl -pi -e 's/[ \t]+$$//' {} \; \
- -exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
- -exec sh -c "echo >> {}" \;
- # Apply astyle on *.c, *.h, *.cpp
- find . \( -not -path "./cov-int/*" -and \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) \) \) -exec astyle --formatted --mode=c --suffix=none \
- --indent=spaces=4 --indent-switches \
- --keep-one-line-blocks --max-instatement-indent=60 \
- --style=google --pad-oper --unpad-paren --pad-header \
- --align-pointer=name {} \;
-
-# Detecting weird codepages and tabs.
-checks:
- @echo "Files with suspicious chars:"
- @find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \
- -exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \;
- @echo "Files with tabs:"
-# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq'
- @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
- -exec grep -lP '\t' {} \;
-# @echo "Files with printf \\\\t:"
-# @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
-# -exec grep -lP '\\t' {} \;
-
-# Dummy target to test for GNU make availability
-_test:
diff --git a/pm3rdv4rrg/src/main/cpp/Makefile.defs b/pm3rdv4rrg/src/main/cpp/Makefile.defs
deleted file mode 100644
index 4068d751..00000000
--- a/pm3rdv4rrg/src/main/cpp/Makefile.defs
+++ /dev/null
@@ -1,46 +0,0 @@
-# Hide full compilation line:
-ifneq ($(V),1)
- Q?=@
-endif
-# To see full command lines, use make V=1
-
-# been here
-DEFSBEENHERE = true
-
-CP = cp -a
-GZIP = gzip
-MKDIR = mkdir -p
-RM = rm -f
-RMDIR = rm -rf
-# rmdir only if dir is empty, tolerate failure
-RMDIR_SOFT = -rmdir
-MV = mv
-TOUCH = touch
-FALSE = false
-TAR = tar
-TARFLAGS ?= -v --ignore-failed-read -r
-TARFLAGS += -C .. -f
-CROSS ?= arm-none-eabi-
-CC = gcc
-CXX = g++
-LD = g++
-
-PATHSEP=/
-PREFIX ?= /usr/local
-UDEV_PREFIX ?= /etc/udev/rules.d
-INSTALLBINRELPATH ?= bin
-INSTALLSHARERELPATH ?= share/proxmark3
-INSTALLFWRELPATH ?= share/proxmark3/firmware
-INSTALLTOOLSRELPATH ?= share/proxmark3/tools
-INSTALLDOCSRELPATH ?= share/doc/proxmark3
-
-platform = $(shell uname)
-DETECTED_OS=$(platform)
-
-ifeq ($(platform),Darwin)
- AR= /usr/bin/ar rcs
- RANLIB= /usr/bin/ranlib
-else
- AR= ar rcs
- RANLIB= ranlib
-endif
diff --git a/pm3rdv4rrg/src/main/cpp/Makefile.host b/pm3rdv4rrg/src/main/cpp/Makefile.host
deleted file mode 100644
index 6d405ee1..00000000
--- a/pm3rdv4rrg/src/main/cpp/Makefile.host
+++ /dev/null
@@ -1,79 +0,0 @@
-# This Makefile might have been called from various subdirs, trying to find our Makefile.defs
-ifeq ($(DEFSBEENHERE),)
- -include Makefile.defs
-endif
-ifeq ($(DEFSBEENHERE),)
- -include ../Makefile.defs
-endif
-ifeq ($(DEFSBEENHERE),)
- -include ../../Makefile.defs
-endif
-ifeq ($(DEFSBEENHERE),)
- -include ../../../Makefile.defs
-endif
-ifeq ($(DEFSBEENHERE),)
- $(error Can't find Makefile.defs)
-endif
-
-CFLAGS ?= -Wall -Werror -O3
-CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES)
-
-vpath %.c $(MYSRCPATHS)
-
-# Flags to generate temporary dependency files
-DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
-# make temporary to final dependency files after successful compilation
-POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
-
-BINDIR := .
-OBJDIR := obj
-
-MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o)
-CLEAN = $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
-
-all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
-
-clean:
- $(Q)$(RM) $(CLEAN)
- $(Q)$(RMDIR) $(OBJDIR)
-
-install: all
-ifneq (,$(INSTALLTOOLS))
- $(info [@] Installing $(BINS) to $(DESTDIR)$(PREFIX)...)
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
- $(Q)$(CP) $(INSTALLTOOLS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
-endif
- @true
-
-uninstall:
-ifneq (,$(INSTALLTOOLS))
- $(info [@] Uninstalling $(BINS) from $(DESTDIR)$(PREFIX)...)
- $(Q)$(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
-endif
- @true
-
-.PHONY: all clean install uninstall
-
-$(BINDIR)/$(LIB_A): $(MYOBJS)
- $(info [=] AR $(notdir $@))
- $(Q)$(AR) $@ $(MYOBJS)
- $(Q)$(RANLIB) $@
-
-$(BINDIR)/% : $(OBJDIR)/%.o $(MYOBJS) $(MYLIBS)
- $(info [=] LD $(notdir $@))
- $(Q)$(LD) $(LDFLAGS) $(MYOBJS) $< -o $@ $(MYLIBS)
-
-$(OBJDIR)/%.o : %.c | $(OBJDIR)
- $(info [-] CC $<)
- $(Q)$(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $<
- $(Q)$(POSTCOMPILE)
-
-$(OBJDIR):
- $(Q)$(MKDIR) $(OBJDIR)
-
-DEPENDENCY_FILES = $(MYOBJS:%.o=%.d) $(BINS:%=$(OBJDIR)/%.d)
-
-$(DEPENDENCY_FILES): ;
-.PRECIOUS: $(DEPENDENCY_FILES)
-
--include $(DEPENDENCY_FILES)
diff --git a/pm3rdv4rrg/src/main/cpp/Makefile.platform.sample b/pm3rdv4rrg/src/main/cpp/Makefile.platform.sample
deleted file mode 100644
index 57a6f106..00000000
--- a/pm3rdv4rrg/src/main/cpp/Makefile.platform.sample
+++ /dev/null
@@ -1,7 +0,0 @@
-# If you want to use it, copy this file as Makefile.platform and adjust it to your needs
-# Run 'make PLATFORM=' to get an exhaustive list of possible parameters for this file.
-
-PLATFORM=PM3RDV4
-# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
-PLATFORM_EXTRAS=BTADDON
-#STANDALONE=LF_SAMYRUN
diff --git a/pm3rdv4rrg/src/main/cpp/README.md b/pm3rdv4rrg/src/main/cpp/README.md
deleted file mode 100644
index 96a8d269..00000000
--- a/pm3rdv4rrg/src/main/cpp/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# RRG / Iceman repo - Proxmark3
-
-
-| Releases | Linux & OSX CI | Windows CI | Coverity |
-| ------------------- |:-------------------:| -------------------:| -------------------:|
-| [](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [](https://travis-ci.org/RfidResearchGroup/proxmark3) | [](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) | [](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo)|
-
-
-
-# PROXMARK INSTALLATION AND OVERVIEW
-
-| FAQ's & Updates | Installation | Use of the Proxmark |
-| ------------------- |:-------------------:| -------------------:|
-|[What has changed?](#what-has-changed) | [Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
-|[Development](#development) | [Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
-|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
-|[Proxmark3 GUI](#proxmark3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
-|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) |[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|
-|[Notes on UART](/doc/uart_notes.md)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)|
-|[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)|
-|[Notes on external flash](/doc/ext_flash_notes.md)||[EMV](/doc/emv_notes.md)|
-|[Notes on Termux / Android](/doc/termux_notes.md)||[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)|
-|[Notes on wireshark / tracedata](/doc/trace_wireshark_notes.md)||[JTAG](/doc/jtag_notes.md)|
-|[Notes on loclass](/doc/loclass_notes.md)||[Complete client command set](/doc/commands.md)|
-|[Notes on paths](/doc/path_notes.md)|||
-|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) ||
-|[Donations](#Donations)|||
-
-
-## Build for non-RDV4 Proxmark3 platforms
-
-In order to build this repo for other Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)
-
-
-## What has changed?
-
-On the hardware side:
-
- * added flash memory 256kb.
- * added smart card module
- * added FPC connector
-
-On the software side: quite a lot, see the [Changelog file](CHANGELOG.md).
-
-## Development
-
-> ⚠ **Note**: This is a bleeding edge repository. The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so **DO expect significant changes to code layout on a regular basis**.
-
-This repo compiles nicely on
- - Proxspace v3.2
- - Windows/mingw environment with Qt5.6.1 & GCC 4.8
- - Ubuntu 1404, 1510, 1604, 1804, 1904
- - Mac OS X / Homebrew
- - ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora
- - WSL, WSL2 (Windows subsystem linux) on Windows 10
- - Docker container
-
-The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing.
-
-> 👉 **Remember!** If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first.
-We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards.
-
-## Notes / helpful documents
-- notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md).
-- notes on [UART](/doc/uart_notes.md)
-- notes on [Frame format](/doc/new_frame_format.md)
-- notes on [external flash](/doc/ext_flash_notes.md)
-- notes on [standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)
-- notes on [Termux / Android](/doc/termux_notes.md)
-- notes on [Wireshark / tracedata](/doc/trace_wireshark_notes.md)
-- notes on [loclass](/doc/loclass_notes.md)
-- notes on [EMV](/doc/emv_notes.md)
-- notes on [Paths](/doc/path_notes.md)
-- notes on [file formats used with Proxmark3](/doc/extensions_notes.md)
-## Cheat sheet
-
-Thanks to Alex Dibs, you can enjoy a [command cheat sheet](/doc/cheatsheet.md)
-
-## Maintainers ( package, distro )
-
-To all distro, package maintainers, we tried to make your life easier. `make install` is now available and if you want to know more.
-- [Maintainers](/doc/md/Development/Maintainers.md)
-
-## Why didn't you base it on official Proxmark3 Master?
-
-The separation from official Proxmark3 repo gives us a lot of freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the official Proxmark3 repo with RDV40 specific code.
-
-## Proxmark3 GUI
-
-The official PM3-GUI from Gaucho will not work.
-The new universal GUI will work. [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) Almost, change needed in order to show helptext when client isn't connected to a device.
-
-## Issues
-
-Please see the [Proxmark Forum](http://www.proxmark.org/forum/index.php) and see if your issue is listed in the first instance Google is your friend :) Questions will be answered via the forum by Iceman and the team.
-
-Read the [Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md) guide to weed out most known problems.
-
-
-## The end
-
-- July 2018 [@herrmann1001](https://mobile.twitter.com/herrmann1001)
-- updated Feb 2019 [@5w0rdfish](https://mobile.twitter.com/5w0rdFish)
-- updated 2019 [@doegox](https://mobile.twitter.com/doegox)
-
-# Donations
-
-Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards.
-
-https://www.patreon.com/iceman1001
-
diff --git a/pm3rdv4rrg/src/main/cpp/appveyor.yml b/pm3rdv4rrg/src/main/cpp/appveyor.yml
deleted file mode 100644
index b2ab84fb..00000000
--- a/pm3rdv4rrg/src/main/cpp/appveyor.yml
+++ /dev/null
@@ -1,412 +0,0 @@
-version: 3.0.1.{build}
-image: Visual Studio 2017
-clone_folder: C:\ProxSpace\pm3
-init:
-- ps: >-
- $psversiontable
-
- #Get-ChildItem Env:
-
-
- $releasename=""
-
- $env:APPVEYOR_REPO_COMMIT_SHORT = $env:APPVEYOR_REPO_COMMIT.Substring(0, 8)
-
- if ($env:appveyor_repo_tag -match "true"){
- $releasename=$env:APPVEYOR_REPO_TAG_NAME + "/"
- }
-
- $releasename+=$env:APPVEYOR_BUILD_VERSION + " [" + $env:APPVEYOR_REPO_COMMIT_SHORT + "]"
-
-
- Write-Host "repository: $env:appveyor_repo_name branch:$env:APPVEYOR_REPO_BRANCH release: $releasename" -ForegroundColor Yellow
-
- Add-AppveyorMessage -Message "[$env:APPVEYOR_REPO_COMMIT_SHORT]$env:appveyor_repo_name($env:APPVEYOR_REPO_BRANCH)" -Category Information -Details "repository: $env:appveyor_repo_name branch: $env:APPVEYOR_REPO_BRANCH release: $releasename"
-
-
- iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
-clone_script:
-- ps: >-
- Write-Host "Removing ProxSpace..." -NoNewLine
-
- cd \
-
- Remove-Item -Recurse -Force -Path c:\ProxSpace\*
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- Write-Host "Git clone ProxSpace..." -NoNewLine
-
- git clone -q https://github.com/Gator96100/ProxSpace c:\ProxSpace
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- if(!(Test-Path -Path C:\ProxSpace\pm3)){
-
- New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3
-
- }
-
- Write-Host "Removing pm3 dir..." -NoNewLine
-
- Remove-Item -Recurse -Force -Path c:\ProxSpace\pm3\*
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- Write-Host "Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." -NoNewLine
-
- if(-not $env:appveyor_pull_request_number) {
- git clone -q --branch=$env:appveyor_repo_branch https://github.com/$env:appveyor_repo_name.git $env:appveyor_build_folder
- cd $env:appveyor_build_folder
- git checkout -qf $env:appveyor_repo_commit
- } else {
- git clone -q https://github.com/$env:appveyor_repo_name.git $env:appveyor_build_folder
- cd $env:appveyor_build_folder
- git fetch -q origin +refs/pull/$env:appveyor_pull_request_number/merge:
- git checkout -qf FETCH_HEAD
- }
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- Write-Host "Fill msys2\etc\fstab file..." -NoNewLine
-
- New-Item c:\ProxSpace\msys2\etc\fstab -type file -force -value "# For a description of the file format, see the Users Guide`n# http://cygwin.com/cygwin-ug-net/using.html#mount-table`nnone / cygdrive binary,posix=0,noacl,user 0 0 `nC:\ProxSpace\pm3 /pm3 ntfs noacl 0 0 `nC:\ProxSpace\gcc-arm-none-eabi /gcc-arm-none-eabi ntfs noacl 0 0 `n"
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- Write-Host "Update msys2 packages..."
-
- $env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
-
- Function ExecUpdate($Name, $Cmd, $ErrorLine) {
-
- Write-Host "Exec [$Name]... " -NoNewLine
- #--- begin Job
-
- $Job = Start-Job -Name "$Name" -ScriptBlock {
- $env:Path = "C:\ProxSpace\msys\bin;$env:Path"
- Set-Location $using:PWD
-
- $sb=[scriptblock]::Create("$using:Cmd")
- #execute scriptblock
- $Cond=&$sb
-
- return $Cond
- }
-
- #--- end Job
-
- $JobTime=[System.Environment]::TickCount
- while($true) {
- Try {
- $Res = Receive-Job -Job $Job -Keep 2>&1 6>&1
- }
- Catch {
- $Res = ""
- Write-host "error in Receive-Job"
- }
-
- if ($Res -is "String" -and $Res -like "*$ErrorLine*"){
- Write-host "Exit by stop phrase" -ForegroundColor Green
- break
- }
-
- if ($Res -is [Object]){
- [bool]$needexit = $false
- ForEach($line in $Res){
- if ($line -like "*$ErrorLine*"){
- Write-host "Exit by stop phrase [obj]" -ForegroundColor Green
- $needexit = $true
- break
- }
- }
- if ($needexit) {
- break
- }
- }
-
- if(Wait-Job $Job -Timeout 5){
- Write-host "Exit by end job" -ForegroundColor Green
- break
- }
-
- if ([System.Environment]::TickCount-$JobTime -gt 1000000) {
- Write-host "Exit by timeout" -ForegroundColor Yellow
- break
- }
- }
-
- Remove-Job -Force $Job
- }
-
- cd C:\ProxSpace\
-
- C:\ProxSpace\msys2\ps\setup.cmd
-
- ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
-
- ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
-
- Write-Host "Update " -NoNewLine
-
- Write-Host "[ OK ]" -ForegroundColor Green
-install:
-- ps: >-
- function Exec-External {
- param(
- [Parameter(Position=0,Mandatory=1)][scriptblock] $command
- )
- & $command
- if ($LASTEXITCODE -ne 0) {
- throw ("Command returned non-zero error-code ${LASTEXITCODE}: $command")
- }
- }
-build_script:
-- ps: >-
- "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
-
-
- $env:MINGW_HOME="C:\ProxSpace\msys2\mingw32"
-
- $env:MSYS_HOME="C:\ProxSpace\msys2"
-
- $env:MSYSTEM="MINGW32"
-
- $env:MINGW_PREFIX="/mingw32"
-
- $env:SHELL="/bin/bash"
-
- $env:MSYSTEM_CHOST="i686-w64-mingw32"
-
- cd C:\ProxSpace\pm3
-
- #make
-
- bash -c -i 'pwd;make clean;make all'
-
-
- #some checks
-
- if(!(Test-Path C:\ProxSpace\pm3\client\proxmark3.exe)){
-
- throw "Main file proxmark3.exe not exists."
-
- }
-
- if(!(Test-Path C:\ProxSpace\pm3\armsrc\obj\fullimage.elf)){
-
- throw "ARM file fullimage.elf not exists."
-
- }
-
- if(!(Test-Path C:\ProxSpace\pm3\client\resources\hardnested_tables\*.bin.z)){
-
- throw "Files in client\resources\hardnested_tables is not exists."
-
- }
-
-
- #install
-
- Write-Host "Installing..." -NoNewLine -ForegroundColor Yellow
-
- New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3\Release\bin
-
- bash -c -i 'make install DESTDIR=Release PREFIX='
-
- # dll files
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\pm3\Release\bin
-
- Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\pm3\Release\bin
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- #archive and push
-
- $releasename=""
-
- if ($env:appveyor_repo_tag -match "true"){
-
- $releasename=$env:APPVEYOR_REPO_TAG_NAME + "/"
-
- }
-
- $releasename+=$env:APPVEYOR_BUILD_VERSION + " [" + $env:APPVEYOR_REPO_COMMIT.Substring(0, 7) + "]"
-
-
- Write-Host "Archive and publish release files ($releasename)..." -NoNewLine -ForegroundColor Yellow
-
- cd C:\ProxSpace
-
- 7z a release.zip C:\ProxSpace\pm3\Release
-
- Push-AppveyorArtifact release.zip -DeploymentName "$releasename"
-
- Write-Host "[ OK ]" -ForegroundColor Green
-
-
- Write-Host "Builded..." -ForegroundColor Yellow
-test_script:
-- ps: >-
- $env:Path = "C:\ProxSpace\msys\bin;$env:Path"
-
- cd c:\ProxSpace\pm3
-
-
- $global:TestsPassed=$true
-
-
- Function ExecTest($Name, $File, $Cmd, $CheckResult) {
-
- #--- begin Job
-
- $Job = Start-Job -ScriptBlock {
- [bool]$res=$false
- $TestTime=[System.Environment]::TickCount
- $env:Path = "C:\ProxSpace\msys\bin;$env:Path"
- Set-Location $using:PWD
-
- $sb=[scriptblock]::Create("$using:Cmd")
- #execute scriptblock
- Write-host "Test [$using:Name] job: $using:Cmd"
- $Cond=&$sb
-
- if ($Cond -eq $null){
- } ElseIf($using:CheckResult -ne $null) {
- [String]$searchstr=""
- if ($Cond -is [Object]){
- ForEach($line in $Cond){
- Write-host $line -ForegroundColor Gray
- $searchstr += $line
- }
- }else{
- Write-host "$Cond" -ForegroundColor Gray
- $searchstr = $Cond
- }
- If($searchstr -like "*$using:CheckResult*") {
- $res=$true
- }
- $Cond="*$using:CheckResult*"
- } Else {
- If (!($Cond -is [bool] -or $Cond -is [byte] -or $Cond -is [int16] -or $Cond -is [int32] -or $Cond -is [int64] -or $Cond -is [float])){
- if ($Cond -is "String" -and $Cond -like "*passed*"){
- $res= $true
- }
- if ($Cond -is "String" -and $Cond -like "*true*"){
- $res= $true
- }
- ForEach($line in $Cond){
- if ($line -like "*passed*"){
- $res = $true
- $Cond = $line
- break
- }
- }
- } Else {
- $res=$Cond
- }
- }
-
- If ($res) {
- Write-host "Result[$using:Name]: $Cond" -ForegroundColor Green
- Add-AppveyorTest -Name "$using:Name" -Framework NUnit -Filename "$using:File" -Outcome Passed -Duration "$([System.Environment]::TickCount-$TestTime)"
- }Else {
- Write-host "Result[$using:Name]: $Cond" -ForegroundColor Red
- Add-AppveyorTest -Name "$using:Name" -Framework NUnit -Filename "$using:File" -Outcome Failed -Duration "$([System.Environment]::TickCount-$TestTime)" -ErrorMessage "command:$using:Cmd`nresult:$Cond"
- }
- return $res
- }
-
- #--- end Job
-
- [bool]$res=$false
- # Wait 180 sec timeout for Job
- if(Wait-Job $Job -Timeout 180){
- $Results = $Job | Receive-Job
- if($Results -like "true"){
- $res=$true
- }
- } else {
- Write-host "Test [$Name] timeout" -ForegroundColor Red
- Add-AppveyorTest -Name "$Name" -Framework NUnit -Filename "$File" -Outcome Failed -Duration 60000 -ErrorMessage "timeout"
- }
- Remove-Job -Force $Job
-
- if(!$res){
- Write-host "--------------------- tests fail" -ForegroundColor Red
- $global:TestsPassed=$false
- }
- }
-
-
- Write-Host "Running tests..." -ForegroundColor Yellow
-
-
- #file test
-
- ExecTest "proxmark3 exists" "proxmark3.exe" {Test-Path C:\ProxSpace\pm3\Release\bin\proxmark3.exe}
-
- ExecTest "arm bootrom exists" "bootrom.elf" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\bootrom.elf}
-
- ExecTest "arm image exists" "fullimage.elf" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\fullimage.elf}
-
- ExecTest "arm recovery image exists" "proxmark3_recovery.bin" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\proxmark3_recovery.bin}
-
- ExecTest "hardnested tables exists" "hardnested" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\resources\hardnested_tables\*.z}
-
- ExecTest "release exists" "release.zip" {Test-Path C:\ProxSpace\release.zip}
-
-
- #proxmark logic tests
-
- ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h 2>&1 | grep -q wait && echo passed || echo failed'}
-
- ExecTest "proxmark help text ISO7816" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q ISO7816 && echo passed || echo failed'}
-
- ExecTest "proxmark help text hardnested" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q hardnested && echo passed || echo failed'}
-
-
- ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf'"} "at_enc"
-
- #proxmark crypto tests
-
- # Long tests:
- # ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:"
- # ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t l'"} "verified ok"
- # ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test -i -l'"} "Test?s? ? OK"
- # Short tests:
- ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t'"} "OK!"
- ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test -i'"} "Test?s? ? OK"
-
-
- if ($global:TestsPassed) {
- Write-Host "Tests [ OK ]" -ForegroundColor Green
- } else {
- Write-Host "Tests [ ERROR ]" -ForegroundColor Red
- throw "Tests error."
- }
-on_success:
-- ps: Write-Host "Build success..." -ForegroundColor Green
-on_failure:
-- ps: Write-Host "Build error." -ForegroundColor Red
-on_finish:
-- ps: $blockRdp = $false; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/BigBuf.c b/pm3rdv4rrg/src/main/cpp/armsrc/BigBuf.c
deleted file mode 100644
index 765d230a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/BigBuf.c
+++ /dev/null
@@ -1,212 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// BigBuf and functions to allocate/free parts of it.
-//-----------------------------------------------------------------------------
-#include "BigBuf.h"
-
-#include "string.h"
-#include "dbprint.h"
-
-// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
-// Also used to hold various smaller buffers and the Mifare Emulator Memory.
-// declare it as uint32_t to achieve alignment to 4 Byte boundary
-static uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)];
-
-/* BigBuf memory layout:
-Pointer to highest available memory: BigBuf_hi
-
- high BIGBUF_SIZE
- reserved = BigBuf_malloc() subtracts amount from BigBuf_hi,
- low 0x00
-*/
-
-// High memory mark
-static uint16_t BigBuf_hi = BIGBUF_SIZE;
-
-// pointer to the emulator memory.
-static uint8_t *emulator_memory = NULL;
-
-// trace related variables
-static uint32_t traceLen = 0;
-static bool tracing = true; //todo static?
-
-// get the address of BigBuf
-uint8_t *BigBuf_get_addr(void) {
- return (uint8_t *)BigBuf;
-}
-
-// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
-uint8_t *BigBuf_get_EM_addr(void) {
- // not yet allocated
- if (emulator_memory == NULL)
- emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
-
- return emulator_memory;
-}
-
-// clear ALL of BigBuf
-void BigBuf_Clear(void) {
- BigBuf_Clear_ext(true);
-}
-
-// clear ALL of BigBuf
-void BigBuf_Clear_ext(bool verbose) {
- memset(BigBuf, 0, BIGBUF_SIZE);
- if (verbose)
- Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE);
-}
-
-void BigBuf_Clear_EM(void) {
- memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE);
-}
-
-void BigBuf_Clear_keep_EM(void) {
- memset(BigBuf, 0, BigBuf_hi);
-}
-
-// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
-// at the beginning of BigBuf is always for traces/samples
-uint8_t *BigBuf_malloc(uint16_t chunksize) {
- if (BigBuf_hi - chunksize < 0)
- return NULL; // no memory left
-
- chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
- BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
- return (uint8_t *)BigBuf + BigBuf_hi;
-}
-
-// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
-void BigBuf_free(void) {
- BigBuf_hi = BIGBUF_SIZE;
- emulator_memory = NULL;
- // shouldn't this empty BigBuf also?
-}
-
-// free allocated chunks EXCEPT the emulator memory
-void BigBuf_free_keep_EM(void) {
- if (emulator_memory != NULL)
- BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
- else
- BigBuf_hi = BIGBUF_SIZE;
-
- // shouldn't this empty BigBuf also?
-}
-
-void BigBuf_print_status(void) {
- DbpString(_BLUE_("Memory"));
- Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
- Dbprintf(" Available memory........%d", BigBuf_hi);
- DbpString(_BLUE_("Tracing"));
- Dbprintf(" tracing ................%d", tracing);
- Dbprintf(" traceLen ...............%d", traceLen);
-}
-
-// return the maximum trace length (i.e. the unallocated size of BigBuf)
-uint16_t BigBuf_max_traceLen(void) {
- return BigBuf_hi;
-}
-
-void clear_trace(void) {
- traceLen = 0;
-}
-
-void set_tracelen(uint32_t value) {
- traceLen = value;
-}
-
-void set_tracing(bool enable) {
- tracing = enable;
-}
-
-bool get_tracing(void) {
- return tracing;
-}
-
-/**
- * Get the number of bytes traced
- * @return
- */
-uint32_t BigBuf_get_traceLen(void) {
- return traceLen;
-}
-
-/**
- This is a function to store traces. All protocols can use this generic tracer-function.
- The traces produced by calling this function can be fetched on the client-side
- by 'hf list raw', alternatively 'hf list ' for protocol-specific
- annotation of commands/responses.
-**/
-bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) {
- if (!tracing) return false;
-
- uint8_t *trace = BigBuf_get_addr();
-
- uint32_t num_paritybytes = (iLen - 1) / 8 + 1; // number of valid paritybytes in *parity
- uint32_t duration = timestamp_end - timestamp_start;
-
- // Return when trace is full
- if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) {
- tracing = false; // don't trace any more
- return false;
- }
- // Traceformat:
- // 32 bits timestamp (little endian)
- // 16 bits duration (little endian)
- // 16 bits data length (little endian, Highest Bit used as readerToTag flag)
- // y Bytes data
- // x Bytes parity (one byte per 8 bytes data)
-
- // timestamp (start)
- trace[traceLen++] = ((timestamp_start >> 0) & 0xff);
- trace[traceLen++] = ((timestamp_start >> 8) & 0xff);
- trace[traceLen++] = ((timestamp_start >> 16) & 0xff);
- trace[traceLen++] = ((timestamp_start >> 24) & 0xff);
-
- // duration
- trace[traceLen++] = ((duration >> 0) & 0xff);
- trace[traceLen++] = ((duration >> 8) & 0xff);
-
- // data length
- trace[traceLen++] = ((iLen >> 0) & 0xff);
- trace[traceLen++] = ((iLen >> 8) & 0xff);
-
- // readerToTag flag
- if (!readerToTag) {
- trace[traceLen - 1] |= 0x80;
- }
-
- // data bytes
- if (btBytes != NULL && iLen != 0) {
- memcpy(trace + traceLen, btBytes, iLen);
- }
- traceLen += iLen;
-
- // parity bytes
- if (num_paritybytes != 0) {
- if (parity != NULL) {
- memcpy(trace + traceLen, parity, num_paritybytes);
- } else {
- memset(trace + traceLen, 0x00, num_paritybytes);
- }
- }
- traceLen += num_paritybytes;
-
- return true;
-}
-
-// Emulator memory
-uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {
- uint8_t *mem = BigBuf_get_EM_addr();
- if (offset + length < CARD_MEMORY_SIZE) {
- memcpy(mem + offset, data, length);
- return 0;
- }
- Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE);
- return 1;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/BigBuf.h b/pm3rdv4rrg/src/main/cpp/armsrc/BigBuf.h
deleted file mode 100644
index ad967c4c..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/BigBuf.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// BigBuf and functions to allocate/free parts of it.
-//-----------------------------------------------------------------------------
-
-#ifndef __BIGBUF_H
-#define __BIGBUF_H
-
-#include "common.h"
-
-#define BIGBUF_SIZE 40000
-#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
-#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
-#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
-#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
-#define CARD_MEMORY_SIZE 4096
-#define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!?
-
-uint8_t *BigBuf_get_addr(void);
-uint8_t *BigBuf_get_EM_addr(void);
-uint16_t BigBuf_max_traceLen(void);
-void BigBuf_Clear(void);
-void BigBuf_Clear_ext(bool verbose);
-void BigBuf_Clear_keep_EM(void);
-void BigBuf_Clear_EM(void);
-uint8_t *BigBuf_malloc(uint16_t);
-void BigBuf_free(void);
-void BigBuf_free_keep_EM(void);
-void BigBuf_print_status(void);
-uint32_t BigBuf_get_traceLen(void);
-void clear_trace(void);
-void set_tracing(bool enable);
-void set_tracelen(uint32_t value);
-bool get_tracing(void);
-bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
-uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
-
-#endif /* __BIGBUF_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/LCD_disabled.c b/pm3rdv4rrg/src/main/cpp/armsrc/LCD_disabled.c
deleted file mode 100644
index 32a91792..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/LCD_disabled.c
+++ /dev/null
@@ -1,140 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LCD code
-//-----------------------------------------------------------------------------
-#include "LCD.h"
-
-void LCDSend(unsigned int data) {
- // 9th bit set for data, clear for command
- while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
- // For clarity's sake we pass data with 9th bit clear and commands with 9th
- // bit set since they're implemented as defines, se we need to invert bit
- AT91C_BASE_SPI->SPI_TDR = data ^ 0x100; // Send the data/command
-}
-
-void LCDSetXY(unsigned char x, unsigned char y) {
- LCDSend(PPASET); // page start/end ram
- LCDSend(y); // Start Page to display to
- LCDSend(131); // End Page to display to
-
- LCDSend(PCASET); // column start/end ram
- LCDSend(x); // Start Column to display to
- LCDSend(131); // End Column to display to
-}
-
-void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color) {
- LCDSetXY(x, y); // Set position
- LCDSend(PRAMWR); // Now write the pixel to the display
- LCDSend(color); // Write the data in the specified Color
-}
-
-void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color) {
- unsigned char i, j;
-
- for (i = 0; i < height; i++) { // Number of horizontal lines
- LCDSetXY(xs, ys + i); // Goto start of fill area (Top Left)
- LCDSend(PRAMWR); // Write to display
-
- for (j = 0; j < width; j++) // pixels per line
- LCDSend(color);
- }
-}
-
-void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) {
- unsigned int i;
- unsigned char mask = 0, px, py, xme, yme, offset;
- const char *data;
-
- data = font_style; // point to the start of the font table
-
- xme = *data; // get font x width
- data++;
- yme = *data; // get font y length
- data++;
- offset = *data; // get data bytes per font
-
- do {
- // point to data in table to be loaded
- data = (font_style + offset) + (offset * (int)(*lcd_string - 32));
-
- for (i = 0; i < yme; i++) {
- mask |= 0x80;
-
- for (px = x; px < (x + xme); px++) {
- py = y + i;
-
- if (*data & mask) LCDSetPixel(px, py, fcolor);
- else LCDSetPixel(px, py, bcolor);
-
- mask >>= 1;
- }
- data++;
- }
- x += xme;
-
- lcd_string++; // next character in string
-
- } while (*lcd_string != '\0'); // keep spitting chars out until end of string
-}
-
-void LCDReset(void) {
- LED_A_ON();
- SetupSpi(SPI_LCD_MODE);
- LOW(GPIO_LRST);
- SpinDelay(100);
-
- HIGH(GPIO_LRST);
- SpinDelay(100);
- LED_A_OFF();
-}
-
-void LCDInit(void) {
- int i;
-
- LCDReset();
-
- LCDSend(PSWRESET); // software reset
- SpinDelay(100);
- LCDSend(PSLEEPOUT); // exit sleep mode
- LCDSend(PBSTRON); // booster on
- LCDSend(PDISPON); // display on
- LCDSend(PNORON); // normal on
- LCDSend(PMADCTL); // rotate display 180 deg
- LCDSend(0xC0);
-
- LCDSend(PCOLMOD); // color mode
- LCDSend(0x02); // 8bpp color mode
-
- LCDSend(PSETCON); // set contrast
- LCDSend(0xDC);
-
- // clear display
- LCDSetXY(0, 0);
- LCDSend(PRAMWR); // Write to display
- i = LCD_XRES * LCD_YRES;
- while (i--) LCDSend(WHITE);
-
- // test text on different colored backgrounds
- LCDString(" The quick brown fox ", (char *)&FONT6x8, 1, 1 + 8 * 0, WHITE, BLACK);
- LCDString(" jumped over the ", (char *)&FONT6x8, 1, 1 + 8 * 1, BLACK, WHITE);
- LCDString(" lazy dog. ", (char *)&FONT6x8, 1, 1 + 8 * 2, YELLOW, RED);
- LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8, 1, 1 + 8 * 3, RED, GREEN);
- LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8, 1, 1 + 8 * 4, MAGENTA, BLUE);
- LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8, 1, 1 + 8 * 5, BLUE, YELLOW);
- LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8, 1, 1 + 8 * 6, BLACK, CYAN);
- LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8, 1, 1 + 8 * 7, BLUE, MAGENTA);
-
- // color bands
- LCDFill(0, 1 + 8 * 8, 132, 8, BLACK);
- LCDFill(0, 1 + 8 * 9, 132, 8, WHITE);
- LCDFill(0, 1 + 8 * 10, 132, 8, RED);
- LCDFill(0, 1 + 8 * 11, 132, 8, GREEN);
- LCDFill(0, 1 + 8 * 12, 132, 8, BLUE);
- LCDFill(0, 1 + 8 * 13, 132, 8, YELLOW);
- LCDFill(0, 1 + 8 * 14, 132, 8, CYAN);
- LCDFill(0, 1 + 8 * 15, 132, 8, MAGENTA);
-
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/LCD_disabled.h b/pm3rdv4rrg/src/main/cpp/armsrc/LCD_disabled.h
deleted file mode 100644
index ed765298..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/LCD_disabled.h
+++ /dev/null
@@ -1,126 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LCD code
-//-----------------------------------------------------------------------------
-
-#ifndef __LCD_H
-#define __LCD_H
-
-// The resolution of the LCD
-#define LCD_XRES 132
-#define LCD_YRES 132
-
-// 8bpp Color Mode - Some basic colors defined for ease of use
-// remember 8bpp color = 3xRed, 3xGreen & 2xBlue bits
-// organised as RRRGGGBB
-
-#define BLACK 0x00
-#define BLUE 0x03
-#define GREEN 0x1C
-#define CYAN 0x1F
-#define RED 0xE0
-#define MAGENTA 0xE3
-#define YELLOW 0xFC
-#define WHITE 0xFF
-
-// EPSON LCD command set
-#define ECASET 0x115
-#define EPWRCTR 0x120
-#define ENOP 0x125
-#define ERAMWR 0x15C
-#define ERAMRD 0x15D
-#define EPASET 0x175
-#define EEPSRRD1 0x17C
-#define EEPSRRD2 0x17D
-#define EVOLCTR 0x181
-#define ETMPGRD 0x182
-#define ESLPOUT 0x194
-#define ESLPIN 0x195
-#define EDISNOR 0x1A6
-#define EDISINV 0x1A7
-#define EPTLIN 0x1A8
-#define EPTLOUT 0x1A9
-#define EASCSET 0x1AA
-#define ESCSTART 0x1AB
-#define EDISOFF 0x1AE
-#define EDISON 0x1AF
-#define ECOMSCN 0x1BB
-#define EDATCTL 0x1BC
-#define EDISCTL 0x1CA
-#define EEPCOUT 0x1CC
-#define EEPCTIN 0x1CD
-#define ERGBSET8 0x1CE
-#define EOSCON 0x1D1
-#define EOSCOFF 0x1D2
-#define EVOLUP 0x1D6
-#define EVOLDOWN 0x1D7
-#define ERMWIN 0x1E0
-#define ERMWOUT 0x1EE
-#define EEPMWR 0x1FC
-#define EEPMRD 0x1FD
-
-// PHILIPS LCD command set
-#define PNOP 0x100
-#define PSWRESET 0x101
-#define PBSTROFF 0x102
-#define PBSTRON 0x103
-#define PRDDIDIF 0x104
-#define PRDDST 0x109
-#define PSLEEPIN 0x110
-#define PSLEEPOUT 0x111
-#define PPTLON 0x112
-#define PNORON 0x113
-#define PINVOFF 0x120
-#define PINVON 0x121
-#define PDALO 0x122
-#define PDAL 0x123
-#define PSETCON 0x125
-#define PDISPOFF 0x128
-#define PDISPON 0x129
-#define PCASET 0x12A
-#define PPASET 0x12B
-#define PRAMWR 0x12C
-#define PRGBSET 0x12D
-#define PPTLAR 0x130
-#define PVSCRDEF 0x133
-#define PTEOFF 0x134
-#define PTEON 0x135
-#define PMADCTL 0x136
-#define PSEP 0x137
-#define PIDMOFF 0x138
-#define PIDMON 0x139
-#define PCOLMOD 0x13A
-#define PSETVOP 0x1B0
-#define PBRS 0x1B4
-#define PTRS 0x1B6
-#define PFINV 0x1B9
-#define PDOR 0x1BA
-#define PTCDFE 0x1BD
-#define PTCVOPE 0x1BF
-#define PEC 0x1C0
-#define PSETMUL 0x1C2
-#define PTCVOPAB 0x1C3
-#define PTCVOPCD 0x1C4
-#define PTCDF 0x1C5
-#define PDF8C 0x1C6
-#define PSETBS 0x1C7
-#define PRDTEMP 0x1C8
-#define PNLI 0x1C9
-#define PRDID1 0x1DA
-#define PRDID2 0x1DB
-#define PRDID3 0x1DC
-#define PSFD 0x1EF
-#define PECM 0x1F0
-
-void LCDSend(unsigned int data);
-void LCDInit(void);
-void LCDReset(void);
-void LCDSetXY(unsigned char x, unsigned char y);
-void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color);
-void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor);
-void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Makefile b/pm3rdv4rrg/src/main/cpp/armsrc/Makefile
deleted file mode 100644
index 12819c3d..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Makefile
+++ /dev/null
@@ -1,239 +0,0 @@
-# This code is licensed to you under the terms of the GNU GPL, version 2 or,
-# at your option, any later version. See the LICENSE.txt file for the text of
-# the license.
-#-----------------------------------------------------------------------------
-# Makefile for armsrc, see ../common_arm/Makefile.common for common settings
-#-----------------------------------------------------------------------------
-
-# This Makefile might have been called directly, not via the root Makefile, so:
-ifeq ($(PLTNAME),)
- -include ../Makefile.platform
- -include ../.Makefile.options.cache
- include ../common_arm/Makefile.hal
-# detect if there were changes in the platform definitions, requiring a clean
- ifeq ($(PLATFORM_CHANGED), true)
- $(error platform definitions have been changed, please "make clean" at the root of the project)
- endif
-endif
-
-#remove one of the following defines and comment out the relevant line
-#in the next section to remove that particular feature from compilation.
-# NO space,TABs after the "\" sign.
-APP_CFLAGS = $(PLATFORM_DEFS) \
- -DON_DEVICE \
- -fno-strict-aliasing -ffunction-sections -fdata-sections
-
-SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
-SRC_ISO15693 = iso15693.c iso15693tools.c
-SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
-#UNUSED: mifaresniff.c desfire_crypto.c
-SRC_ISO14443b = iso14443b.c
-SRC_FELICA = felica.c
-SRC_CRAPTO1 = crypto1.c des.c desfire_key.c mifaredesfire.c aes.c platform_util.c
-SRC_CRC = crc.c crc16.c crc32.c
-SRC_ICLASS = iclass.c optimized_cipher.c
-SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
-SRC_NFCBARCODE = thinfilm.c
-
-# SRC_BEE = bee.c
-
-# RDV40 related hardware support
-ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS)))
- SRC_FLASH = flashmem.c
- SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c
-else
- SRC_FLASH =
- SRC_SPIFFS =
-endif
-
-ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
- SRC_SMARTCARD = i2c.c
-else
- SRC_SMARTCARD =
-endif
-
-ifneq (,$(findstring WITH_FPC_USART,$(APP_CFLAGS)))
- SRC_FPC = usart.c
-else
- SRC_FPC =
-endif
-
-ifneq (,$(findstring WITH_HITAG,$(APP_CFLAGS)))
- SRC_HITAG = hitag2_crypto.c hitag2.c hitagS.c
-else
- SRC_HITAG =
-endif
-
-ifneq (,$(findstring WITH_LCD,$(APP_CFLAGS)))
- SRC_LCD = fonts.c LCD.c
-else
- SRC_LCD =
-endif
-
-# Generic standalone Mode injection of source code
-include Standalone/Makefile.inc
-
-#the FPGA bitstream files. Note: order matters!
-FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
-
-#the zlib source files required for decompressing the fpga config at run time
-SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c
-#additional defines required to compile zlib
-ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
-APP_CFLAGS += $(ZLIB_CFLAGS)
-# zlib includes:
-APP_CFLAGS += -I../common/zlib
-
-# stdint.h provided locally until GCC 4.5 becomes C99 compliant,
-# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
-APP_CFLAGS += -I. -fno-stack-protector -fno-pie
-
-# Compile these in thumb mode (small size)
-THUMBSRC = start.c \
- $(SRC_LCD) \
- $(SRC_ISO15693) \
- $(SRC_NFCBARCODE) \
- $(SRC_LF) \
- $(SRC_ZLIB) \
- $(SRC_LEGIC) \
- $(SRC_FLASH) \
- $(SRC_SMARTCARD) \
- $(SRC_FPC) \
- $(SRC_HITAG) \
- $(SRC_SPIFFS) \
- appmain.c \
- printf.c \
- dbprint.c \
- commonutil.c \
- util.c \
- string.c \
- BigBuf.c \
- ticks.c \
- clocks.c \
- hfsnoop.c
-
-
-# These are to be compiled in ARM mode
-ARMSRC = fpgaloader.c \
- $(SRC_ISO14443a) \
- $(SRC_ISO14443b) \
- $(SRC_CRAPTO1) \
- $(SRC_ICLASS) \
- $(SRC_EMV) \
- $(SRC_CRC) \
- $(SRC_FELICA) \
- $(SRC_STANDALONE) \
- parity.c \
- usb_cdc.c \
- cmd.c
-
-VERSIONSRC = version.c \
- fpga_version_info.c
-
-# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
-include ../common_arm/Makefile.common
-
-COMMON_FLAGS = -Os
-
-INSTALLFW = $(OBJDIR)/fullimage.elf
-ifneq (,$(FWTAG))
- INSTALLFWTAG = $(notdir $(INSTALLFW:%.elf=%-$(FWTAG).elf))
-else
- INSTALLFWTAG = $(notdir $(INSTALLFW))
-endif
-
-OBJS = $(OBJDIR)/fullimage.s19
-FPGA_COMPRESSOR = ../tools/fpga_compress/fpga_compress
-
-all: $(OBJS)
-
-.DELETE_ON_ERROR:
-
-# version.c should be remade on every time fullimage.stage1.elf should be remade
-version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
- $(info [-] GEN $@)
- $(Q)sh ../tools/mkversion.sh > $@ || perl ../tools/mkversion.pl > $@ || $(CP) $^ $@
-
-fpga_version_info.c: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
- $(info [-] GEN $@)
- $(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
-
-$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
- $(info [-] GEN $@)
- $(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
-
-$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
- $(info [-] GEN $@)
-ifeq ($(Q),@)
- @$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null
-else
- $(FPGA_COMPRESSOR) $(filter %.bit,$^) $@
-endif
-
-$(FPGA_COMPRESSOR):
- $(error [!] MISSING $@ => To build it, go the root of the repo and do "make $(notdir $@)")
- $(error [!] MISSING $@)
-
-$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
- $(info [=] LD $@)
- $(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
-
-$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf
- $(info [-] GEN $@)
- $(Q)$(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@
-
-$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin
- $(info [-] GEN $@)
- $(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@
-
-$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
- $(info [-] GEN $@)
- $(Q)$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
-
-$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin | $(FPGA_COMPRESSOR)
- $(info [-] GEN $@)
-ifeq ($(Q),@)
- @$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ >/dev/null
-else
- $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@
-endif
-
-$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z
- $(info [-] GEN $@)
- $(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@
-
-$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o
- $(info [=] LD $@)
- $(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^
-
-tarbin: $(OBJS)
- $(info TAR $@)
- $(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf)
-
-clean:
- $(Q)$(RM) $(DEPENDENCY_FILES)
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.o
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.elf
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.s19
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.map
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.d
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.z
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.bin
- $(Q)$(RM) version.c
-
-install: all
- $(info [@] Installing fullimage to $(DESTDIR)$(PREFIX)...)
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
- $(Q)$(CP) $(INSTALLFW) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG)
-
-uninstall:
- $(info [@] Uninstalling fullimage from $(DESTDIR)$(PREFIX)...)
- $(Q)$(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG)
-
-.PHONY: all clean help install uninstall
-help:
- @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
- @echo Possible targets:
- @echo + all - Build the full image $(OBJDIR)/fullimage.s19
- @echo + clean - Clean $(OBJDIR)
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/Makefile.hal b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/Makefile.hal
deleted file mode 100644
index 2dec4cfd..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/Makefile.hal
+++ /dev/null
@@ -1,60 +0,0 @@
-# Default standalone if no standalone specified
-DEFAULT_STANDALONE=LF_SAMYRUN
-HELP_EXAMPLE_STANDALONE=HF_YOUNG
-# (you can set explicitly STANDALONE= to disable standalone modes)
-STANDALONE?=$(DEFAULT_STANDALONE)
-STANDALONE_REQ_DEFS=
-
-define KNOWN_STANDALONE_DEFINITIONS
-+==========================================================+
-| STANDALONE | DESCRIPTION |
-+==========================================================+
-| (empty) | No standalone mode |
-+----------------------------------------------------------+
-| LF_SAMYRUN | HID26 read/clone/sim |
-| (default) | - Samy Kamkar |
-+----------------------------------------------------------+
-| LF_ICERUN | standalone mode skeleton |
-| | - iceman |
-+----------------------------------------------------------+
-| LF_PROXBRUTE | HID ProxII bruteforce |
-| | - Brad Antoniewicz |
-+----------------------------------------------------------+
-| LF_HIDBRUTE | HID corporate 1000 bruteforce |
-| | - Federico dotta & Maurizio Agazzini |
-+----------------------------------------------------------+
-| HF_YOUNG | Mifare sniff/simulation |
-| | - Craig Young |
-+----------------------------------------------------------+
-| HF_MATTYRUN | Mifare sniff/clone |
-| | - Matías A. Ré Medina |
-+----------------------------------------------------------+
-| HF_COLIN | Mifare ultra fast sniff/sim/clone |
-| (RDV4 only) | - Colin Brigato |
-+----------------------------------------------------------+
-| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
-| (RDV4 only) | storing in flashmem - Bogito |
-+----------------------------------------------------------+
-| HF_14ASNIFF | 14a sniff to flashmem |
-| (RDV4 only) | |
-+----------------------------------------------------------+
-| LF_ICEHID | LF HID collector to flashmem |
-| (RDV4 only) | |
-+----------------------------------------------------------+
-endef
-
-STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID
-STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF
-STANDALONE_MODES_REQ_SMARTCARD :=
-STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID
-ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
- STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
- ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
- STANDALONE_REQ_DEFS += -DWITH_SMARTCARD
- endif
- ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_FLASH)),)
- STANDALONE_REQ_DEFS += -DWITH_FLASH
- endif
-else ifneq ($(STANDALONE),)
- $(error Invalid STANDALONE: $(STANDALONE). $(KNOWN_DEFINITIONS))
-endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/Makefile.inc b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/Makefile.inc
deleted file mode 100644
index d4de0411..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/Makefile.inc
+++ /dev/null
@@ -1,43 +0,0 @@
-# Generic standalone Mode injection of source code
-
-SRC_STANDALONE = placeholder.c
-# WITH_STANDALONE_LF_ICERUN
-ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_icerun.c
-endif
-# WITH_STANDALONE_LF_SAMYRUN
-ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_samyrun.c
-endif
-# WITH_STANDALONE_LF_PROXBRUTE
-ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_proxbrute.c
-endif
-# WITH_STANDALONE_LF_HIDBRUTE
-ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_hidbrute.c
-endif
-# WITH_STANDALONE_HF_YOUNG
-ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
- SRC_STANDALONE = hf_young.c
-endif
-# WITH_STANDALONE_HF_MATTYRUN
-ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
- SRC_STANDALONE = hf_mattyrun.c
-endif
-# WITH_STANDALONE_HF_COLIN
-ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
- SRC_STANDALONE = vtsend.c hf_colin.c frozen.c nprintf.c
-endif
-# WITH_STANDALONE_HF_BOG
-ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
- SRC_STANDALONE = hf_bog.c
-endif
-# WITH_STANDALONE_HF_14ASNIFF
-ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
- SRC_STANDALONE = hf_14asniff.c
-endif
-# WITH_STANDALONE_LF_ICEHID
-ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_icehid.c
-endif
\ No newline at end of file
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_14asniff.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_14asniff.c
deleted file mode 100644
index d8bf6ab8..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_14asniff.c
+++ /dev/null
@@ -1,124 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright 2020 Michael Farrell
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for standalone HF/iso14a Sniff to flash
-//-----------------------------------------------------------------------------
-
-/*
- * `hf_14asniff` passively sniffs ISO14a frames, and stores them in internal
- * flash. It requires RDV4 hardware (for flash and battery).
- *
- * This module is similar to hf_bog (which only logs ULC/NTAG/ULEV1 auth).
- *
- * On entering stand-alone mode, this module will start sniffing ISO14a frames.
- * This will be stored in the normal trace buffer (ie: in RAM -- will be lost
- * at power-off).
- *
- * Short-pressing the button again will stop sniffing, and at _this_ point
- * append trace data from RAM to a file in flash (hf_14asniff.trc) and unmount.
- *
- * Once the data is saved, standalone mode will exit.
- *
- * LEDs:
- * - LED1: sniffing
- * - LED2: sniffed tag command, turns off when finished sniffing reader command
- * - LED3: sniffed reader command, turns off when finished sniffing tag command
- * - LED4: unmounting/sync'ing flash (normally < 100ms)
- *
- * To retrieve trace data from flash:
- *
- * 1. mem spiffs dump o hf_14asniff.trc f trace.trc
- * Copies trace data file from flash to your PC.
- *
- * 2. trace load trace.trc
- * Loads trace data from a file into PC-side buffers.
- *
- * 3. For ISO14a: trace list 14a 1
- * For MIFARE Classic: trace list mf 1
- *
- * Lists trace data from buffer without requesting it from PM3.
- *
- * This module emits debug strings during normal operation -- so try it out in
- * the lab connected to PM3 client before taking it into the field.
- *
- * To delete the trace data from flash:
- *
- * Caveats / notes:
- * - Trace buffer will be cleared on starting stand-alone mode. Data in flash
- * will remain unless explicitly deleted.
- * - This module will terminate if the trace buffer is full (and save data to
- * flash).
- * - Like normal sniffing mode, timestamps overflow after 5 min 16 sec.
- * However, the trace buffer is sequential, so will be in the correct order.
- */
-
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "iso14443a.h"
-#include "util.h"
-#include "spiffs.h"
-#include "appmain.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "BigBuf.h"
-
-#define HF_14ASNIFF_LOGFILE "hf_14asniff.trc"
-
-void DownloadTraceInstructions() {
- Dbprintf("");
- Dbprintf("To get the trace from flash and display it:");
- Dbprintf("1. mem spiffs dump o "HF_14ASNIFF_LOGFILE" f trace.trc");
- Dbprintf("2. trace load trace.trc");
- Dbprintf("3. trace list 14a 1");
-}
-
-void ModInfo(void) {
- DbpString("hf_14asniff: standalone 'hf 14a sniff', storing in flashmem");
- DownloadTraceInstructions();
-}
-
-void RunMod() {
- StandAloneMode();
-
- Dbprintf("Starting standalone mode: hf_14asniff");
- rdv40_spiffs_lazy_mount();
-
- SniffIso14443a(0);
-
- Dbprintf("Stopped sniffing");
- SpinDelay(200);
-
- // Write stuff to spiffs logfile
- uint32_t trace_len = BigBuf_get_traceLen();
- if (trace_len > 0) {
- Dbprintf("[!] Trace length (bytes) = %u", trace_len);
-
- uint8_t* trace_buffer = BigBuf_get_addr();
- if (!exists_in_spiffs(HF_14ASNIFF_LOGFILE)) {
- rdv40_spiffs_write(
- HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
- Dbprintf("[!] Wrote trace to "HF_14ASNIFF_LOGFILE);
- } else {
- rdv40_spiffs_append(
- HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
- Dbprintf("[!] Appended trace to "HF_14ASNIFF_LOGFILE);
- }
- } else {
- Dbprintf("[!] Trace buffer is empty, nothing to write!");
- }
-
- LED_D_ON();
- rdv40_spiffs_lazy_unmount();
- LED_D_OFF();
-
- SpinErr(LED_A, 200, 5);
- SpinDelay(100);
-
- LEDsoff();
- SpinDelay(300);
- DownloadTraceInstructions();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_bog.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_bog.c
deleted file mode 100644
index d656ad50..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_bog.c
+++ /dev/null
@@ -1,253 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for standalone HF Sniff (and ULC/NTAG/ULEV1 pwd storing)
-//-----------------------------------------------------------------------------
-
-/*
-This can actually be used in two separate ways.
-It can either be used to just HF 14a sniff on the go and/or grab the
-authentication attempts for ULC/NTAG/ULEV1 into the flash mem (RDV4).
-
-The retrieved sniffing session can be acquired by connecting the devices
-to a client that supports the reconnect capability and issue 'hf 14a list'.
-
-In order to view the grabbed authentication attempts in the flash mem,
-you can simply run 'script run read_pwd_mem' or just 'mem dump p l 256'
-from the client to view the stored quadlets.
-*/
-
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "iso14443a.h"
-#include "protocols.h"
-#include "util.h"
-#include "spiffs.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "BigBuf.h"
-#include "string.h"
-
-#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8)
-#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
-
-// Maximum number of auth attempts per standalone session
-#define MAX_PWDS_PER_SESSION 64
-
-#define HF_BOG_LOGFILE "hf_bog.log"
-
-// This is actually copied from SniffIso14443a
-void RAMFUNC SniffAndStore(uint8_t param) {
-
- iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
-
- // Allocate memory from BigBuf for some buffers
- // free all previous allocations first
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // Array to store the authpwds
- uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION);
-
- // The command (reader -> tag) that we're receiving.
- uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
- uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
-
- // The response (tag -> reader) that we're receiving.
- uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
- uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
-
- // The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
- uint8_t *data = dmaBuf;
-
- uint8_t previous_data = 0;
- int dataLen;
- bool TagIsActive = false;
- bool ReaderIsActive = false;
-
- // Set up the demodulator for tag -> reader responses.
- Demod14aInit(receivedResp, receivedRespPar);
-
- // Set up the demodulator for the reader -> tag commands
- Uart14aInit(receivedCmd, receivedCmdPar);
-
- // Setup and start DMA.
- if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) {
- if (DBGLEVEL > 1)
- Dbprintf("FpgaSetupSscDma failed. Exiting");
- return;
- }
-
- tUart14a *uart = GetUart14a();
- tDemod14a *demod = GetDemod14a();
-
- // We won't start recording the frames that we acquire until we trigger;
- // a good trigger condition to get started is probably when we see a
- // response from the tag.
- // triggered == false -- to wait first for card
- bool triggered = !(param & 0x03);
-
- uint32_t my_rsamples = 0;
-
- // Current captured passwords counter
- uint8_t auth_attempts = 0;
-
- SpinDelay(50);
-
- // loop and listen
- while (!BUTTON_PRESS()) {
- WDT_HIT();
- LED_A_ON();
-
- int register readBufDataP = data - dmaBuf;
- int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
- if (readBufDataP <= dmaBufDataP)
- dataLen = dmaBufDataP - readBufDataP;
- else
- dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP;
-
- // test for length of buffer
- if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly
- Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
- break;
- }
- if (dataLen < 1)
- continue;
-
- // primary buffer was stopped( <-- we lost data!
- if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
- AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
- // Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
- }
- // secondary buffer sets as primary, secondary buffer was stopped
- if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
- }
-
- LED_A_OFF();
-
- // Need two samples to feed Miller and Manchester-Decoder
- if (my_rsamples & 0x01) {
-
- if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
- uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
- if (MillerDecoding(readerdata, (my_rsamples - 1) * 4)) {
- LED_C_ON();
-
- // check - if there is a short 7bit request from reader
- if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7))
- triggered = true;
-
- if (triggered) {
- if ((receivedCmd) &&
- ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
- if (DBGLEVEL > 1)
- Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2],
- receivedCmd[3], receivedCmd[4]);
-
- // temporarily save the captured pwd in our array
- memcpy(&capturedPwds[4 * auth_attempts], receivedCmd + 1, 4);
- auth_attempts++;
- }
-
- if (!LogTrace(receivedCmd, uart->len, uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
- uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER, uart->parity, true))
- break;
- }
- /* ready to read another command. */
- Uart14aReset();
- /* reset the demod code, which might have been */
- /* false-triggered by the commands from the reader. */
- Demod14aReset();
- LED_B_OFF();
- }
- ReaderIsActive = (uart->state != STATE_14A_UNSYNCD);
- }
-
- // no need to try decoding tag data if the reader is sending - and we cannot afford the time
- if (!ReaderIsActive) {
- uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
- if (ManchesterDecoding(tagdata, 0, (my_rsamples - 1) * 4)) {
- LED_B_ON();
-
- if (!LogTrace(receivedResp, demod->len, demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
- demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->parity, false))
- break;
-
- if ((!triggered) && (param & 0x01))
- triggered = true;
-
- // ready to read another response.
- Demod14aReset();
- // reset the Miller decoder including its (now outdated) input buffer
- Uart14aReset();
- // UartInit(receivedCmd, receivedCmdPar);
- LED_C_OFF();
- }
- TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
- }
- }
-
- previous_data = *data;
- my_rsamples++;
- data++;
- if (data == dmaBuf + DMA_BUFFER_SIZE) {
- data = dmaBuf;
- }
- } // end main loop
-
- FpgaDisableSscDma();
- set_tracing(false);
-
- Dbprintf("Stopped sniffing");
-
- SpinDelay(200);
-
- // Write stuff to spiffs logfile
- if (auth_attempts > 0) {
- if (DBGLEVEL > 1)
- Dbprintf("[!] Authentication attempts = %u", auth_attempts);
-
- if (!exists_in_spiffs((char *)HF_BOG_LOGFILE)) {
- rdv40_spiffs_write((char *)HF_BOG_LOGFILE, capturedPwds, 4 * auth_attempts, RDV40_SPIFFS_SAFETY_SAFE);
- } else {
- rdv40_spiffs_append((char *)HF_BOG_LOGFILE, capturedPwds, 4 * auth_attempts, RDV40_SPIFFS_SAFETY_SAFE);
- }
- }
-
- if (DBGLEVEL > 1)
- Dbprintf("[!] Wrote %u Authentification attempts into logfile", auth_attempts);
-
- SpinErr(LED_A, 200, 5);
- SpinDelay(100);
-}
-
-void ModInfo(void) {
- DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)");
-}
-
-void RunMod() {
-
- StandAloneMode();
-
- Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<");
- Dbprintf("Starting to sniff");
-
- // param:
- // bit 0 - trigger from first card answer
- // bit 1 - trigger from first reader 7-bit request
- SniffAndStore(0);
- LEDsoff();
- SpinDelay(300);
- Dbprintf("- [ End ] -> You can take shell back ...");
- Dbprintf("- [ ! ] -> use 'script run read_pwd_mem_spiffs' to print passwords");
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_colin.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_colin.c
deleted file mode 100644
index 17997aac..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_colin.c
+++ /dev/null
@@ -1,1094 +0,0 @@
-//-----------------------------------------------------------------------------
-// Colin Brigato, 2016, 2017, 2018, 2019
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for HF Mifare aka ColinRun by Colin Brigato
-//-----------------------------------------------------------------------------
-
-#include "standalone.h" // standalone definitions
-
-#include "hf_colin.h"
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "util.h"
-#include "commonutil.h"
-#include "BigBuf.h"
-#include "iso14443a.h"
-#include "mifareutil.h"
-#include "mifaresim.h"
-#include "vtsend.h"
-#include "spiffs.h"
-#include "frozen.h"
-
-#define MF1KSZ 1024
-#define MF1KSZSIZE 64
-#define AUTHENTICATION_TIMEOUT 848
-#define HFCOLIN_LASTTAG_SYMLINK "hf_colin/lasttag.bin"
-#define HFCOLIN_SCHEMAS_JSON "hf_colin/schemas.json"
-
-/* Example jsonconfig file schemas.json : (array !)
-[{
- "name": "UrmetCaptive",
- "trigger": "0x8829da9daf76",
- "keysA": [
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76"
- ],
- "keysB": [
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76",
- "0x8829da9daf76"
- ]
-},{
- "name": "Noralsy",
-...
-
-]
-
-*/
-
-uint8_t cjuid[10];
-uint32_t cjcuid;
-iso14a_card_select_t p_card;
-int currline;
-int currfline;
-int curlline;
-
-// TODO : Implement fast read of KEYS like in RFIdea
-// also http://ext.delaat.net/rp/2015-2016/p04/report.pdf
-
-// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare
-
-static const uint8_t is_hex[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0,
- 0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static inline uint64_t hex2i(const char *s) {
- uint64_t val = 0;
- if (s == NULL || s[0] == 0)
- return 0;
- if (s[1] == 'x')
- s += 2;
- else if (*s == 'x')
- s++;
- while (is_hex[(uint8_t)*s])
- val = (val << 4) | (is_hex[(uint8_t) * (s++)] - 1);
- return val;
-}
-
-/*char *noralsy2test =
- "{\"name\":\"noralsy2\",\"trigger\":\"0x414C41524F4E\",\"keysA\":[\"0x414C41524F4E\",\"0x414C41524F4E\","
- "\"0x414C41524F4E\","
- "\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\","
- "\"0x414C41524F4E\",\"0x414C41524F4E\","
- "\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\","
- "\"0x414C41524F4E\"],\"keysB\":["
- "\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\","
- "\"0x424C41524F4E\",\"0x424C41524F4E\","
- "\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\","
- "\"0x424C41524F4E\",\"0x424C41524F4E\","
- "\"0x424C41524F4E\",\"0x424C41524F4E\"]}";*/
-
-/*char *urmetcaptive2test =
- "{\"name\":\"urmetcaptive2\",\"trigger\":\"0x8829da9daf76\",\"keysA\":[\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\"],\"keysB\":["
- "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\","
- "\"0x8829da9daf76\",\"0x8829da9daf76\"]}";*/
-
-typedef struct MFC1KSchema {
- uint8_t name[32];
- uint64_t trigger;
- uint64_t keysA[16];
- uint64_t keysB[16];
-} MFC1KSchema;
-
-#define MAX_SCHEMAS 4
-
-static void scan_keys(const char *str, int len, uint64_t *user_data) {
- struct json_token t;
- int i;
- char ks[32];
- for (i = 0; json_scanf_array_elem(str, len, "", i, &t) > 0; i++) {
- sprintf(ks, "%.*s", t.len, t.ptr);
- user_data[i] = hex2i(ks);
- }
-}
-
-MFC1KSchema Schemas[MAX_SCHEMAS];
-
-/*MFC1KSchema Noralsy = {
- .name = "Noralsy",
- .trigger = 0x414c41524f4e,
- .keysA = {0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
- 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
- 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e},
- .keysB = {0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
- 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
- 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e}};
-
-MFC1KSchema InfiHexact = {.name = "Infineon/Hexact",
- .trigger = 0x484558414354,
- .keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
- 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
- 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
- 0x484558414354},
- .keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1,
- 0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94,
- 0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f}};
-*/
-
-/*MFC1KSchema UrmetCaptive = {
- .name = "Urmet Captive",
- .trigger = 0x8829da9daf76,
- .keysA = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
- 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
- 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76},
- .keysB = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
- 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
- 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76}};
-*/
-
-int total_schemas = 0;
-
-void add_schema(MFC1KSchema *p, MFC1KSchema a, int *schemas_counter) {
- if (*schemas_counter < MAX_SCHEMAS) {
- p[*schemas_counter] = a;
- *schemas_counter += 1;
- }
-}
-
-void delete_schema(MFC1KSchema *p, int *schemas_counter, int index) {
- if (*schemas_counter > 0 && index < *schemas_counter && index > -1) {
- int last_index = *schemas_counter - 1;
- for (int i = index; i < last_index; i++) {
- p[i] = p[i + 1];
- }
- *schemas_counter -= 1;
- }
-}
-
-void cjSetCursFRight() {
- vtsend_cursor_position(NULL, 98, (currfline));
- currfline++;
-}
-
-void cjSetCursRight() {
- vtsend_cursor_position(NULL, 59, (currline));
- currline++;
-}
-
-void cjSetCursLeft() {
- vtsend_cursor_position(NULL, 0, (curlline));
- curlline++;
-}
-
-void cjTabulize() { DbprintfEx(FLAG_RAWPRINT, "\t\t\t"); }
-
-/*
-void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) {
- char tosendkey[13];
- sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4],
-foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type);
-}
-*/
-
-char *ReadSchemasFromSPIFFS(char *filename) {
- SpinOff(0);
-
- int changed = rdv40_spiffs_lazy_mount();
- uint32_t size = size_in_spiffs((char *)filename);
- uint8_t *mem = BigBuf_malloc(size);
- rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)mem, size, RDV40_SPIFFS_SAFETY_SAFE);
-
- if (changed) {
- rdv40_spiffs_lazy_unmount();
- }
- SpinOff(0);
- return (char *)mem;
-}
-
-void add_schemas_from_json_in_spiffs(char *filename) {
-
- char *jsonfile = ReadSchemasFromSPIFFS((char *)filename);
-
- int i, len = strlen(jsonfile);
- struct json_token t;
- for (i = 0; json_scanf_array_elem(jsonfile, len, "", i, &t) > 0; i++) {
- char *tmpname;
- char *tmptrigger;
- MFC1KSchema tmpscheme;
- json_scanf(t.ptr, t.len, "{ name:%Q, trigger:%Q, keysA:%M, keysB:%M}", &tmpname, &tmptrigger, scan_keys,
- &tmpscheme.keysA, scan_keys, &tmpscheme.keysB);
- memcpy(tmpscheme.name, tmpname, 32);
- tmpscheme.trigger = hex2i(tmptrigger);
- add_schema(Schemas, tmpscheme, &total_schemas);
- DbprintfEx(FLAG_NEWLINE, "Schema loaded : %s", tmpname);
- cjSetCursLeft();
- }
-}
-
-void ReadLastTagFromFlash() {
- SpinOff(0);
- LED_A_ON();
- LED_B_ON();
- LED_C_ON();
- LED_D_ON();
- uint16_t len = 1024;
- size_t size = len;
-
- DbprintfEx(FLAG_NEWLINE, "Button HELD ! Using LAST Known TAG for Simulation...");
- cjSetCursLeft();
-
- uint8_t *mem = BigBuf_malloc(size);
-
- // this one will handle filetype (symlink or not) and resolving by itself
- rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE);
-
- emlSetMem(mem, 0, 64);
-
- DbprintfEx(FLAG_NEWLINE, "[OK] Last tag recovered from FLASHMEM set to emulator");
- cjSetCursLeft();
- SpinOff(0);
- return;
-}
-
-void WriteTagToFlash(uint32_t uid, size_t size) {
- SpinOff(0);
- LED_A_ON();
- LED_B_ON();
- LED_C_ON();
- LED_D_ON();
-
- uint32_t len = size;
- uint8_t data[(size * (16 * 64)) / 1024];
-
- emlGetMem(data, 0, (size * 64) / 1024);
-
- char dest[SPIFFS_OBJ_NAME_LEN];
- uint8_t buid[4];
- num_to_bytes(uid, 4, buid);
- sprintf(dest, "hf_colin/mf_%02x%02x%02x%02x.bin", buid[0], buid[1], buid[2], buid[3]);
-
- // TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and
- // unoptimized mount operations we should manage at out level the mount status before and after the whole
- // standalone mode
- rdv40_spiffs_write((char *)dest, (uint8_t *)data, len, RDV40_SPIFFS_SAFETY_SAFE);
- // lastag will only contain filename/path to last written tag file so we don't loose time or space.
- rdv40_spiffs_make_symlink((char *)dest, (char *)HFCOLIN_LASTTAG_SYMLINK, RDV40_SPIFFS_SAFETY_SAFE);
-
- DbprintfEx(FLAG_NEWLINE, "[OK] TAG WRITTEN TO FLASH !");
- cjSetCursLeft();
- SpinOff(0);
- return;
-}
-
-void ModInfo(void) { DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); }
-
-void RunMod() {
- StandAloneMode();
-
- // add_schema(Schemas, Noralsy, &total_schemas);
- // add_schema(Schemas, InfiHexact, &total_schemas);
- // add_schema_from_json_in_spiffs((char *)HFCOLIN_URMETCAPTIVE_JSON);
- // add_schema(Schemas, UrmetCaptive, &total_schemas);
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- currline = 20;
- curlline = 20;
- currfline = 24;
- memset(cjuid, 0, sizeof(cjuid));
- cjcuid = 0;
- uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE);
- uint64_t key64; // Defines current key
- uint8_t *keyBlock; // Where the keys will be held in memory.
-
- /* VIGIK EXPIRED DUMP FOR STUDY
- Sector 0
- 121C7F730208040001FA33F5CB2D021D
- 44001049164916491649000000000000
- 00000000000000000000000000000000
- A0A1A2A3A4A579678800010203040506
- Sector 1
- 0F000000000000000000000000000000
- AA0700002102080000740C110600AF13
- 000000000000000001740C1108220000
- 314B4947495679678800010203040506
- Sector 2
- 24E572B923A3D243B402D60CAB576956
- 216D6501FC8618B6C426762511AC2DEE
- 25BF4CEC3618D0BAB3A6E9210D887746
- 314B4947495679678800010203040506
- Sector 3
- 0FBC41A5D95398E76A1B2029E8EA9735
- 088BA2CE732653D0C1147596AFCF94D7
- 77B4D91F0442182273A29DEAF7A2D095
- 314B4947495679678800010203040506
- Sector 4
- 4CEE715866E508CDBC95C640EC9D1E58
- E800457CF8B079414E1B45DD3E6C9317
- 77B4D91F0442182273A29DEAF7A2D095
- 314B4947495679678800010203040506
- 010203040506 0
- Sector 5-0F
- 00000000000000000000000000000000
- 00000000000000000000000000000000
- 00000000000000000000000000000000
- FFFFFFFFFFFFFF078069FFFFFFFFFFFF
- KEY A : 1KGIV ;
- ACCBITS : 796788[00]+VALUE
- */
-
-//----------------------------
-// Set of keys to be used.
-// This should cover ~98% of
-// French VIGIK system @2017
-//----------------------------
-
- const uint64_t mfKeys[] = {
- 0xffffffffffff, // TRANSPORTS
- 0x000000000000, // Blankkey
- 0x484558414354, // INFINEONON A / 0F SEC B / INTRATONE / HEXACT...
- 0x414c41524f4e, // ALARON NORALSY
- 0x424c41524f4e, // BLARON NORALSY
- 0x4a6352684677, // COMELIT A General Key / 08 [2] 004
- 0x536653644c65, // COMELIT B General Key / 08 [2] 004
- 0x8829da9daf76, // URMET CAPTIV IF A => ALL A/B / BTICINO
- 0x314B49474956, // "1KIGIV" VIGIK'S SERVICE BADGE A KEY
- 0xa0a1a2a3a4a5, // PUBLIC BLOC0 BTICINO MAD ACCESS
- 0x021209197591, // BTCINO UNDETERMINED SPREAKD 0x01->0x13 key
- 0x010203040506, // VIGIK's B Derivative
- 0xb0b1b2b3b4b5, // NA DERIVATE B # 1
- 0xaabbccddeeff, // NA DERIVATE B # 1
- 0x4d3a99c351dd, // NA DERIVATE B # 1
- 0x1a982c7e459a, // NA DERIVATE B # 1
- 0xd3f7d3f7d3f7, // NA DERIVATE B # 1
- 0x714c5c886e97, // NA DERIVATE B # 1
- 0x587ee5f9350f, // NA DERIVATE B # 1
- 0xa0478cc39091, // NA DERIVATE B # 1
- 0x533cb6c723f6, // NA DERIVATE B # 1
- 0x8fd0a4f256e9, // NA DERIVATE B # 1
- 0xa22ae129c013, // INFINEON B 00
- 0x49fae4e3849f, // INFINEON B 01
- 0x38fcf33072e0, // INFINEON B 02
- 0x8ad5517b4b18, // INFINEON B 03
- 0x509359f131b1, // INFINEON B 04
- 0x6c78928e1317, // INFINEON B 05
- 0xaa0720018738, // INFINEON B 06
- 0xa6cac2886412, // INFINEON B 07
- 0x62d0c424ed8e, // INFINEON B 08
- 0xe64a986a5d94, // INFINEON B 09
- 0x8fa1d601d0a2, // INFINEON B 0A
- 0x89347350bd36, // INFINEON B 0B
- 0x66d2b7dc39ef, // INFINEON B 0C
- 0x6bc1e1ae547d, // INFINEON B 0D
- 0x22729a9bd40f // INFINEON B 0E
- };
-
- // Can remember something like that in case of Bigbuf
- keyBlock = BigBuf_malloc(ARRAYLEN(mfKeys) * 6);
- int mfKeysCnt = ARRAYLEN(mfKeys);
-
- for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
- num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
- }
-
- // TODO : remember why we actually had need to initialize this array in such specific case
- // and why not a simple memset abuse to 0xffize the whole space in one go ?
- // uint8_t foundKey[2][40][6]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21
- uint8_t foundKey[2][40][6];
- for (uint16_t i = 0; i < 2; i++) {
- for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
- foundKey[i][sectorNo][0] = 0xFF;
- foundKey[i][sectorNo][1] = 0xFF;
- foundKey[i][sectorNo][2] = 0xFF;
- foundKey[i][sectorNo][3] = 0xFF;
- foundKey[i][sectorNo][4] = 0xFF;
- foundKey[i][sectorNo][5] = 0xFF;
- }
- }
-
- int key = -1;
- bool err = 0;
- bool trapped = 0;
- bool allKeysFound = true;
-
- uint32_t size = mfKeysCnt;
-
- // banner:
- vtsend_reset(NULL);
- DbprintfEx(FLAG_NEWLINE, "\r\n%s", clearTerm);
- DbprintfEx(FLAG_NEWLINE, "%s%s%s", _XCYAN_, sub_banner, _XWHITE_);
- DbprintfEx(FLAG_NEWLINE, "%s>>%s C.J.B's MifareFastPwn Started\r\n", _XRED_, _XWHITE_);
-
- currline = 20;
- curlline = 20;
- currfline = 24;
- cjSetCursLeft();
-
- add_schemas_from_json_in_spiffs((char *)HFCOLIN_SCHEMAS_JSON);
-
-failtag:
-
- vtsend_cursor_position_save(NULL);
- vtsend_set_attribute(NULL, 1);
- vtsend_set_attribute(NULL, 5);
- DbprintfEx(FLAG_NEWLINE, "\t\t\t[ Waiting For Tag ]");
- vtsend_set_attribute(NULL, 0);
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- SpinOff(50);
- LED_A_ON();
- uint8_t ticker = 0;
- // while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
- while (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
- WDT_HIT();
-
- ticker++;
- if (ticker % 64 == 0) {
- LED_A_INV();
- }
-
- if (BUTTON_HELD(10) > 0) {
- WDT_HIT();
- DbprintfEx(FLAG_NEWLINE, "\t\t\t[ READING FLASH ]");
- ReadLastTagFromFlash();
- goto readysim;
- }
- }
-
- SpinOff(50);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- vtsend_cursor_position_restore(NULL);
- DbprintfEx(FLAG_NEWLINE, "\t\t\t%s[ GOT a Tag ! ]%s", _XGREEN_, _XWHITE_);
- cjSetCursLeft();
- DbprintfEx(FLAG_NEWLINE, "\t\t\t `---> Breaking keys ---->");
- cjSetCursRight();
-
- DbprintfEx(FLAG_NEWLINE, "\t%sGOT TAG :%s %08x%s", _XRED_, _XCYAN_, cjcuid, _XWHITE_);
-
- if (cjcuid == 0) {
- cjSetCursLeft();
- DbprintfEx(FLAG_NEWLINE, "%s>>%s BUG: 0000_CJCUID! Retrying...", _XRED_, _XWHITE_);
- SpinErr(LED_A, 100, 8);
- goto failtag;
- }
-
- SpinOff(50);
- LED_B_ON();
- cjSetCursRight();
- DbprintfEx(FLAG_NEWLINE, "--------+--------------------+-------");
- cjSetCursRight();
- DbprintfEx(FLAG_NEWLINE, " SECTOR | KEY | A/B ");
- cjSetCursRight();
- DbprintfEx(FLAG_NEWLINE, "--------+--------------------+-------");
-
- uint32_t start_time = GetTickCount();
- uint32_t delta_time = 0;
-
- //---------------------------------------------------------------------------
- // WE SHOULD FIND A WAY TO GET UID TO AVOID THIS "TESTRUN"
- // --------------------------------------------------------
- // + HERE IS TO BE THOUGHT AS ONLY A KEY SHOULD BE CHECK
- // `-+ THEN WE FILL EMULATOR WITH KEY
- // `-+ WHEN WE FILL EMULATOR CARD WITH A KEY
- // `-+ IF THERE IS ANY FAIL DURING ANY POINT, WE START BACK CHECKING B KEYS
- // `-+ THEN FILL EMULATOR WITH B KEEY
- // `-+ THEN EMULATOR WITH CARD WITH B KEY
- // `-+ IF IT HAS FAILED OF ANY OF SORT THEN WE ARE MARRON LIKE POMALO.
- //----------------------------------------------------------------------------
- // AN EVEN BETTER IMPLEMENTATION IS TO CHECK EVERY KEY FOR SECTOR 0 KEY A
- // THEN IF FOUND CHECK THE SAME KEY FOR NEXT SECTOR ONLY KEY A
- // THEN IF FAIL CHECK EVERY SECTOR A KEY FOR EVERY OTHER KEY BUT NOT THE BLOCK
- // 0 KEY
- // THEN TRY TO READ B KEYS FROM KNOWN A KEYS
- // IF FAIL, CHECK SECTOR 0 B KEY WITH SECTOR 0 A KEY
- // THEN IF FOUND CHECK EVERY SECTOR FOR SAME B KEY
- // ELSE IF FAIL CHECK EVERY KEY FOR SECTOR 0 KEY B
- // THEN IF FOUND CHECK SAME KEY FOR ONLY NEXT SECTOR KEY B (PROBABLE A KEY IS
- // SAME FOR EVERY SECTOR AND B KEY IS SAME FOR EVERY SECTOR WITH JUST A vs B
- // DERIVATION
- // THEN IF B KEY IS NOT OF THIS SCHEME CHECK EVERY REMAINING B KEYED SECTOR
- // WITH EVERY REMAINING KEYS, BUT DISCARDING ANY DEFAULT TRANSPORT KEYS.
- //-----------------------------------------------------------------------------
- // also we could avoid first UID check for every block
-
- // then let's expose this optimal case of well known vigik schemes :
- for (uint8_t type = 0; type < 2 && !err && !trapped; type++) {
- for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) {
- key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64);
-
- if (key == -1) {
- err = 1;
- allKeysFound = false;
- // used in portable imlementation on microcontroller: it reports back the fail and open the
- // standalone lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
- break;
- } else if (key == -2) {
- err = 1; // Can't select card.
- allKeysFound = false;
- // reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
- break;
- } else {
- /* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */
- // uint8_t tosendkey[13];
- char tosendkey[13];
- num_to_bytes(key64, 6, foundKey[type][sec]);
- cjSetCursRight();
- DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type);
- /*reply_old(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/
-
- for (int i = 0; i < total_schemas; i++) {
- if (key64 == Schemas[i].trigger) {
-
- cjSetCursLeft();
- DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%sDetected: %s %s%s", _XORANGE_, _XCYAN_, Schemas[i].name, _XWHITE_);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_,
- _XYELLOW_, _XGREEN_);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
-
- uint16_t t = 0;
- for (uint16_t s = 0; s < sectorsCnt; s++) {
- num_to_bytes(Schemas[i].keysA[s], 6, foundKey[t][s]);
- sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1],
- foundKey[t][s][2], foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
- cjSetCursRight();
- DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
- }
- t = 1;
- for (uint16_t s = 0; s < sectorsCnt; s++) {
- num_to_bytes(Schemas[i].keysB[s], 6, foundKey[t][s]);
- sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1],
- foundKey[t][s][2], foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
- cjSetCursRight();
- DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
- }
- trapped = 1;
- break;
- }
- }
-
- /* etc etc for testing schemes quick schemes */
- }
- }
- }
-
- if (!allKeysFound) {
- cjSetCursLeft();
- cjTabulize();
- DbprintfEx(FLAG_NEWLINE, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _XRED_, _XWHITE_);
- cjSetCursLeft();
- SpinErr(LED_B, 100, 8);
- SpinOff(100);
- return;
- }
-
- /* Settings keys to emulator */
- emlClearMem();
- uint8_t mblock[16];
- for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
- emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
- for (uint8_t t = 0; t < 2; t++) {
- memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
- }
- emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
- }
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%s>>%s Setting Keys->Emulator MEM...[%sOK%s]", _XYELLOW_, _XWHITE_, _XGREEN_, _XWHITE_);
-
- /* filling TAG to emulator */
- int filled;
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%s>>%s Filling Emulator <- from A keys...", _XYELLOW_, _XWHITE_);
- filled = e_MifareECardLoad(sectorsCnt, 0);
- if (filled != PM3_SUCCESS) {
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%s>>%s W_FAILURE ! %sTrying fallback B keys....", _XRED_, _XORANGE_, _XWHITE_);
-
- /* no trace, no dbg */
- filled = e_MifareECardLoad(sectorsCnt, 1);
- if (filled != PM3_SUCCESS) {
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "FATAL:EML_FALLBACKFILL_B");
- SpinErr(LED_C, 100, 8);
- SpinOff(100);
- return;
- }
- }
-
- delta_time = GetTickCountDelta(start_time);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%s>>%s Time for VIGIK break :%s%dms%s", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time,
- _XWHITE_);
-
- vtsend_cursor_position_save(NULL);
- vtsend_set_attribute(NULL, 1);
- vtsend_set_attribute(NULL, 5);
- cjTabulize();
- DbprintfEx(FLAG_NEWLINE, "[ WRITING FLASH ]");
- cjSetCursLeft();
- cjSetCursLeft();
-
- WriteTagToFlash(cjcuid, 1024);
-
-readysim:
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "-> We launch Emulation ->");
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "%s!> HOLD ON : %s When you'll click, simm will stop", _XRED_, _XWHITE_);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE,
- "Then %s immediately %s we'll try to %s dump our emulator state%s \r\nin a %s chinese tag%s", _XRED_,
- _XWHITE_, _XYELLOW_, _XWHITE_, _XCYAN_, _XWHITE_);
- cjSetCursLeft();
- cjSetCursLeft();
-
- cjTabulize();
-
- DbprintfEx(FLAG_NEWLINE, "[ SIMULATION ]");
- vtsend_set_attribute(NULL, 0);
-
- SpinOff(100);
- LED_C_ON();
-
- DBGLEVEL = DBG_NONE;
-
- //uint16_t flags=0;
- /*switch (p_card.uidlen) {
- case 10:
- flags = FLAG_10B_UID_IN_DATA;
- break;
- case 7:
- flags = FLAG_7B_UID_IN_DATA;
- break;
- case 4:
- flags = FLAG_4B_UID_IN_DATA;
- break;
- default:
- flags = FLAG_UID_IN_EMUL;
- break;
- }*/
-
- // Use UID, SAK, ATQA from EMUL, if uid not defined
- // if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
- //flags |= FLAG_UID_IN_EMUL;
- //}
- //flags |= FLAG_MF_1K;
- //if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
- // flags |= FLAG_UID_IN_EMUL;
- //}
- //flags = 0x10;
- uint16_t flags = 0;
- flags = 16;
- DbprintfEx(FLAG_NEWLINE, "\n\n\n\n\n\n\n\nn\n\nn\n\n\nflags: %d (0x%02x)", flags, flags);
- cjSetCursLeft();
- SpinOff(1000);
- Mifare1ksim(flags, 0, cjuid, 0, 0);
- LED_C_OFF();
- SpinOff(50);
- vtsend_cursor_position_restore(NULL);
- DbprintfEx(FLAG_NEWLINE, "[ SIMUL ENDED ]%s", _XGREEN_, _XWHITE_);
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "<- We're out of Emulation");
- // END SIM
-
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "-> Trying a clone !");
- saMifareMakeTag();
- cjSetCursLeft();
- vtsend_cursor_position_restore(NULL);
- DbprintfEx(FLAG_NEWLINE, "%s[ CLONED? ]", _XCYAN_);
-
- DbprintfEx(FLAG_NEWLINE, "-> End Cloning.");
- WDT_HIT();
-
- // Debunk...
- cjSetCursLeft();
- cjTabulize();
- vtsend_set_attribute(NULL, 0);
- vtsend_set_attribute(NULL, 7);
- DbprintfEx(FLAG_NEWLINE, "- [ LA FIN ] -\r\n%s`-> You can take shell back :) ...", _XWHITE_);
- cjSetCursLeft();
- vtsend_set_attribute(NULL, 0);
- SpinErr(LED_D, 100, 16);
- SpinDown(75);
- SpinOff(100);
- return;
-}
-
-/* Abusive microgain on original MifareECardLoad :
- * - *datain used as error return
- * - tracing is falsed
- */
-int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
- DBGLEVEL = DBG_NONE;
-
- uint8_t numSectors = numofsectors;
- uint8_t keyType = keytype;
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- uint8_t dataoutbuf[16];
- uint8_t dataoutbuf2[16];
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(false);
-
- bool isOK = true;
-
- if (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
- isOK = false;
- if (DBGLEVEL >= 1)
- DbprintfEx(FLAG_RAWPRINT, "Can't select card");
- }
-
- for (uint8_t s = 0; isOK && s < numSectors; s++) {
- uint64_t ui64Key = emlGetKey(s, keyType);
- if (s == 0) {
- if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(s), keyType, ui64Key, AUTH_FIRST)) {
-
- if (DBGLEVEL >= 1)
- DbprintfEx(FLAG_NEWLINE, "Sector[%2d]. Auth error", s);
- break;
- }
- } else {
- if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(s), keyType, ui64Key, AUTH_NESTED)) {
- isOK = false;
- if (DBGLEVEL >= 1)
- DbprintfEx(FLAG_NEWLINE, "Sector[%2d]. Auth nested error", s);
- break;
- }
- }
-
- for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) {
- if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) {
- isOK = false;
- if (DBGLEVEL >= 1)
- DbprintfEx(FLAG_NEWLINE, "Error reading sector %2d block %2d", s, blockNo);
- break;
- };
- if (isOK) {
- if (blockNo < NumBlocksPerSector(s) - 1) {
- emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1);
- } else {
- // sector trailer, keep the keys, set only the AC
- emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
- memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
- emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
- }
- }
- }
- }
-
- if (mifare_classic_halt(pcs, cjcuid)) {
- if (DBGLEVEL >= 1)
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- };
-
- crypto1_deinit(pcs);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- return (isOK) ? PM3_SUCCESS : PM3_EUNDEF;
-}
-
-/* the chk function is a piwi'ed(tm) check that will try all keys for
-a particular sector. also no tracing no dbg */
-int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain,
- uint64_t *key) {
- DBGLEVEL = DBG_NONE;
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- set_tracing(false);
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- for (int i = 0; i < keyCount; ++i) {
-
- /* no need for anticollision. just verify tag is still here */
- // if (!iso14443a_fast_select_card(cjuid, 0)) {
- if (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
- cjSetCursLeft();
- DbprintfEx(FLAG_NEWLINE, "%sFATAL%s : E_MF_LOSTTAG", _XRED_, _XWHITE_);
- return -1;
- }
-
- uint64_t ui64Key = bytes_to_num(datain + i * 6, 6);
- if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
- uint8_t dummy_answer = 0;
- ReaderTransmit(&dummy_answer, 1, NULL);
- // wait for the card to become ready again
- SpinDelayUs(AUTHENTICATION_TIMEOUT);
- continue;
- }
- crypto1_deinit(pcs);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- *key = ui64Key;
- return i;
- }
- crypto1_deinit(pcs);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- return -1;
-}
-
-void saMifareMakeTag(void) {
- uint8_t cfail = 0;
- cjSetCursLeft();
- cjTabulize();
- vtsend_cursor_position_save(NULL);
- vtsend_set_attribute(NULL, 1);
- DbprintfEx(FLAG_NEWLINE, "[ CLONING ]");
- vtsend_set_attribute(NULL, 0);
-
- cjSetCursFRight();
-
- DbprintfEx(FLAG_NEWLINE, ">> Write to Special:");
- int flags = 0;
- for (int blockNum = 0; blockNum < 16 * 4; blockNum++) {
- uint8_t mblock[16];
- // cnt = 0;
- emlGetMem(mblock, blockNum, 1);
- // switch on field and write magic sequence
- if (blockNum == 0)
- flags = 0x08 + 0x02;
-
- // just write
- if (blockNum == 1)
- flags = 0;
-
- // Done. Magic Halt and switch off field.
- if (blockNum == 16 * 4 - 1)
- flags = 0x04 + 0x10;
-
- if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) {
- //&& cnt <= retry) {
- // cnt++;
- cjSetCursFRight();
- if (currfline > 53) {
- currfline = 54;
- }
- DbprintfEx(FLAG_NEWLINE, "Block :%02x %sOK%s", blockNum, _XGREEN_, _XWHITE_);
- // DbprintfEx(FLAG_RAWPRINT,"FATAL:E_MF_CHINESECOOK_NORICE");
- // cfail=1;
- // return;
- continue;
- } else {
- cjSetCursLeft();
- cjSetCursLeft();
-
- DbprintfEx(FLAG_NEWLINE, "`--> %sFAIL%s : CHN_FAIL_BLK_%02x_NOK", _XRED_, _XWHITE_, blockNum);
- cjSetCursFRight();
- DbprintfEx(FLAG_NEWLINE, "%s>>>>%s STOP AT %02x", _XRED_, _XWHITE_, blockNum);
- cfail++;
- break;
- }
- cjSetCursFRight();
-
- DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>> END <<<<<<<<%s", _XYELLOW_, _XWHITE_);
- // break;
- /*if (cfail == 1) {
- DbprintfEx(FLAG_RAWPRINT,"FATAL: E_MF_HARA_KIRI_\r\n");
- break;
- } */
- }
- if (cfail == 0) {
- SpinUp(50);
- SpinUp(50);
- SpinUp(50);
- }
-}
-
-// TODO : make this work either for a Gen1a or for a block 0 direct write all transparently
-//-----------------------------------------------------------------------------
-// Matt's StandAlone mod.
-// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
-//-----------------------------------------------------------------------------
-int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
- // params
- uint8_t needWipe = arg0;
- // bit 0 - need get UID
- // bit 1 - need wupC
- // bit 2 - need HALT after sequence
- // bit 3 - need init FPGA and field before sequence
- // bit 4 - need reset FPGA and LED
- uint8_t workFlags = arg1;
- uint8_t blockNo = arg2;
-
- // card commands
- uint8_t wupC1[] = {0x40};
- uint8_t wupC2[] = {0x43};
- uint8_t wipeC[] = {0x41};
-
- // variables
- uint8_t isOK = 0;
- uint8_t d_block[18] = {0x00};
-
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
-
- // reset FPGA and LED
- if (workFlags & 0x08) {
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- // clear_trace();
- set_tracing(FALSE);
- }
-
- while (true) {
- cjSetCursLeft();
-
- // get UID from chip
- if (workFlags & 0x01) {
- if (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
- DbprintfEx(FLAG_NEWLINE, "Can't select card");
- break;
- };
-
- if (mifare_classic_halt(NULL, cjcuid)) {
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- break;
- };
- };
-
- // reset chip
- if (needWipe) {
- ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wupC1 error");
- break;
- };
-
- ReaderTransmit(wipeC, sizeof(wipeC), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wipeC error");
- break;
- };
-
- if (mifare_classic_halt(NULL, cjcuid)) {
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- break;
- };
- };
-
- // chaud
- // write block
- if (workFlags & 0x02) {
- ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wupC1 error");
- break;
- };
-
- ReaderTransmit(wupC2, sizeof(wupC2), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wupC2 errorv");
- break;
- };
- }
-
- if ((mifare_sendcmd_short(NULL, CRYPT_NONE, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) ||
- (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "write block write command error");
- break;
- };
-
- memcpy(d_block, datain, 16);
- AddCrc14A(d_block, 16);
- ReaderTransmit(d_block, sizeof(d_block), NULL);
- if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "write block write data error");
- break;
- };
-
- if (workFlags & 0x04) {
- if (mifare_classic_halt(NULL, cjcuid)) {
- cjSetCursFRight();
-
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- break;
- };
- }
-
- isOK = 1;
- break;
- }
-
- if ((workFlags & 0x10) || (!isOK)) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- }
-
- return isOK;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_colin.h b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_colin.h
deleted file mode 100644
index a4b870ab..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_colin.h
+++ /dev/null
@@ -1,495 +0,0 @@
-//-----------------------------------------------------------------------------
-// Colin Brigato 2016, 2017
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// StandAlone Mod
-//-----------------------------------------------------------------------------
-
-#include
-#include
-#include
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef __HF_COLIN_H
-#define __HF_COLIN_H
-
-#define _XRED_ "\x1b[31m"
-#define _XGREEN_ "\x1b[32m"
-#define _XYELLOW_ "\x1b[33m"
-#define _XBLUE_ "\x1b[34m"
-#define _XMAGENTA_ "\x1b[35m"
-#define _XCYAN_ "\x1b[36m"
-#define _XWHITE_ "\x1b[0m"
-#define _XORANGE_ _XYELLOW_
-
-int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key);
-int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype);
-void saMifareMakeTag(void);
-int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void WriteTagToFlash(uint32_t uid, size_t size);
-
-const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'};
-
-//void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug);
-//void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate);
-
-//#define LOGO logo_kigiv
-
-const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\"";
-/*
-const char logo_kigiv[] = {
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d,
- 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x0d, 0x0a, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35,
- 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38,
- 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31,
- 0x37, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x20, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x33, 0x38, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34,
- 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d,
- 0x31, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x34, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d,
- 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x20,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x31, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x33, 0x37, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x30, 0x32, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x0d, 0x0a, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38,
- 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38,
- 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x30, 0x32, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x0d,
- 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33,
- 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35,
- 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30,
- 0x32, 0x6d, 0x30, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38,
- 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x35, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35,
- 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x35, 0x39, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20,
- 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x30, 0x20, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34,
- 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x30, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x0d, 0x0a, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x30, 0x31, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32,
- 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x37, 0x6d, 0x30, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31,
- 0x30, 0x32, 0x6d, 0x31, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34,
- 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x30, 0x0d, 0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35,
- 0x32, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33,
- 0x6d, 0x30, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32,
- 0x33, 0x30, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x30,
- 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x34, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x30, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d,
- 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b,
- 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x32, 0x33, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39,
- 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x33, 0x31, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31,
- 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x30, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x31, 0x34, 0x35, 0x6d, 0x30, 0x0d, 0x0a, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38,
- 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x35, 0x32, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d, 0x31, 0x1b, 0x5b,
- 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b,
- 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
- 0x31, 0x33, 0x38, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x38, 0x6d,
- 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
- 0x3b, 0x31, 0x30, 0x31, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x32, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d,
- 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
- 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a};
-unsigned int logo_kigiv_len = 9303;
-*/
-
-/*const char logo_kigiv_nocolor[] = {
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d,
- 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x31, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x31, 0x20, 0x31, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x0d, 0x0a, 0x30, 0x30, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30,
- 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x31,
- 0x30, 0x31, 0x30, 0x31, 0x20, 0x30, 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x31, 0x31, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x31, 0x30,
- 0x30, 0x31, 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x31, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x30, 0x30, 0x31, 0x30, 0x20, 0x20, 0x31, 0x30, 0x31,
- 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x20, 0x20,
- 0x30, 0x31, 0x30, 0x31, 0x31, 0x20, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x30, 0x31, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31,
- 0x31, 0x31, 0x30, 0x20, 0x20, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x30, 0x30,
- 0x30, 0x31, 0x30, 0x31, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x20,
- 0x20, 0x31, 0x31, 0x30, 0x30, 0x31, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x31, 0x31, 0x30,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x20, 0x30,
- 0x31, 0x31, 0x20, 0x20, 0x31, 0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x30, 0x31, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x31, 0x31, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31,
- 0x30, 0x31, 0x30, 0x31, 0x30, 0x20, 0x31, 0x31, 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x31, 0x30, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x30, 0x31, 0x31, 0x30, 0x20, 0x30, 0x31, 0x31, 0x30, 0x20, 0x30, 0x31,
- 0x31, 0x20, 0x20, 0x31, 0x31, 0x31, 0x20, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x31, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x31, 0x30, 0x30, 0x31, 0x30, 0x30, 0x20, 0x30, 0x30, 0x31, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31,
- 0x30, 0x30, 0x20, 0x30, 0x30, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0x31, 0x30, 0x20, 0x30, 0x31, 0x31,
- 0x20, 0x20, 0x30, 0x30, 0x31, 0x20, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x30, 0x31, 0x31, 0x30, 0x30, 0x30, 0x20, 0x31, 0x31, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31,
- 0x30, 0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x31, 0x20, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x30, 0x31, 0x30, 0x31, 0x20, 0x30, 0x31, 0x31, 0x20, 0x20, 0x30, 0x30, 0x31, 0x20,
- 0x20, 0x30, 0x31, 0x30, 0x20, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x30, 0x30, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x30, 0x30, 0x31, 0x31, 0x30, 0x31, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x31, 0x31,
- 0x30, 0x31, 0x31, 0x31, 0x20, 0x31, 0x31, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x30, 0x31, 0x20, 0x30, 0x31, 0x31, 0x20, 0x20,
- 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x30, 0x31, 0x31, 0x30,
- 0x20, 0x20, 0x20, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31,
- 0x30, 0x31, 0x31, 0x30, 0x30, 0x20, 0x30, 0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x31, 0x31, 0x30, 0x31, 0x31, 0x30, 0x30,
- 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x20, 0x20, 0x30, 0x31, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x20, 0x31, 0x30,
- 0x30, 0x30, 0x20, 0x30, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x30, 0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x31, 0x30, 0x31,
- 0x30, 0x30, 0x31, 0x20, 0x30, 0x31, 0x31, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31, 0x30, 0x31, 0x31,
- 0x31, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x31, 0x31, 0x31, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x30, 0x31, 0x31, 0x31,
- 0x30, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31,
- 0x31, 0x20, 0x20, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x31, 0x31, 0x31, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30,
- 0x30, 0x30, 0x31, 0x30, 0x20, 0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x31, 0x31, 0x31,
- 0x30, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30, 0x30,
- 0x30, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x30, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x31, 0x31, 0x31, 0x30, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x20, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x31,
- 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a};
-unsigned int logo_kigiv_nocolor_len = 2153;*/
-
-#endif /* __HF_COLIN_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_mattyrun.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_mattyrun.c
deleted file mode 100644
index 3e53fffe..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_mattyrun.c
+++ /dev/null
@@ -1,463 +0,0 @@
-//-----------------------------------------------------------------------------
-// Matías A. Ré Medina 2016
-// Christian Herrmann, 2018
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for HF aka MattyRun by Matías A. Ré Medina
-//-----------------------------------------------------------------------------
-/*
-### What I did:
-I've personally recoded the image of the ARM in order to automate
-the attack and simulation on Mifare cards. I've moved some of the
-implementation on the client side to the ARM such as *chk*, *ecfill*, *sim*
-and *clone* commands.
-
-### What it does now:
-It will check if the keys from the attacked tag are a subset from
-the hardcoded set of keys inside of the FPGA. If this is the case
-then it will load the keys into the emulator memory and also the
-content of the victim tag, to finally simulate it and make a clone
-on a blank card.
-
-#### TODO:
-- Nested attack in the case not all keys are known.
-- Dump into magic card in case of needed replication.
-
-#### ~ Basically automates commands without user intervention.
-#### ~ No need of interface.
-#### ~ Just a portable battery or an OTG usb cable for power supply.
-
-## Spanish full description of the project [here](http://bit.ly/2c9nZXR).
-*/
-
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "util.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "string.h"
-#include "commonutil.h"
-#include "iso14443a.h"
-#include "mifarecmd.h"
-#include "crc16.h"
-#include "BigBuf.h"
-#include "mifaresim.h" // mifare1ksim
-#include "mifareutil.h"
-
-uint8_t uid[10];
-uint32_t cuid;
-iso14a_card_select_t p_card;
-
-//-----------------------------------------------------------------------------
-// Matt's StandAlone mod.
-// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
-//-----------------------------------------------------------------------------
-static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
- // params
- uint8_t needWipe = arg0;
- // bit 0 - need get UID
- // bit 1 - need wupC
- // bit 2 - need HALT after sequence
- // bit 3 - need init FPGA and field before sequence
- // bit 4 - need reset FPGA and LED
- uint8_t workFlags = arg1;
- uint8_t blockNo = arg2;
-
- // card commands
- uint8_t wupC1[] = {0x40};
- uint8_t wupC2[] = {0x43};
- uint8_t wipeC[] = {0x41};
-
- // variables
- uint8_t isOK = 0;
- uint8_t d_block[18] = {0x00};
-
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
-
- // reset FPGA and LED
- if (workFlags & 0x08) {
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- set_tracing(false);
- }
-
- while (true) {
- // get UID from chip
- if (workFlags & 0x01) {
- if (!iso14443a_select_card(uid, &p_card, &cuid, true, 0, true)) {
- DbprintfEx(FLAG_NEWLINE, "Can't select card");
- break;
- };
-
- if (mifare_classic_halt(NULL, cuid)) {
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- break;
- };
- };
-
- // reset chip
- if (needWipe) {
- ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wupC1 error");
- break;
- };
-
- ReaderTransmit(wipeC, sizeof(wipeC), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wipeC error");
- break;
- };
-
- if (mifare_classic_halt(NULL, cuid)) {
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- break;
- };
- };
-
- // chaud
- // write block
- if (workFlags & 0x02) {
- ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wupC1 error");
- break;
- };
-
- ReaderTransmit(wupC2, sizeof(wupC2), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "wupC2 errorv");
- break;
- };
- }
-
- if ((mifare_sendcmd_short(NULL, CRYPT_NONE, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "write block send command error");
- break;
- };
-
- memcpy(d_block, datain, 16);
- AddCrc14A(d_block, 16);
- ReaderTransmit(d_block, sizeof(d_block), NULL);
- if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
- DbprintfEx(FLAG_NEWLINE, "write block send data error");
- break;
- };
-
- if (workFlags & 0x04) {
- if (mifare_classic_halt(NULL, cuid)) {
- DbprintfEx(FLAG_NEWLINE, "Halt error");
- break;
- };
- }
-
- isOK = 1;
- break;
- }
-
- if ((workFlags & 0x10) || (!isOK)) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- }
-
- return isOK;
-}
-
-/* the chk function is a piwi’ed(tm) check that will try all keys for
-a particular sector. also no tracing no dbg */
-static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) {
- DBGLEVEL = DBG_NONE;
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- set_tracing(false);
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- for (int i = 0; i < keyCount; ++i) {
-
- /* no need for anticollision. just verify tag is still here */
- // if (!iso14443a_fast_select_card(cjuid, 0)) {
- if (!iso14443a_select_card(uid, &p_card, &cuid, true, 0, true)) {
- DbprintfEx(FLAG_NEWLINE, "FATAL : E_MF_LOSTTAG");
- return -1;
- }
-
- uint64_t ui64Key = bytes_to_num(datain + i * 6, 6);
- if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
- uint8_t dummy_answer = 0;
- ReaderTransmit(&dummy_answer, 1, NULL);
- // wait for the card to become ready again
- SpinDelayUs(AUTHENTICATION_TIMEOUT);
- continue;
- }
- crypto1_deinit(pcs);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- *key = ui64Key;
- return i;
- }
- crypto1_deinit(pcs);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- return -1;
-}
-
-void ModInfo(void) {
- DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)");
-}
-
-void RunMod() {
- StandAloneMode();
- Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- /*
- It will check if the keys from the attacked tag are a subset from
- the hardcoded set of keys inside of the ARM. If this is the case
- then it will load the keys into the emulator memory and also the
- content of the victim tag, to finally simulate it.
-
- Alternatively, it can be dumped into a blank card.
-
- This source code has been tested only in Mifare 1k.
-
- If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug
- messages, you MUST uncomment usb_disable().
- */
-
- // Comment this line below if you want to see debug messages.
- // usb_disable();
-
- /*
- Pseudo-configuration block.
- */
- bool printKeys = false; // Prints keys
- bool transferToEml = true; // Transfer keys to emulator memory
- bool ecfill = true; // Fill emulator memory with cards content.
- bool simulation = true; // Simulates an exact copy of the target tag
- bool fillFromEmulator = false; // Dump emulator memory.
-
-
- uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now)
- uint8_t sectorSize = 64; // 1k's sector size is 64 bytes.
- uint8_t blockNo = 3; // Security block is number 3 for each sector.
- uint8_t sectorsCnt = (mifare_size / sectorSize);
- uint8_t keyType = 2; // Keytype buffer
- uint64_t key64; // Defines current key
- uint8_t *keyBlock; // Where the keys will be held in memory.
- uint8_t stKeyBlock = 20; // Set the quantity of keys in the block.
- bool keyFound = false;
-
- /*
- Set of keys to be used.
- */
- uint64_t mfKeys[] = {
- 0xffffffffffff, // Default key
- 0x000000000000, // Blank key
- 0xa0a1a2a3a4a5, // NFCForum MAD key
- 0xb0b1b2b3b4b5,
- 0xaabbccddeeff,
- 0x4d3a99c351dd,
- 0x1a982c7e459a,
- 0xd3f7d3f7d3f7,
- 0x714c5c886e97,
- 0x587ee5f9350f,
- 0xa0478cc39091,
- 0x533cb6c723f6,
- 0x8fd0a4f256e9,
- };
-
- /*
- This part allocates the byte representation of the
- keys in keyBlock's memory space .
- */
- keyBlock = BigBuf_malloc(stKeyBlock * 6);
- int mfKeysCnt = ARRAYLEN(mfKeys);
-
- for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
- num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
- }
-
- /*
- Pretty print of the keys to be checked.
- */
- if (printKeys) {
- Dbprintf("[+] Printing mf keys");
- for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++)
- Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
- (keyBlock + 6 * keycnt)[0], (keyBlock + 6 * keycnt)[1], (keyBlock + 6 * keycnt)[2],
- (keyBlock + 6 * keycnt)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5], 6);
- DbpString("--------------------------------------------------------");
- }
-
- /*
- Initialization of validKeys and foundKeys storages.
- - validKey will store whether the sector has a valid A/B key.
- - foundKey will store the found A/B key for each sector.
- */
- bool validKey[2][40];
- uint8_t foundKey[2][40][6];
- for (uint16_t t = 0; t < 2; t++) {
- for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
- validKey[t][sectorNo] = false;
- for (uint16_t i = 0; i < 6; i++) {
- foundKey[t][sectorNo][i] = 0xff;
- }
- }
- }
-
- /*
- Iterates through each sector checking if there is a correct key.
- */
- bool err = 0;
- bool allKeysFound = true;
- uint32_t size = mfKeysCnt;
-
- for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) {
- int block = blockNo;
- for (int sec = 0; sec < sectorsCnt && !err; ++sec) {
- Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt);
- int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
- if (key == -1) {
- LED(LED_RED, 50); //red
- Dbprintf("\t✕ Key not found for this sector!");
- allKeysFound = false;
- // break;
- } else if (key == -2) {
- err = 1; // Can't select card.
- break;
- } else {
- num_to_bytes(key64, 6, foundKey[type][sec]);
- validKey[type][sec] = true;
- keyFound = true;
- Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n",
- (keyBlock + 6 * key)[0], (keyBlock + 6 * key)[1], (keyBlock + 6 * key)[2],
- (keyBlock + 6 * key)[3], (keyBlock + 6 * key)[4], (keyBlock + 6 * key)[5]
- );
- }
-
- block < 127 ? (block += 4) : (block += 16);
- }
- }
-
- /*
- TODO:
- - Get UID from tag and set accordingly in emulator memory and call mifaresim with right flags (iceman)
- */
- if (!allKeysFound && keyFound) {
- Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
- LED_C_ON(); //red
- LED_A_ON(); //yellow
- // no room to run nested attack on device (iceman)
- // Do nested attack, set allKeysFound = true;
- // allKeysFound = true;
- } else {
- Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
- LED_C_ON(); //red
- }
-
- /*
- If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
- */
- if ((transferToEml) && (allKeysFound)) {
-
- emlClearMem();
-
- uint8_t mblock[16];
- for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
- if (validKey[0][sectorNo] || validKey[1][sectorNo]) {
- emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4)
- for (uint16_t t = 0; t < 2; t++) {
- if (validKey[t][sectorNo]) {
- memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
- }
- }
- emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
- }
- }
- Dbprintf("\t✓ Found keys have been transferred to the emulator memory.");
- if (ecfill) {
- int filled;
- Dbprintf("\tFilling in with key A.");
- filled = MifareECardLoad(sectorsCnt, 0);
- if (filled != PM3_SUCCESS) {
- Dbprintf("\t✕ Failed filling with A.");
- }
-
- Dbprintf("\tFilling in with key B.");
- filled = MifareECardLoad(sectorsCnt, 1);
- if (filled != PM3_SUCCESS) {
- Dbprintf("\t✕ Failed filling with B.");
- }
-
- if ((filled == PM3_SUCCESS) && simulation) {
- Dbprintf("\t✓ Emulator memory filled, simulation started.");
-
- // This will tell the fpga to emulate using previous keys and current target tag content.
- Dbprintf("\t Press button to abort simulation at anytime.");
-
- LED_B_ON(); // green
- // assuming arg0==0, use hardcoded uid 0xdeadbeaf
- uint16_t simflags;
- switch (p_card.uidlen) {
- case 10:
- simflags = FLAG_10B_UID_IN_DATA;
- break;
- case 7:
- simflags = FLAG_7B_UID_IN_DATA;
- break;
- default:
- simflags = FLAG_4B_UID_IN_DATA;
- break;
- }
- Mifare1ksim(simflags | FLAG_MF_1K, 0, uid, 0, 0);
- LED_B_OFF();
-
- /*
- Needs further testing.
- */
- if (fillFromEmulator) {
- uint8_t retry = 5;
- Dbprintf("\t Trying to dump into blank card.");
- int flags = 0;
- LED_A_ON(); //yellow
- for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) {
- uint8_t cnt = 0;
- emlGetMem(mblock, blockNum, 1);
- // switch on field and send magic sequence
- if (blockNum == 0) flags = 0x08 + 0x02;
-
- // just write
- if (blockNum == 1) flags = 0;
-
- // Done. Magic Halt and switch off field.
- if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10;
-
- while (!saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock) && cnt <= retry) {
- cnt++;
- Dbprintf("\t! Could not write block. Retrying.");
- }
- if (cnt == retry) {
- Dbprintf("\t✕ Retries failed. Aborting.");
- break;
- }
- }
-
- if (!err) {
- LED_B_ON();
- } else {
- LED_C_ON();
- }
-
- }
- } else if (filled != PM3_SUCCESS) {
- Dbprintf("\t✕ Emulator memory could not be filled due to errors.");
- LED_C_ON();
- }
- }
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_young.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_young.c
deleted file mode 100644
index bd489c94..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/hf_young.c
+++ /dev/null
@@ -1,280 +0,0 @@
-//-----------------------------------------------------------------------------
-// Craig Young, 2014
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for HF standalone mode Mifare /sniff/emulation by Craig Young
-//-----------------------------------------------------------------------------
-
-#include "standalone.h" // standalone definitions
-#include
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "util.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "string.h"
-#include "commonutil.h"
-#include "mifarecmd.h"
-#include "iso14443a.h"
-#include "protocols.h"
-
-#define OPTS 2
-
-typedef struct {
- uint8_t uid[10];
- uint8_t uidlen;
- uint8_t atqa[2];
- uint8_t sak;
-} PACKED card_clone_t;
-
-
-void ModInfo(void) {
- DbpString(" HF Mifare sniff/simulation - (Craig Young)");
-}
-
-void RunMod() {
- StandAloneMode();
- Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<");
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0;
- int cardRead[OPTS] = {0};
-
- card_clone_t uids[OPTS];
- iso14a_card_select_t card[OPTS];
- uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN);
-
- LED(selected + 1, 0);
-
- for (;;) {
- WDT_HIT();
- // exit from Standalone Mode, write a usbcommand.
- if (data_available()) return;
-
- SpinDelay(300);
-
- if (iGotoRecord == 1 || cardRead[selected] == 0) {
- iGotoRecord = 0;
- LEDsoff();
- LED(selected + 1, 0);
- LED(LED_D, 0);
-
- // record
- Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected);
- /* need this delay to prevent catching some weird data */
- SpinDelay(500);
- iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
-
- for (;;) {
- // exit from Standalone Mode, write a usbcommand.
- if (data_available()) return;
-
- if (BUTTON_PRESS()) {
- if (cardRead[selected]) {
- Dbprintf("Button press detected -- replaying card in bank[%d]", selected);
- break;
- } else if (cardRead[(selected + 1) % OPTS]) {
- Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected + 1) % OPTS);
- selected = (selected + 1) % OPTS;
- break; // playing = 1;
- } else {
- Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
- SpinDelay(300);
- }
- }
-
- if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) {
- continue;
- } else {
- Dbprintf("Read UID:");
- Dbhexdump(card[selected].uidlen, card[selected].uid, 0);
-
- if (memcmp(uids[(selected + 1) % OPTS].uid, card[selected].uid, card[selected].uidlen) == 0) {
- Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping.");
- } else {
- uids[selected].sak = card[selected].sak;
- uids[selected].uidlen = card[selected].uidlen;
- memcpy(uids[selected].uid, card[selected].uid, uids[selected].uidlen);
- memcpy(uids[selected].atqa, card[selected].atqa, 2);
-
- if (uids[selected].uidlen > 4)
- Dbprintf("Bank[%d] received a 7-byte UID", selected);
- else
- Dbprintf("Bank[%d] received a 4-byte UID", selected);
- break;
- }
- }
- }
-
- Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]);
- Dbprintf("SAK = %02X", uids[selected].sak);
- LEDsoff();
- LED(LED_B, 200);
- LED(LED_A, 200);
- LED(LED_B, 200);
- LED(LED_A, 200);
-
- LEDsoff();
- LED(selected + 1, 0);
-
- // Next state is replay:
- playing = 1;
-
- cardRead[selected] = 1;
- }
-
- /* MF Classic UID clone */
- else if (iGotoClone == 1) {
- iGotoClone = 0;
- LEDsoff();
- LED(selected + 1, 0);
- LED(LED_A, 250);
-
- // magiccards holds 4bytes uid. *usually*
- uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4);
-
- // record
- Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid);
-
- // wait for button to be released
- // Delay cloning until card is in place
- while (BUTTON_PRESS())
- WDT_HIT();
-
- Dbprintf("Starting clone. [Bank: %d]", selected);
- // need this delay to prevent catching some weird data
- SpinDelay(500);
- // Begin clone function here:
- /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
- SendCommandOLD(CMD_HF_MIFARE_CSETBL, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16);
-
- Block read is similar:
- SendCommandOLD(CMD_HF_MIFARE_CGETBL, params, blockNo, 0,...};
- We need to imitate that call with blockNo 0 to set a uid.
-
- The get and set commands are handled in this file:
- // Work with "magic Chinese" card
- case CMD_HF_MIFARE_CSETBL:
- MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
- break;
- case CMD_HF_MIFARE_CGETBL:
- MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
- break;
-
- mfCSetUID provides example logic for UID set workflow:
- -Read block0 from card in field with MifareCGetBlock()
- -Configure new values without replacing reserved bytes
- memcpy(block0, uid, 4); // Copy UID bytes from byte array
- // Mifare UID BCC
- block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5
- Bytes 5-7 are reserved SAK and ATQA for mifare classic
- -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it
- */
- uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0};
- // arg0 = Flags, arg1=blockNo
- MifareCGetBlock(params, 0, oldBlock0);
- if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
- Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
- playing = 1;
- } else {
- uint8_t testBlock0[16] = {0};
- Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]);
- memcpy(newBlock0 + 5, oldBlock0 + 5, 11);
-
- // Copy uid for bank (2nd is for longer UIDs not supported if classic)
- memcpy(newBlock0, uids[selected].uid, 4);
- newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3];
-
- // arg0 = workFlags, arg1 = blockNo, datain
- MifareCSetBlock(params, 0, newBlock0);
- MifareCGetBlock(params, 0, testBlock0);
-
- if (memcmp(testBlock0, newBlock0, 16) == 0) {
- DbpString("Cloned successful!");
- cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
- playing = 0;
- iGotoRecord = 1;
- selected = (selected + 1) % OPTS;
- } else {
- Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
- playing = 1;
- }
- }
- LEDsoff();
- LED(selected + 1, 0);
- }
-
- // Change where to record (or begin playing)
- // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
- else if (playing == 1) {
- LEDsoff();
- LED(selected + 1, 0);
-
- // Begin transmitting
- LED(LED_B, 0);
- DbpString("Playing");
- for (; ;) {
- // exit from Standalone Mode, write a usbcommand.
- if (data_available()) return;
-
- int button_action = BUTTON_HELD(1000);
- if (button_action == 0) { // No button action, proceed with sim
-
- uint8_t flags = FLAG_4B_UID_IN_DATA;
- uint8_t data[PM3_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
-
- memcpy(data, uids[selected].uid, uids[selected].uidlen);
-
- uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen);
-
- if (uids[selected].uidlen == 7) {
- flags = FLAG_7B_UID_IN_DATA;
- Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected);
- } else {
- Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected);
- }
-
- if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) {
- DbpString("Mifare Classic 1k");
- SimulateIso14443aTag(1, flags, data);
- } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) {
- DbpString("Mifare Classic 4k (4b uid)");
- SimulateIso14443aTag(8, flags, data);
- } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
- DbpString("Mifare Classic 4k (7b uid)");
- SimulateIso14443aTag(8, flags, data);
- } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
- DbpString("Mifare Ultralight");
- SimulateIso14443aTag(2, flags, data);
- } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) {
- DbpString("Mifare DESFire");
- SimulateIso14443aTag(3, flags, data);
- } else {
- Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
- SimulateIso14443aTag(1, flags, data);
- }
-
- } else if (button_action == BUTTON_SINGLE_CLICK) {
- selected = (selected + 1) % OPTS;
- Dbprintf("Done playing. Switching to record mode on bank %d", selected);
- iGotoRecord = 1;
- break;
- } else if (button_action == BUTTON_HOLD) {
- Dbprintf("Playtime over. Begin cloning...");
- iGotoClone = 1;
- break;
- }
- }
-
- /* We pressed a button so ignore it here with a delay */
- SpinDelay(300);
- LEDsoff();
- LED(selected + 1, 0);
- }
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_hidbrute.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_hidbrute.c
deleted file mode 100644
index 738334d2..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_hidbrute.c
+++ /dev/null
@@ -1,324 +0,0 @@
-//-----------------------------------------------------------------------------
-// Samy Kamkar, 2012
-// Federico Dotta, 2015
-// Maurizio Agazzini, 2015
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//
-// PROXMARK3 - HID CORPORATE 1000 BRUTEFORCER (STAND-ALONE MODE)
-//
-// This version of Proxmark3 firmware adds one extra stand-alone mode.
-// The new stand-alone mode allows to execute a bruteforce on HID Corporate 1000 readers, by
-// reading a specific badge and bruteforcing the Card Number (incrementing and decrementing it),
-// mainteining the same Facility Code of the original badge.
-//
-// Based on an idea of Brad Antoniewicz of McAfee® Foundstone® Professional Services (ProxBrute),
-// the stand-alone mode has been rewritten in order to overcome some limitations of ProxBrute firmware,
-// that does not consider parity bits.
-//
-// https://github.com/federicodotta/proxmark3
-//
-//-----------------------------------------------------------------------------------
-// main code for LF aka HID corporate brutefore by Federico Dotta & Maurizio Agazzini
-//-----------------------------------------------------------------------------------
-#include "standalone.h" // standalone definitions
-#include "lf_hidbrute.h"
-
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "util.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "lfops.h"
-
-#define OPTS 3
-
-void ModInfo(void) {
- DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
-}
-
-// samy's sniff and repeat routine for LF
-void RunMod() {
- StandAloneMode();
- Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<");
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- uint32_t high[OPTS], low[OPTS];
- int selected = 0;
- int playing = 0;
- int cardRead = 0;
-
- for (;;) {
-
- WDT_HIT();
-
- // exit from SamyRun, write a usbcommand.
- if (data_available()) break;
-
- // Was our button held down or pressed?
- int button_pressed = BUTTON_HELD(280);
- if (button_pressed != BUTTON_HOLD)
- continue;
-
- // Button was held for a second, begin recording
- if (cardRead == 0) {
- LEDsoff();
- LED(selected + 1, 0);
- LED(LED_D, 0);
-
- WAIT_BUTTON_RELEASED();
-
- // record
- DbpString("[=] starting recording");
-
- CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
- Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
-
- LEDsoff();
- LED(selected + 1, 0);
- // Finished recording
- // If we were previously playing, set playing off
- // so next button push begins playing what we recorded
- playing = 0;
- cardRead = 1;
- } else if (button_pressed > 0 && cardRead == 1) {
- LEDsoff();
- LED(selected + 1, 0);
- LED(LED_A, 0);
-
- // record
- Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
-
- WAIT_BUTTON_RELEASED();
-
- CopyHIDtoT55x7(0, high[selected], low[selected], 0);
- Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
-
- LEDsoff();
- LED(selected + 1, 0);
- // Finished recording
-
- // If we were previously playing, set playing off
- // so next button push begins playing what we recorded
- playing = 0;
- cardRead = 0;
- }
-
- // Change where to record (or begin playing)
- else if (button_pressed) {
- // Next option if we were previously playing
- if (playing)
- selected = (selected + 1) % OPTS;
-
- playing = !playing;
-
- LEDsoff();
- LED(selected + 1, 0);
-
- // Begin transmitting
- if (playing && selected != 2) {
-
- LED(LED_B, 0);
- DbpString("[=] playing");
-
- WAIT_BUTTON_RELEASED();
-
- Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
- CmdHIDsimTAG(0, high[selected], low[selected], 0, 0);
- DbpString("[=] done playing");
-
- if (BUTTON_HELD(1000) > 0)
- goto out;
-
- /* We pressed a button so ignore it here with a delay */
- SpinDelay(300);
-
- // when done, we're done playing, move to next option
- selected = (selected + 1) % OPTS;
- playing = !playing;
- LEDsoff();
- LED(selected + 1, 0);
- } else if (playing && selected == 2) {
- // Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
- // It is necessary only to calculate the correct parity.
-
- // Brute force code
- // Check if the badge is an HID Corporate 1000
- if ((high[selected] & 0xFFFFFFF8) != 0x28) {
- DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce.");
- continue;
- }
-
- LED(LED_B, 0);
- DbpString("[=] entering bruteforce mode");
-
- WAIT_BUTTON_RELEASED();
-
- // Calculate Facility Code and Card Number from high and low
- uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF;
- uint32_t fc = ((high[selected] & 1) << 11) | (low[selected] >> 21);
- uint32_t original_cardnum = cardnum;
-
- Dbprintf("[=] HID brute - starting decrementing card number");
-
- while (cardnum > 0) {
-
- // Needed for exiting from proxbrute when button is pressed
- if (BUTTON_PRESS()) {
- if (BUTTON_HELD(1000) > 0) {
- goto out;
- } else {
- while (BUTTON_PRESS()) {
- WDT_HIT();
- }
- break;
- }
- }
-
- // Decrement Card Number
- cardnum--;
-
- // Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables
- hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc);
-
- // Print actual code to brute
- Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
-
- CmdHIDsimTAGEx(0, high[selected], low[selected], 0, 1, 50000);
- }
-
- cardnum = original_cardnum;
-
- Dbprintf("[=] HID brute - starting incrementing card number");
-
- while (cardnum <= 0xFFFFF) {
-
- // Needed for exiting from proxbrute when button is pressed
- if (BUTTON_PRESS()) {
- if (BUTTON_HELD(1000) > 0) {
- goto out;
- } else {
- while (BUTTON_PRESS()) { WDT_HIT(); }
- break;
- }
- }
-
- // Decrement Card Number
- cardnum++;
-
- // Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables
- hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc);
-
- // Print actual code to brute
- Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
-
- CmdHIDsimTAGEx(0, high[selected], low[selected], 0, 1, 50000);
- }
-
- DbpString("[=] done bruteforcing");
- if (BUTTON_HELD(1000) > 0)
- goto out;
-
- /* We pressed a button so ignore it here with a delay */
- SpinDelay(300);
-
- // when done, we're done playing, move to next option
- selected = (selected + 1) % OPTS;
- playing = !playing;
- LEDsoff();
- LED(selected + 1, 0);
-
- } else {
- WAIT_BUTTON_RELEASED();
- }
- }
- }
-
-out:
- SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5);
- DbpString("[=] exiting");
- LEDsoff();
-}
-
-// Function that calculate next value for the brutforce of HID corporate 1000
-void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) {
-
- uint32_t new_high = 0;
- uint32_t new_low = 0;
-
- // Calculate new high and low base value from card number and facility code, without parity
- new_low = (fc << 21) | (cardnum << 1);
- new_high = 0x28 | ((fc >> 11) & 1); // 0x28 is 101000
-
- int n_ones;
- uint32_t i;
-
- // Calculating and setting parity bit 34
- // Select only bit used for parity bit 34 in low number (10110110110110110110110110110110)
- uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6;
- n_ones = 0;
- // Calculate number of ones in low number
- for (i = 1; i != 0; i <<= 1) {
- if (parity_bit_34_low & i)
- n_ones++;
- }
- // Calculate number of ones in high number
- if (new_high & 1)
- n_ones++;
-
- // Set parity bit (Even parity)
- if (n_ones % 2)
- new_high = new_high | 0x2;
-
- // Calculating and setting parity bit 1
- // Select only bit used for parity bit 1 in low number (01101101101101101101101101101100)
- uint32_t parity_bit_1_low = new_low & 0x6DB6DB6C;
- n_ones = 0;
-
- // Calculate number of ones in low number
- for (i = 1; i != 0; i <<= 1) {
- if (parity_bit_1_low & i)
- n_ones++;
- }
- // Calculate number of ones in high number
- if (new_high & 0x1)
- n_ones++;
-
- if (new_high & 0x2)
- n_ones++;
-
- // Set parity bit (Odd parity)
- if (!(n_ones % 2))
- new_low = new_low | 0x1;
-
- // Calculating and setting parity bit 35
- n_ones = 0;
- // Calculate number of ones in low number (all bit of low, bitmask unnecessary)
- for (i = 1; i != 0; i <<= 1) {
- if (new_low & i)
- n_ones++;
- }
- // Calculate number of ones in high number
- if (new_high & 0x1)
- n_ones++;
-
- if (new_high & 0x2)
- n_ones++;
-
- // Set parity bit (Odd parity)
- if (!(n_ones % 2))
- new_high = new_high | 0x4;
-
- // Setting new calculated values
- *low = new_low;
- *high = new_high;
-}
-
-// prepare a waveform pattern in the buffer based on the ID given then
-// simulate a HID tag until the button is pressed or after #numcycles cycles
-// Used to bruteforce HID in standalone mode.
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_hidbrute.h b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_hidbrute.h
deleted file mode 100644
index 72e12d30..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_hidbrute.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//-----------------------------------------------------------------------------
-// Samy Kamkar 2012
-// Federico Dotta, 2015
-// Maurizio Agazzini, 2015
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// StandAlone Mod
-//-----------------------------------------------------------------------------
-
-#ifndef __LF_HIDBRUTE_H
-#define __LF_HIDBRUTE_H
-
-#include
-
-void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
-
-#endif /* __LF_HIDBRUTE_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_icehid.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_icehid.c
deleted file mode 100644
index 77f04024..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_icehid.c
+++ /dev/null
@@ -1,389 +0,0 @@
-//-----------------------------------------------------------------------------
-// Christian Herrmann, 2020
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for HID collector aka IceHID by Iceman
-//-----------------------------------------------------------------------------
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "lfops.h"
-#include "lfsampling.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "util.h"
-#include "dbprint.h"
-#include "printf.h"
-#include "spiffs.h"
-#include "ticks.h"
-#include "lfdemod.h"
-/*
- * `lf_hidcollect` sniffs after LF HID credentials, and stores them in internal
- * flash. It requires RDV4 hardware (for flash and battery).
- *
- * On entering stand-alone mode, this module will start reading/record HID credentials.
- * Every found / collected credential will be written/appended to the logfile in flash
- * as a text string.
- *
- * LEDs:
- * - LED A: reading / record
- * - LED B: writing to flash
- * - LED C: unmounting/sync'ing flash (normally < 100ms)
- *
- * To retrieve log file from flash:
- *
- * 1. mem spiffs dump o lf_hidcollect.log f lf_hidcollect.log
- * Copies log file from flash to your PC.
- *
- * 2. exit the Proxmark3 client
- *
- * 3. more lf_hidcollect.log
- *
- * This module emits debug strings during normal operation -- so try it out in
- * the lab connected to PM3 client before taking it into the field.
- *
- * To delete the log file from flash:
- *
- * 1. mem spiffs remove lf_hidcollect.log
- */
-
-#define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log"
-
-
-void DownloadLogInstructions() {
- Dbprintf("");
- Dbprintf("[=] To get the logfile from flash and display it:");
- Dbprintf("[=] " _YELLOW_("1.") "mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE);
- Dbprintf("[=] " _YELLOW_("2.") "exit proxmark3 client");
- Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE);
-}
-
-bool log_exists;
-
-void append(uint8_t* entry, size_t entry_len) {
-
- LED_B_ON();
- if (log_exists == false) {
- rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
- log_exists = true;
- } else {
- rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
- }
- LED_B_OFF();
-}
-
-uint32_t IceEM410xdemod() {
-
- uint8_t *dest = BigBuf_get_addr();
- size_t idx = 0;
- int clk = 0, invert = 0, maxErr = 20;
- uint32_t hi = 0;
- uint64_t lo = 0;
-
- size_t size = MIN(16385, BigBuf_max_traceLen());
-
- //askdemod and manchester decode
- int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1);
-
- WDT_HIT();
-
- if (errCnt > 50) {
- BigBuf_free();
- return PM3_ESOFT;
- }
-
- errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
- if (errCnt != 1) {
- BigBuf_free();
- return PM3_ESOFT;
- }
-
- uint8_t entry[81];
- memset(entry, 0, sizeof(entry));
-
- if (size == 128) {
- sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)\n",
- hi,
- (uint32_t)(lo >> 32),
- (uint32_t)lo,
- (uint32_t)(lo & 0xFFFF),
- (uint32_t)((lo >> 16LL) & 0xFF),
- (uint32_t)(lo & 0xFFFFFF));
- } else {
- sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)\n",
- (uint32_t)(lo >> 32),
- (uint32_t)lo,
- (uint32_t)(lo & 0xFFFF),
- (uint32_t)((lo >> 16LL) & 0xFF),
- (uint32_t)(lo & 0xFFFFFF));
- }
-
- append(entry, strlen((char*)entry));
- Dbprintf("%s", entry);
- BigBuf_free();
- return PM3_SUCCESS;
-}
-
-uint32_t IceAWIDdemod() {
-
- uint8_t *dest = BigBuf_get_addr();
- size_t size = MIN(12800, BigBuf_max_traceLen());
- int dummyIdx = 0;
-
- //askdemod and manchester decode
- int idx = detectAWID(dest, &size, &dummyIdx);
-
- if (idx <= 0 || size != 96) {
- BigBuf_free();
- return PM3_ESOFT;
- }
-
- //get raw ID before removing parities
- uint32_t rawLo = bytebits_to_byte(dest + idx + 64, 32);
- uint32_t rawHi = bytebits_to_byte(dest + idx + 32, 32);
- uint32_t rawHi2 = bytebits_to_byte(dest + idx, 32);
-
- size = removeParity(dest, idx + 8, 4, 1, 88);
- if (size != 66) {
- BigBuf_free();
- return PM3_ESOFT;
- }
-
- uint8_t entry[110];
- memset(entry, 0, sizeof(entry));
-
- uint8_t fmtLen = bytebits_to_byte(dest, 8);
- if (fmtLen == 26) {
- uint8_t fac = bytebits_to_byte(dest + 9, 8);
- uint32_t cardnum = bytebits_to_byte(dest + 17, 16);
- uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
- sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo);
- } else {
- uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16);
- if (fmtLen > 32) {
- uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32);
- uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32);
- sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx%08lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
- } else {
- uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
- sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
- }
- }
-
- append(entry, strlen((char*)entry));
- Dbprintf("%s", entry);
- BigBuf_free();
- return PM3_SUCCESS;
-}
-
-uint32_t IceIOdemod() {
-
- int dummyIdx = 0;
- uint8_t version = 0, facilitycode = 0;
- uint16_t number = 0;
- uint32_t hi = 0, lo = 0;
-
- size_t size = MIN(12000, BigBuf_max_traceLen());
-
-// uint8_t *dest = BigBuf_malloc(size);
- uint8_t *dest = BigBuf_get_addr();
-
- //fskdemod and get start index
- int idx = detectIOProx(dest, &size, &dummyIdx);
-
- if (idx < 0) {
- BigBuf_free();
- return PM3_ESOFT;
- }
-
- hi = bytebits_to_byte(dest + idx, 32);
- lo = bytebits_to_byte(dest + idx + 32, 32);
-
- version = bytebits_to_byte(dest + idx + 27, 8); //14,4
- facilitycode = bytebits_to_byte(dest + idx + 18, 8);
- number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9
-
- uint8_t entry[64];
- memset(entry, 0, sizeof(entry));
-
- sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx)\n"
- , version
- , facilitycode
- , number
- , hi
- , lo
- );
-
- append(entry, strlen((char*)entry));
- Dbprintf("%s", entry);
- BigBuf_free();
- return PM3_SUCCESS;
-}
-
-uint32_t IceHIDDemod() {
-
- int dummyIdx = 0;
-
- uint32_t hi2 = 0, hi = 0, lo = 0;
-
- // large enough to catch 2 sequences of largest format
- size_t size = 50 * 128 * 2; // 12800 bytes
- //uint8_t *dest = BigBuf_malloc(size);
- uint8_t *dest = BigBuf_get_addr();
-
- // FSK demodulator
- int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx);
- if (idx < 0) {
- BigBuf_free();
- return PM3_ESOFT;
- }
-
- if ((size == 96 || size == 192)) {
-
- uint8_t entry[80];
- memset(entry, 0, sizeof(entry));
-
- // go over previously decoded manchester data and decode into usable tag ID
- if (hi2 != 0) { //extra large HID tags 88/192 bits
-
- sprintf((char *)entry, "HID large: %lx%08lx%08lx (%ld)\n",
- hi2,
- hi,
- lo,
- (lo >> 1) & 0xFFFF
- );
-
- append(entry, strlen((char*)entry));
-
- } else { //standard HID tags 44/96 bits
- uint8_t bitlen = 0;
- uint32_t fac = 0;
- uint32_t cardnum = 0;
-
- if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used
- uint32_t lo2 = 0;
- lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit
- uint8_t idx3 = 1;
- while (lo2 > 1) { //find last bit set to 1 (format len bit)
- lo2 >>= 1;
- idx3++;
- }
- bitlen = idx3 + 19;
- fac = 0;
- cardnum = 0;
- if (bitlen == 26) {
- cardnum = (lo >> 1) & 0xFFFF;
- fac = (lo >> 17) & 0xFF;
- }
- if (bitlen == 37) {
- cardnum = (lo >> 1) & 0x7FFFF;
- fac = ((hi & 0xF) << 12) | (lo >> 20);
- }
- if (bitlen == 34) {
- cardnum = (lo >> 1) & 0xFFFF;
- fac = ((hi & 1) << 15) | (lo >> 17);
- }
- if (bitlen == 35) {
- cardnum = (lo >> 1) & 0xFFFFF;
- fac = ((hi & 1) << 11) | (lo >> 21);
- }
- } else { //if bit 38 is not set then 37 bit format is used
- bitlen = 37;
- cardnum = (lo >> 1) & 0x7FFFF;
- fac = ((hi & 0xF) << 12) | (lo >> 20);
- }
-
- sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld\n",
- hi,
- lo,
- (lo >> 1) & 0xFFFF,
- bitlen,
- fac,
- cardnum
- );
-
- append(entry, strlen((char*)entry));
- }
-
- Dbprintf("%s", entry);
- }
-
- BigBuf_free();
- return PM3_SUCCESS;
-}
-
-void ModInfo(void) {
- DbpString(_YELLOW_(" LF HID / IOprox / AWID / EM4100 collector mode") " - a.k.a IceHID (Iceman)");
-}
-
-void RunMod() {
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
- BigBuf_Clear();
-
- StandAloneMode();
-
- Dbprintf(_YELLOW_("[=] Standalone mode IceHID started"));
-
- rdv40_spiffs_lazy_mount();
-
- log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE);
-
- // the main loop for your standalone mode
- for (;;) {
- WDT_HIT();
-
- // exit from IceHID, send a usbcommand.
- if (data_available()) break;
-
- // Was our button held down or pressed?
- int button_pressed = BUTTON_HELD(280);
- if (button_pressed == BUTTON_HOLD)
- break;
-
- LED_A_ON();
-
- uint32_t res;
-
- // since we steal 12800 from bigbuffer, no need to sample it.
- DoAcquisition_config(false, 28000);
- res = IceHIDDemod();
- if (res == PM3_SUCCESS) {
- LED_A_OFF();
- continue;
- }
-
- DoAcquisition_config(false, 28000);
- res = IceAWIDdemod();
- if (res == PM3_SUCCESS) {
- LED_A_OFF();
- continue;
- }
-
- DoAcquisition_config(false, 20000);
- res = IceEM410xdemod();
- if (res == PM3_SUCCESS) {
- LED_A_OFF();
- continue;
- }
-
- DoAcquisition_config(false, 28000);
- res = IceIOdemod();
- if (res == PM3_SUCCESS) {
- LED_A_OFF();
- continue;
- }
- }
-
- LED_C_ON();
- rdv40_spiffs_lazy_unmount();
- LED_C_OFF();
-
- LEDsoff();
- DownloadLogInstructions();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_icerun.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_icerun.c
deleted file mode 100644
index 1d20e4ed..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_icerun.c
+++ /dev/null
@@ -1,44 +0,0 @@
-//-----------------------------------------------------------------------------
-// Christian Herrmann, 2019
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for skeleton aka IceRun by Iceman
-//-----------------------------------------------------------------------------
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "util.h"
-#include "dbprint.h"
-
-void ModInfo(void) {
- DbpString(" LF skeleton mode - aka IceRun (iceman)");
-}
-
-void RunMod() {
- StandAloneMode();
- Dbprintf("[=] LF skeleton code a.k.a IceRun started");
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- // the main loop for your standalone mode
- for (;;) {
- WDT_HIT();
-
- // exit from IceRun, write a usbcommand.
- if (data_available()) break;
-
- // Was our button held down or pressed?
- int button_pressed = BUTTON_HELD(1000);
-
- Dbprintf("button %d", button_pressed);
-
- if (button_pressed)
- break;
- }
-
- DbpString("[=] exiting");
- LEDsoff();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_proxbrute.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_proxbrute.c
deleted file mode 100644
index e79eb785..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_proxbrute.c
+++ /dev/null
@@ -1,119 +0,0 @@
-//-----------------------------------------------------------------------------
-// Samy Kamkar, 2011, 2012
-// Brad antoniewicz 2011
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for LF aka Proxbrute by Brad antoniewicz
-//-----------------------------------------------------------------------------
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "util.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "lfops.h"
-
-void ModInfo(void) {
- DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
-}
-
-// samy's sniff and repeat routine for LF
-void RunMod() {
- StandAloneMode();
- Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<");
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- uint32_t high, low;
-
-#define STATE_READ 0
-#define STATE_BRUTE 1
-
- uint8_t state = STATE_READ;
-
- for (;;) {
-
- WDT_HIT();
-
- // exit from SamyRun, write a usbcommand.
- if (data_available()) break;
-
- // Was our button held down or pressed?
- int button_pressed = BUTTON_HELD(280);
- if (button_pressed != BUTTON_HOLD)
- continue;
-
- // Button was held for a second, begin recording
- if (state == STATE_READ) {
-
- LEDsoff();
- LED_A_ON();
- WAIT_BUTTON_RELEASED();
-
- DbpString("[=] starting recording");
-
-
- // findone, high, low, no ledcontrol (A)
- CmdHIDdemodFSK(1, &high, &low, 0);
-
- Dbprintf("[=] recorded | %x%08x", high, low);
-
- // got nothing. blink and loop.
- if (high == 0 && low == 0) {
- SpinErr(LED_A, 100, 12);
- DbpString("[=] only got zeros, retry recording after click");
- continue;
- }
-
- SpinErr(LED_A, 250, 2);
- state = STATE_BRUTE;
- continue;
-
- } else if (state == STATE_BRUTE) {
-
- LED_C_ON(); // Simulate
- WAIT_BUTTON_RELEASED();
-
-
- /*
- ProxBrute - brad a. - foundstone
-
- Following code is a trivial brute forcer once you read a valid tag
- the idea is you get a valid tag, then just try and brute force to
- another priv level. The problem is that it has no idea if the code
- worked or not, so its a crap shoot. One option is to time how long
- it takes to get a valid ID then start from scratch every time.
- */
- DbpString("[=] entering ProxBrute mode");
- Dbprintf("[=] simulating | %08x%08x", high, low);
-
- for (uint16_t i = low - 1; i > 0; i--) {
-
- if (data_available()) break;
-
- // Was our button held down or pressed?
- button_pressed = BUTTON_HELD(280);
- if (button_pressed != BUTTON_HOLD) break;
-
- Dbprintf("[=] trying Facility = %08x ID %08x", high, i);
-
- // high, i, ledcontrol, timelimit 20000
- CmdHIDsimTAGEx(0, high, i, 0, false, 20000);
-
- SpinDelay(100);
- }
-
- state = STATE_READ;
- SpinErr((LED_A | LED_C), 250, 2);
- LEDsoff();
- }
- }
-
- SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5);
- DbpString("[=] You can take the shell back :) ...");
- LEDsoff();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_samyrun.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_samyrun.c
deleted file mode 100644
index 54e84d82..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/lf_samyrun.c
+++ /dev/null
@@ -1,144 +0,0 @@
-//-----------------------------------------------------------------------------
-// Samy Kamkar, 2012
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// main code for LF aka SamyRun by Samy Kamkar
-//-----------------------------------------------------------------------------
-#include "standalone.h" // standalone definitions
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "fpgaloader.h"
-#include "lfops.h"
-#include "util.h"
-#include "dbprint.h"
-#include "ticks.h"
-
-#define OPTS 2
-
-void ModInfo(void) {
- DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
-}
-
-// samy's sniff and repeat routine for LF
-
-// LEDS.
-// A , B == which bank (recording)
-// FLASHING A, B = clone bank
-// C = playing bank A
-// D = playing bank B
-
-void RunMod() {
- StandAloneMode();
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
-
- uint32_t high[OPTS], low[OPTS];
- int selected = 0;
-
-#define STATE_READ 0
-#define STATE_SIM 1
-#define STATE_CLONE 2
-
- uint8_t state = STATE_READ;
-
- for (;;) {
-
- WDT_HIT();
-
- // exit from SamyRun, write a usbcommand.
- if (data_available()) break;
-
- // Was our button held down or pressed?
- int button_pressed = BUTTON_HELD(280);
- if (button_pressed != BUTTON_HOLD)
- continue;
- /*
- #define BUTTON_NO_CLICK 0
- #define BUTTON_SINGLE_CLICK -1
- #define BUTTON_DOUBLE_CLICK -2
- */
-
- if (state == STATE_READ) {
-
- if (selected == 0) {
- LED_A_ON();
- LED_B_OFF();
- } else {
- LED_B_ON();
- LED_A_OFF();
- }
-
- LED_C_OFF();
- LED_D_OFF();
-
- WAIT_BUTTON_RELEASED();
-
- // record
- DbpString("[=] start recording");
-
- // findone, high, low, no ledcontrol (A)
- uint32_t hi = 0, lo = 0;
- CmdHIDdemodFSK(1, &hi, &lo, 0);
- high[selected] = hi;
- low[selected] = lo;
-
- Dbprintf("[=] recorded %x | %x%08x", selected, high[selected], low[selected]);
-
- // got nothing. blink and loop.
- if (hi == 0 && lo == 0) {
- SpinErr((selected == 0) ? LED_A : LED_B, 100, 12);
- DbpString("[=] only got zeros, retry recording after click");
- continue;
- }
-
- SpinErr((selected == 0) ? LED_A : LED_B, 250, 2);
- state = STATE_SIM;
- continue;
-
- } else if (state == STATE_SIM) {
-
- LED_C_ON(); // Simulate
- LED_D_OFF();
- WAIT_BUTTON_RELEASED();
-
- Dbprintf("[=] simulating %x | %x%08x", selected, high[selected], low[selected]);
-
- // high, low, no led control(A) no time limit
- CmdHIDsimTAGEx(0, high[selected], low[selected], 0, false, -1);
-
- DbpString("[=] simulating done");
-
- uint8_t leds = ((selected == 0) ? LED_A : LED_B) | LED_C;
- SpinErr(leds, 250, 2);
- state = STATE_CLONE;
- continue;
-
- } else if (state == STATE_CLONE) {
-
- LED_C_OFF();
- LED_D_ON(); // clone
- WAIT_BUTTON_RELEASED();
-
- Dbprintf("[=] cloning %x | %x%08x", selected, high[selected], low[selected]);
-
- // high2, high, low, no longFMT
- CopyHIDtoT55x7(0, high[selected], low[selected], 0);
-
- DbpString("[=] cloned done");
-
- state = STATE_READ;
- uint8_t leds = ((selected == 0) ? LED_A : LED_B) | LED_D;
- SpinErr(leds, 250, 2);
- selected = (selected + 1) % OPTS;
- LEDsoff();
- }
- }
-
- SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5);
- DbpString("[=] You can take shell back :) ...");
- LEDsoff();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/placeholder.c b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/placeholder.c
deleted file mode 100644
index 84f72492..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/placeholder.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "standalone.h" // standalone definitions
-
-#include "dbprint.h"
-
-void ModInfo(void) {
- DbpString(" No standalone mode present");
-}
-
-void RunMod() {
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/readme.md b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/readme.md
deleted file mode 100644
index 9b9d4568..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/readme.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# Standalone Modes
-
-This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `Makefile.inc` and `Makefile.hal`
-
-If you want to implement a new standalone mode, you need to implement the methods provided in `standalone.h`.
-Have a look at the skeleton standalone mode called IceRun, in the files `lf_icerun.c lf_icerun.h`.
-
-As it is now, you can only have one standalone mode installed at the time.
-
-## Implementing a standalone mode
-
-We suggest you keep your standalone code inside the `armsrc/Standalone` folder. And that you name your files according to your standalone mode name.
-
-The `standalone.h` states that you must have two functions implemented.
-
-The ModInfo function, which is your identification of your standalone mode. This string will show when running the command `hw status` on the client.
-
-The RunMod function, which is your "main" function when running. You need to check for Usb commands, in order to let the pm3 client break the standalone mode. See this basic skeleton of main function RunMod() and Modinfo() below.
-
-````
-void ModInfo(void) {
- DbpString(" LF good description of your mode - aka FooRun (your name)");
-}
-
-void RunMod(void) {
- // led show
- StandAloneMode();
-
- // Do you target LF or HF?
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- // main loop
- for (;;) {
- WDT_HIT();
-
- // exit from standalone mode, just send a usbcommand
- if (data_available()) break;
-
- // do your standalone stuff..
- }
-````
-
-## Naming your standalone mode
-
-We suggest that you follow these guidelines:
-- Use HF/LF to denote which frequency your mode is targeting.
-- Use you own github name/similar for perpetual honour to denote your mode.
-
-sample:
- `LF_FOO`
-
-Which indicates your mode targets LF and is called FOO.
-
-This leads to your next step, your DEFINE name needed in Makefile.
-
-`WITH_STANDALONE_LF_FOO`
-
-
-## Update MAKEFILE.HAL
-
-Add your mode to the `Makefile.hal` help and modes list:
-```
-+==========================================================+
-| STANDALONE | DESCRIPTION |
-+==========================================================+
-...
-+----------------------------------------------------------+
-| LF_FOO | My foobar mode will make you coffee |
-+----------------------------------------------------------+
-
-STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_FOO
-STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG
-```
-
-If your mode is using one of the unique features of the RDV4, add it to the proper list:
-
-```
-STANDALONE_MODES_REQ_SMARTCARD :=
-STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG
-```
-
-## Update MAKEFILE.INC
-Add your source code files like the following sample in the `Makefile.inc`
-
-```
-# WITH_STANDALONE_LF_ICERUN
-ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_icerun.c
-endif
-
-# WITH_STANDALONE_LF_FOO
-ifneq (,$(findstring WITH_STANDALONE_LF_FOO,$(APP_CFLAGS)))
- SRC_STANDALONE = lf_foo.c
-endif
-```
-
-## Adding identification string of your mode
-Do please add a identification string in a function called `ModInfo` inside your source code file.
-This will enable an easy way to detect on client side which standalone mode has been installed on the device.
-
-````
-void ModInfo(void) {
- DbpString(" LF good description of your mode - aka FooRun (your name)");
-}
-````
-
-## Compiling your standalone mode
-Once all this is done, you and others can now easily compile different standalone modes by just selecting one of the standalone modes (list in `Makefile.hal` or ) , e.g.:
-
-- rename Makefile.platform.sample -> Makefile.platform
-- edit the "STANDALONE" row inside Makefile.platform. You need to uncomment it and add your standalone mode name
-
-Makefile.platform.sample
-```
-# If you want to use it, copy this file as Makefile.platform and adjust it to your needs
-PLATFORM=PM3RDV4
-#PLATFORM_EXTRAS=BTADDON
-#STANDALONE=LF_SAMYRUN
-```
- becomes
-
- Makefile.platform
- ```
-# If you want to use it, copy this file as Makefile.platform and adjust it to your needs
-PLATFORM=PM3RDV4
-#PLATFORM_EXTRAS=BTADDON
-STANDALONE=LF_FOO
-```
-
-Remember only one can be selected at a time for now.
-
-The final steps is to
-- force recompilation of all code. ```make clean```
-- compile ```make -j8```
-- flash your device
-- connect to your device
-- press button long time to trigger ledshow and enter your new standalone mode
-- if connected with usb / fpc , you can also see debug statements from your device in standalone mode. Useful for debugging :)
-
-When compiling you will see a header showing what configurations your project compiled with.
-Make sure it says your standalone mode name.
-
-Happy hacking!
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/standalone.h b/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/standalone.h
deleted file mode 100644
index 2dd35e94..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/Standalone/standalone.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//-----------------------------------------------------------------------------
-// Christian Herrmann, 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// StandAlone Mod header file
-//-----------------------------------------------------------------------------
-
-#ifndef __STANDALONE_H
-#define __STANDALONE_H
-
-void RunMod();
-void ModInfo();
-
-#endif /* __STANDALONE_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/appmain.c b/pm3rdv4rrg/src/main/cpp/armsrc/appmain.c
deleted file mode 100644
index 216ce8be..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/appmain.c
+++ /dev/null
@@ -1,2130 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Mar 2006
-// Edits by Gerhard de Koning Gans, Sep 2007 (##)
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// The main maps code. This is the first thing called after start.c
-// executes.
-//-----------------------------------------------------------------------------
-#include "appmain.h"
-
-#include "clocks.h"
-#include "usb_cdc.h"
-#include "proxmark3_arm.h"
-#include "dbprint.h"
-#include "pmflash.h"
-#include "fpga.h"
-#include "fpga.h"
-#include "fpgaloader.h"
-#include "string.h"
-#include "legicrf.h"
-#include "BigBuf.h"
-#include "iso14443a.h"
-#include "iso14443b.h"
-#include "iso15693.h"
-#include "thinfilm.h"
-#include "felica.h"
-#include "hitag2.h"
-#include "hitagS.h"
-#include "iclass.h"
-#include "legicrfsim.h"
-#include "epa.h"
-#include "hfsnoop.h"
-#include "lfops.h"
-#include "lfsampling.h"
-#include "mifarecmd.h"
-#include "mifaredesfire.h"
-#include "mifaresim.h"
-#include "pcf7931.h"
-#include "Standalone/standalone.h"
-#include "util.h"
-#include "ticks.h"
-
-#ifdef WITH_LCD
-#include "LCD.h"
-#endif
-
-#ifdef WITH_SMARTCARD
-#include "i2c.h"
-#endif
-
-#ifdef WITH_FPC_USART
-#include "usart.h"
-#endif
-
-#ifdef WITH_FLASH
-#include "flashmem.h"
-#include "spiffs.h"
-#endif
-
-//=============================================================================
-// A buffer where we can queue things up to be sent through the FPGA, for
-// any purpose (fake tag, as reader, whatever). We go MSB first, since that
-// is the order in which they go out on the wire.
-//=============================================================================
-
-#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
-uint8_t ToSend[TOSEND_BUFFER_SIZE];
-int ToSendMax = -1;
-static int ToSendBit;
-struct common_area common_area __attribute__((section(".commonarea")));
-int button_status = BUTTON_NO_CLICK;
-bool allow_send_wtx = false;
-
-inline void send_wtx(uint16_t wtx) {
- if (allow_send_wtx) {
- reply_ng(CMD_WTX, PM3_SUCCESS, (uint8_t *)&wtx, sizeof(wtx));
- }
-}
-
-void ToSendReset(void) {
- ToSendMax = -1;
- ToSendBit = 8;
-}
-
-void ToSendStuffBit(int b) {
- if (ToSendBit >= 8) {
- ToSendMax++;
- ToSend[ToSendMax] = 0;
- ToSendBit = 0;
- }
-
- if (b)
- ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
-
- ToSendBit++;
-
- if (ToSendMax >= sizeof(ToSend)) {
- ToSendBit = 0;
- DbpString("ToSendStuffBit overflowed!");
- }
-}
-
-//-----------------------------------------------------------------------------
-// Read an ADC channel and block till it completes, then return the result
-// in ADC units (0 to 1023). Also a routine to average 32 samples and
-// return that.
-//-----------------------------------------------------------------------------
-static uint16_t ReadAdc(int ch) {
-
- // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value.
- // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant
- // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged.
- //
- // The maths are:
- // If there is a voltage v_in at the input, the voltage v_cap at the capacitor (this is what we are measuring) will be
- //
- // v_cap = v_in * (1 - exp(-SHTIM/RC)) = v_in * (1 - exp(-40us/10.9us)) = v_in * 0,97 (i.e. an error of 3%)
-
- AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
- AT91C_BASE_ADC->ADC_MR =
- ADC_MODE_PRESCALE(63) // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz
- | ADC_MODE_STARTUP_TIME(1) // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us
- | ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us
-
- AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch);
- AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
-
- while (!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {};
-
- return (AT91C_BASE_ADC->ADC_CDR[ch] & 0x3FF);
-}
-
-// was static - merlok
-uint16_t AvgAdc(int ch) {
- uint16_t a = 0;
- for (uint8_t i = 0; i < 32; i++)
- a += ReadAdc(ch);
-
- //division by 32
- return (a + 15) >> 5;
-}
-
-void MeasureAntennaTuning(void) {
-
- uint32_t peak = 0;
-
- // in mVolt
- struct p {
- uint32_t v_lf134;
- uint32_t v_lf125;
- uint32_t v_lfconf;
- uint32_t v_hf;
- uint32_t peak_v;
- uint32_t peak_f;
- int divisor;
- uint8_t results[256];
- } PACKED payload;
-
- memset(payload.results, 0, sizeof(payload.results));
-
- sample_config *sc = getSamplingConfig();
- payload.divisor = sc->divisor;
-
- LED_B_ON();
-
- /*
- * Sweeps the useful LF range of the proxmark from
- * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
- * read the voltage in the antenna, the result left
- * in the buffer is a graph which should clearly show
- * the resonating frequency of your LF antenna
- * ( hopefully around 95 if it is tuned to 125kHz!)
- */
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
- SpinDelay(50);
-
- for (uint8_t i = 255; i >= 19; i--) {
- WDT_HIT();
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
- SpinDelay(20);
- uint32_t adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
- if (i == LF_DIVISOR_125)
- payload.v_lf125 = adcval; // voltage at 125kHz
-
- if (i == LF_DIVISOR_134)
- payload.v_lf134 = adcval; // voltage at 134kHz
-
- if (i == sc->divisor)
- payload.v_lfconf = adcval; // voltage at `lf config q`
-
- payload.results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes
-
- if (payload.results[i] > peak) {
- payload.peak_v = adcval;
- payload.peak_f = i;
- peak = payload.results[i];
- }
- }
-
- LED_A_ON();
- // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
- SpinDelay(50);
-
- payload.v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
-
- // RDV40 will hit the roof, try other ADC channel used in that hardware revision.
- if (payload.v_hf > MAX_ADC_HF_VOLTAGE - 300) {
- payload.v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_MEASURE_ANTENNA_TUNING, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
- LEDsoff();
-}
-
-// Measure HF in milliVolt
-uint16_t MeasureAntennaTuningHfData(void) {
- uint16_t volt = 0;
- uint16_t avg = AvgAdc(ADC_CHAN_HF);
- volt = (MAX_ADC_HF_VOLTAGE * avg) >> 10;
- bool use_high = (volt > MAX_ADC_HF_VOLTAGE - 300);
-
- if (use_high) {
- volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
-// volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
- }
- return volt;
-}
-
-// Measure LF in milliVolt
-uint32_t MeasureAntennaTuningLfData(void) {
- return (MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10;
-}
-
-void ReadMem(int addr) {
- const uint8_t *data = ((uint8_t *)addr);
-
- Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x", addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
-}
-
-/* osimage version information is linked in */
-extern struct version_information version_information;
-/* bootrom version information is pointed to from _bootphase1_version_pointer */
-extern char *_bootphase1_version_pointer, _flash_start, _flash_end, __data_src_start__;
-void SendVersion(void) {
- char temp[PM3_CMD_DATA_SIZE - 12]; /* Limited data payload in USB packets */
- char VersionString[PM3_CMD_DATA_SIZE - 12] = { '\0' };
-
- /* Try to find the bootrom version information. Expect to find a pointer at
- * symbol _bootphase1_version_pointer, perform slight sanity checks on the
- * pointer, then use it.
- */
- char *bootrom_version = *(char **)&_bootphase1_version_pointer;
-
- strncat(VersionString, " [ ARM ]\n", sizeof(VersionString) - strlen(VersionString) - 1);
-
- if (bootrom_version < &_flash_start || bootrom_version >= &_flash_end) {
- strcat(VersionString, "bootrom version information appears invalid\n");
- } else {
- FormatVersionInformation(temp, sizeof(temp), " bootrom: ", bootrom_version);
- strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
- }
-
- FormatVersionInformation(temp, sizeof(temp), " os: ", &version_information);
- strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
-
-#if defined(__clang__)
- strncat(VersionString, " compiled with Clang/LLVM "__VERSION__"\n", sizeof(VersionString) - strlen(VersionString) - 1);
-#elif defined(__GNUC__) || defined(__GNUG__)
- strncat(VersionString, " compiled with GCC "__VERSION__"\n", sizeof(VersionString) - strlen(VersionString) - 1);
-#endif
-
- strncat(VersionString, "\n [ FPGA ]\n ", sizeof(VersionString) - strlen(VersionString) - 1);
-
- for (int i = 0; i < fpga_bitstream_num; i++) {
- strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1);
- if (i < fpga_bitstream_num - 1) {
- strncat(VersionString, "\n ", sizeof(VersionString) - strlen(VersionString) - 1);
- }
- }
- // Send Chip ID and used flash memory
- uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
- uint32_t compressed_data_section_size = common_area.arg1;
-
- struct p {
- uint32_t id;
- uint32_t section_size;
- uint32_t versionstr_len;
- char versionstr[PM3_CMD_DATA_SIZE - 12];
- } PACKED;
-
- struct p payload;
- payload.id = *(AT91C_DBGU_CIDR);
- payload.section_size = text_and_rodata_section_size + compressed_data_section_size;
- payload.versionstr_len = strlen(VersionString) + 1;
- memcpy(payload.versionstr, VersionString, payload.versionstr_len);
-
- reply_ng(CMD_VERSION, PM3_SUCCESS, (uint8_t *)&payload, 12 + payload.versionstr_len);
-}
-
-void TimingIntervalAcquisition(void) {
- // trigger new acquisition by turning main oscillator off and on
- mck_from_pll_to_slck();
- mck_from_slck_to_pll();
- // wait for MCFR and recompute RTMR scaler
- StartTickCount();
-}
-
-// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
-// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the PacketCommandNG structure included.
-void printConnSpeed(void) {
- DbpString(_BLUE_("Transfer Speed"));
- Dbprintf(" Sending packets to client...");
-
-#define CONN_SPEED_TEST_MIN_TIME 500 // in milliseconds
- uint8_t *test_data = BigBuf_get_addr();
- uint32_t start_time = GetTickCount();
- uint32_t delta_time = 0;
- uint32_t bytes_transferred = 0;
-
- LED_B_ON();
-
- while (delta_time < CONN_SPEED_TEST_MIN_TIME) {
- reply_ng(CMD_DOWNLOADED_BIGBUF, PM3_SUCCESS, test_data, PM3_CMD_DATA_SIZE);
- bytes_transferred += PM3_CMD_DATA_SIZE;
- delta_time = GetTickCountDelta(start_time);
- }
- LED_B_OFF();
-
- Dbprintf(" Time elapsed............%dms", delta_time);
- Dbprintf(" Bytes transferred.......%d", bytes_transferred);
- Dbprintf(" Transfer Speed PM3 -> Client = " _YELLOW_("%d") "bytes/s", 1000 * bytes_transferred / delta_time);
-}
-
-/**
- * Prints runtime information about the PM3.
-**/
-void SendStatus(void) {
- BigBuf_print_status();
- Fpga_print_status();
-#ifdef WITH_FLASH
- Flashmem_print_status();
-#endif
-#ifdef WITH_SMARTCARD
- I2C_print_status();
-#endif
-#ifdef WITH_LF
- printConfig(); // LF Sampling config
- printT55xxConfig(); // LF T55XX Config
-#endif
- printConnSpeed();
- DbpString(_BLUE_("Various"));
- Dbprintf(" DBGLEVEL................%d", DBGLEVEL);
- Dbprintf(" ToSendMax...............%d", ToSendMax);
- Dbprintf(" ToSendBit...............%d", ToSendBit);
- Dbprintf(" ToSend BUFFERSIZE.......%d", TOSEND_BUFFER_SIZE);
- while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
- uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
- Dbprintf(" Slow clock..............%d Hz", (16 * MAINCK) / mainf);
- uint32_t delta_time = 0;
- uint32_t start_time = GetTickCount();
-#define SLCK_CHECK_MS 50
- SpinDelay(SLCK_CHECK_MS);
- delta_time = GetTickCountDelta(start_time);
- if ((delta_time < SLCK_CHECK_MS - 1) || (delta_time > SLCK_CHECK_MS + 1)) {
- // error > 2% with SLCK_CHECK_MS=50
- Dbprintf(_RED_(" Slow Clock speed change detected, TIA needed"));
- Dbprintf(_YELLOW_(" Slow Clock actual speed seems closer to %d kHz"),
- (16 * MAINCK / 1000) / mainf * delta_time / SLCK_CHECK_MS);
- }
- DbpString(_BLUE_("Installed StandAlone Mode"));
- ModInfo();
-
-#ifdef WITH_FLASH
- Flashmem_print_info();
-#endif
-
- reply_ng(CMD_STATUS, PM3_SUCCESS, NULL, 0);
-}
-
-void SendCapabilities(void) {
- capabilities_t capabilities;
- capabilities.version = CAPABILITIES_VERSION;
- capabilities.via_fpc = reply_via_fpc;
- capabilities.via_usb = reply_via_usb;
- capabilities.baudrate = 0; // no real baudrate for USB-CDC
-#ifdef WITH_FPC_USART
- if (reply_via_fpc)
- capabilities.baudrate = usart_baudrate;
-#endif
-
-#ifdef WITH_FLASH
- capabilities.compiled_with_flash = true;
- capabilities.hw_available_flash = FlashInit();
-#else
- capabilities.compiled_with_flash = false;
- capabilities.hw_available_flash = false;
-#endif
-#ifdef WITH_SMARTCARD
- capabilities.compiled_with_smartcard = true;
- uint8_t maj, min;
- capabilities.hw_available_smartcard = I2C_get_version(&maj, &min) == PM3_SUCCESS;
-#else
- capabilities.compiled_with_smartcard = false;
- capabilities.hw_available_smartcard = false;
-#endif
-#ifdef WITH_FPC_USART
- capabilities.compiled_with_fpc_usart = true;
-#else
- capabilities.compiled_with_fpc_usart = false;
-#endif
-#ifdef WITH_FPC_USART_DEV
- capabilities.compiled_with_fpc_usart_dev = true;
-#else
- capabilities.compiled_with_fpc_usart_dev = false;
-#endif
-#ifdef WITH_FPC_USART_HOST
- capabilities.compiled_with_fpc_usart_host = true;
-#else
- capabilities.compiled_with_fpc_usart_host = false;
-#endif
-#ifdef WITH_LF
- capabilities.compiled_with_lf = true;
-#else
- capabilities.compiled_with_lf = false;
-#endif
-#ifdef WITH_HITAG
- capabilities.compiled_with_hitag = true;
-#else
- capabilities.compiled_with_hitag = false;
-#endif
-#ifdef WITH_HFSNIFF
- capabilities.compiled_with_hfsniff = true;
-#else
- capabilities.compiled_with_hfsniff = false;
-#endif
-#ifdef WITH_HFPLOT
- capabilities.compiled_with_hfplot = true;
-#else
- capabilities.compiled_with_hfplot = false;
-#endif
-#ifdef WITH_ISO14443a
- capabilities.compiled_with_iso14443a = true;
-#else
- capabilities.compiled_with_iso14443a = false;
-#endif
-#ifdef WITH_ISO14443b
- capabilities.compiled_with_iso14443b = true;
-#else
- capabilities.compiled_with_iso14443b = false;
-#endif
-#ifdef WITH_ISO15693
- capabilities.compiled_with_iso15693 = true;
-#else
- capabilities.compiled_with_iso15693 = false;
-#endif
-#ifdef WITH_FELICA
- capabilities.compiled_with_felica = true;
-#else
- capabilities.compiled_with_felica = false;
-#endif
-#ifdef WITH_LEGICRF
- capabilities.compiled_with_legicrf = true;
-#else
- capabilities.compiled_with_legicrf = false;
-#endif
-#ifdef WITH_ICLASS
- capabilities.compiled_with_iclass = true;
-#else
- capabilities.compiled_with_iclass = false;
-#endif
-#ifdef WITH_NFCBARCODE
- capabilities.compiled_with_nfcbarcode = true;
-#else
- capabilities.compiled_with_nfcbarcode = false;
-#endif
-#ifdef WITH_LCD
- capabilities.compiled_with_lcd = true;
-#else
- capabilities.compiled_with_lcd = false;
-#endif
- reply_ng(CMD_CAPABILITIES, PM3_SUCCESS, (uint8_t *)&capabilities, sizeof(capabilities));
-}
-
-// Show some leds in a pattern to identify StandAlone mod is running
-void StandAloneMode(void) {
- DbpString("Stand-alone mode, no computer necessary");
- SpinDown(50);
- SpinDelay(50);
- SpinUp(50);
- SpinDelay(50);
- SpinDown(50);
-}
-
-/*
-OBJECTIVE
-Listen and detect an external reader. Determine the best location
-for the antenna.
-
-INSTRUCTIONS:
-Inside the ListenReaderField() function, there is two mode.
-By default, when you call the function, you will enter mode 1.
-If you press the PM3 button one time, you will enter mode 2.
-If you press the PM3 button a second time, you will exit the function.
-
-DESCRIPTION OF MODE 1:
-This mode just listens for an external reader field and lights up green
-for HF and/or red for LF. This is the original mode of the detectreader
-function.
-
-DESCRIPTION OF MODE 2:
-This mode will visually represent, using the LEDs, the actual strength of the
-current compared to the maximum current detected. Basically, once you know
-what kind of external reader is present, it will help you spot the best location to place
-your antenna. You will probably not get some good results if there is a LF and a HF reader
-at the same place! :-)
-*/
-#define LIGHT_LEVELS 20
-
-void ListenReaderField(uint8_t limit) {
-#define LF_ONLY 1
-#define HF_ONLY 2
-#define REPORT_CHANGE 10 // report new values only if they have changed at least by REPORT_CHANGE
-
- uint16_t lf_av = 0, lf_av_new, lf_baseline = 0, lf_max = 0;
- uint16_t hf_av = 0, hf_av_new, hf_baseline = 0, hf_max = 0;
- uint16_t mode = 1, display_val, display_max;
- bool use_high = false;
-
- // switch off FPGA - we don't want to measure our own signal
- // 20180315 - iceman, why load this before and then turn off?
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- LEDsoff();
-
- if (limit == LF_ONLY) {
- lf_av = lf_max = AvgAdc(ADC_CHAN_LF);
- Dbprintf("LF 125/134kHz Baseline: %dmV", (MAX_ADC_LF_VOLTAGE * lf_av) >> 10);
- lf_baseline = lf_av;
- }
-
- if (limit == HF_ONLY) {
-
- hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
-
- // iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader.
- // RDV40 will hit the roof, try other ADC channel used in that hardware revision.
- use_high = (((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE - 300);
- if (use_high) {
- hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40);
- }
-
- Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10);
- hf_baseline = hf_av;
- }
-
- for (;;) {
-
- // Switch modes with button
- if (BUTTON_PRESS()) {
- SpinDelay(500);
- switch (mode) {
- case 1:
- mode = 2;
- DbpString("Signal Strength Mode");
- break;
- case 2:
- default:
- DbpString("Stopped");
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- return;
- }
- }
- WDT_HIT();
-
- if (limit == LF_ONLY) {
- if (mode == 1) {
- if (ABS(lf_av - lf_baseline) > REPORT_CHANGE)
- LED_D_ON();
- else
- LED_D_OFF();
- }
-
- lf_av_new = AvgAdc(ADC_CHAN_LF);
- // see if there's a significant change
- if (ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
- Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
- lf_av = lf_av_new;
- if (lf_av > lf_max)
- lf_max = lf_av;
- }
- }
-
- if (limit == HF_ONLY) {
- if (mode == 1) {
- if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)
- LED_B_ON();
- else
- LED_B_OFF();
- }
-
- hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF);
-
- // see if there's a significant change
- if (ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
- Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
- hf_av = hf_av_new;
- if (hf_av > hf_max)
- hf_max = hf_av;
- }
- }
-
- if (mode == 2) {
- if (limit == LF_ONLY) {
- display_val = lf_av;
- display_max = lf_max;
- } else if (limit == HF_ONLY) {
- display_val = hf_av;
- display_max = hf_max;
- } else { /* Pick one at random */
- if ((hf_max - hf_baseline) > (lf_max - lf_baseline)) {
- display_val = hf_av;
- display_max = hf_max;
- } else {
- display_val = lf_av;
- display_max = lf_max;
- }
- }
-
- display_val = display_val * (4 * LIGHT_LEVELS) / MAX(1, display_max);
- uint32_t duty_a = MIN(MAX(display_val, 0 * LIGHT_LEVELS), 1 * LIGHT_LEVELS) - 0 * LIGHT_LEVELS;
- uint32_t duty_b = MIN(MAX(display_val, 1 * LIGHT_LEVELS), 2 * LIGHT_LEVELS) - 1 * LIGHT_LEVELS;
- uint32_t duty_c = MIN(MAX(display_val, 2 * LIGHT_LEVELS), 3 * LIGHT_LEVELS) - 2 * LIGHT_LEVELS;
- uint32_t duty_d = MIN(MAX(display_val, 3 * LIGHT_LEVELS), 4 * LIGHT_LEVELS) - 3 * LIGHT_LEVELS;
-
- // LED A
- if (duty_a == 0) {
- LED_A_OFF();
- } else if (duty_a == LIGHT_LEVELS) {
- LED_A_ON();
- } else {
- LED_A_ON();
- SpinDelay(duty_a);
- LED_A_OFF();
- SpinDelay(LIGHT_LEVELS - duty_a);
- }
-
- // LED B
- if (duty_b == 0) {
- LED_B_OFF();
- } else if (duty_b == LIGHT_LEVELS) {
- LED_B_ON();
- } else {
- LED_B_ON();
- SpinDelay(duty_b);
- LED_B_OFF();
- SpinDelay(LIGHT_LEVELS - duty_b);
- }
-
- // LED C
- if (duty_c == 0) {
- LED_C_OFF();
- } else if (duty_c == LIGHT_LEVELS) {
- LED_C_ON();
- } else {
- LED_C_ON();
- SpinDelay(duty_c);
- LED_C_OFF();
- SpinDelay(LIGHT_LEVELS - duty_c);
- }
-
- // LED D
- if (duty_d == 0) {
- LED_D_OFF();
- } else if (duty_d == LIGHT_LEVELS) {
- LED_D_ON();
- } else {
- LED_D_ON();
- SpinDelay(duty_d);
- LED_D_OFF();
- SpinDelay(LIGHT_LEVELS - duty_d);
- }
- }
- }
-}
-static void PacketReceived(PacketCommandNG *packet) {
- /*
- if (packet->ng) {
- Dbprintf("received NG frame with %d bytes payload, with command: 0x%04x", packet->length, cmd);
- } else {
- Dbprintf("received OLD frame of %d bytes, with command: 0x%04x and args: %d %d %d", packet->length, packet->cmd, packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
- }
- */
-
- switch (packet->cmd) {
- case CMD_BREAK_LOOP:
- break;
- case CMD_QUIT_SESSION: {
- reply_via_fpc = false;
- reply_via_usb = false;
- break;
- }
- // emulator
- case CMD_SET_DBGMODE: {
- DBGLEVEL = packet->data.asBytes[0];
- Dbprintf("Debug level: %d", DBGLEVEL);
- reply_ng(CMD_SET_DBGMODE, PM3_SUCCESS, NULL, 0);
- break;
- }
- // always available
- case CMD_HF_DROPFIELD: {
- hf_field_off();
- break;
- }
-#ifdef WITH_LF
- case CMD_LF_T55XX_SET_CONFIG: {
- setT55xxConfig(packet->oldarg[0], (t55xx_configurations_t *) packet->data.asBytes);
- break;
- }
- case CMD_LF_SAMPLING_GET_CONFIG: {
- printConfig();
- break;
- }
- case CMD_LF_SAMPLING_SET_CONFIG: {
- setSamplingConfig((sample_config *) packet->data.asBytes);
- break;
- }
- case CMD_LF_ACQ_RAW_ADC: {
- struct p {
- uint8_t verbose;
- uint32_t samples;
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- uint32_t bits = SampleLF(payload->verbose, payload->samples);
- reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits));
- break;
- }
- case CMD_LF_MOD_THEN_ACQ_RAW_ADC: {
- struct p {
- uint32_t delay;
- uint16_t ones;
- uint16_t zeros;
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- ModThenAcquireRawAdcSamples125k(payload->delay, payload->zeros, payload->ones, packet->data.asBytes + 8);
- break;
- }
- case CMD_LF_SNIFF_RAW_ADC: {
- uint32_t bits = SniffLF();
- reply_mix(CMD_ACK, bits, 0, 0, 0, 0);
- break;
- }
- case CMD_LF_HID_DEMOD: {
- uint32_t high, low;
- CmdHIDdemodFSK(0, &high, &low, 1);
- break;
- }
- case CMD_LF_HID_SIMULATE: {
- lf_hidsim_t *payload = (lf_hidsim_t *)packet->data.asBytes;
- CmdHIDsimTAG(payload->hi2, payload->hi, payload->lo, payload->longFMT, 1);
- break;
- }
- case CMD_LF_FSK_SIMULATE: {
- lf_fsksim_t *payload = (lf_fsksim_t *)packet->data.asBytes;
- CmdFSKsimTAG(payload->fchigh, payload->fclow, payload->separator, payload->clock, packet->length - sizeof(lf_fsksim_t), payload->data, true);
- break;
- }
- case CMD_LF_ASK_SIMULATE: {
- lf_asksim_t *payload = (lf_asksim_t *)packet->data.asBytes;
- CmdASKsimTAG(payload->encoding, payload->invert, payload->separator, payload->clock, packet->length - sizeof(lf_asksim_t), payload->data, true);
- break;
- }
- case CMD_LF_PSK_SIMULATE: {
- lf_psksim_t *payload = (lf_psksim_t *)packet->data.asBytes;
- CmdPSKsimTAG(payload->carrier, payload->invert, payload->clock, packet->length - sizeof(lf_psksim_t), payload->data, true);
- break;
- }
- case CMD_LF_NRZ_SIMULATE: {
- lf_nrzsim_t *payload = (lf_nrzsim_t *)packet->data.asBytes;
- CmdNRZsimTAG(payload->invert, payload->separator, payload->clock, packet->length - sizeof(lf_nrzsim_t), payload->data, true);
- break;
- }
- case CMD_LF_HID_CLONE: {
- CopyHIDtoT55x7(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes[0]);
- break;
- }
- case CMD_LF_IO_DEMOD: {
- uint32_t high, low;
- CmdIOdemodFSK(0, &high, &low, 1);
- break;
- }
- case CMD_LF_EM410X_DEMOD: {
- uint32_t high;
- uint64_t low;
- CmdEM410xdemod(packet->oldarg[0], &high, &low, 1);
- break;
- }
- case CMD_LF_EM410X_WRITE: {
- WriteEM410x(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
- break;
- }
- case CMD_LF_TI_READ: {
- ReadTItag();
- break;
- }
- case CMD_LF_TI_WRITE: {
- WriteTItag(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
- break;
- }
- case CMD_LF_SIMULATE: {
- LED_A_ON();
- struct p {
- uint16_t len;
- uint16_t gap;
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- // length, start gap, led control
- SimulateTagLowFrequency(payload->len, payload->gap, 1);
- reply_ng(CMD_LF_SIMULATE, PM3_EOPABORTED, NULL, 0);
- LED_A_OFF();
- break;
- }
- case CMD_LF_SIMULATE_BIDIR: {
- SimulateTagLowFrequencyBidir(packet->oldarg[0], packet->oldarg[1]);
- break;
- }
- case CMD_LF_T55XX_READBL: {
- struct p {
- uint32_t password;
- uint8_t blockno;
- uint8_t page;
- bool pwdmode;
- uint8_t downlink_mode;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- T55xxReadBlock(payload->page, payload->pwdmode, false, payload->blockno, payload->password, payload->downlink_mode);
- break;
- }
- case CMD_LF_T55XX_WRITEBL: {
- // uses NG format
- T55xxWriteBlock(packet->data.asBytes);
- break;
- }
- case CMD_LF_T55XX_DANGERRAW: {
- T55xxDangerousRawTest(packet->data.asBytes);
- break;
- }
- case CMD_LF_T55XX_WAKEUP: {
- struct p {
- uint32_t password;
- uint8_t flags;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- T55xxWakeUp(payload->password, payload->flags);
- break;
- }
- case CMD_LF_T55XX_RESET_READ: {
- T55xxResetRead(packet->data.asBytes[0] & 0xff);
- break;
- }
- case CMD_LF_T55XX_CHK_PWDS: {
- T55xx_ChkPwds(packet->data.asBytes[0] & 0xff);
- break;
- }
- case CMD_LF_PCF7931_READ: {
- ReadPCF7931();
- break;
- }
- case CMD_LF_PCF7931_WRITE: {
- WritePCF7931(
- packet->data.asBytes[0], packet->data.asBytes[1], packet->data.asBytes[2], packet->data.asBytes[3],
- packet->data.asBytes[4], packet->data.asBytes[5], packet->data.asBytes[6], packet->data.asBytes[9],
- packet->data.asBytes[7] - 128, packet->data.asBytes[8] - 128,
- packet->oldarg[0],
- packet->oldarg[1],
- packet->oldarg[2]
- );
- break;
- }
- case CMD_LF_EM4X_READWORD: {
- struct p {
- uint32_t password;
- uint8_t address;
- uint8_t usepwd;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- EM4xReadWord(payload->address, payload->password, payload->usepwd);
- break;
- }
- case CMD_LF_EM4X_WRITEWORD: {
- struct p {
- uint32_t password;
- uint32_t data;
- uint8_t address;
- uint8_t usepwd;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- EM4xWriteWord(payload->address, payload->data, payload->password, payload->usepwd);
- break;
- }
- case CMD_LF_AWID_DEMOD: {
- uint32_t high, low;
- // Set realtime AWID demodulation
- CmdAWIDdemodFSK(0, &high, &low, 1);
- break;
- }
- case CMD_LF_VIKING_CLONE: {
- struct p {
- bool Q5;
- uint8_t blocks[8];
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- CopyVikingtoT55xx(payload->blocks, payload->Q5);
- break;
- }
- case CMD_LF_COTAG_READ: {
- Cotag(packet->oldarg[0]);
- break;
- }
-#endif
-
-#ifdef WITH_HITAG
- case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type
- SniffHitag2();
-// SniffHitag2(packet->oldarg[0]);
- break;
- }
- case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content
- SimulateHitag2((bool)packet->oldarg[0], packet->data.asBytes);
- break;
- }
- case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function
- ReaderHitag((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes);
- break;
- }
- case CMD_LF_HITAGS_SIMULATE: { // Simulate Hitag s tag, args = memory content
- SimulateHitagSTag((bool)packet->oldarg[0], packet->data.asBytes);
- break;
- }
- case CMD_LF_HITAGS_TEST_TRACES: { // Tests every challenge within the given file
- check_challenges((bool)packet->oldarg[0], packet->data.asBytes);
- break;
- }
- case CMD_LF_HITAGS_READ: { //Reader for only Hitag S tags, args = key or challenge
- ReadHitagS((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes);
- break;
- }
- case CMD_LF_HITAGS_WRITE: { //writer for Hitag tags args=data to write,page and key or challenge
- if ((hitag_function)packet->oldarg[0] < 10) {
- WritePageHitagS((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, packet->oldarg[2]);
- } else {
- WriterHitag((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, packet->oldarg[2]);
- }
- break;
- }
-#endif
-
-#ifdef WITH_ISO15693
- case CMD_HF_ISO15693_ACQ_RAW_ADC: {
- AcquireRawAdcSamplesIso15693();
- break;
- }
- case CMD_HF_ISO15693_RAWADC: {
- RecordRawAdcSamplesIso15693();
- break;
- }
- case CMD_HF_ISO15693_COMMAND: {
- DirectTag15693Command(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_ISO15693_FINDAFI: {
- BruteforceIso15693Afi(packet->oldarg[0]);
- break;
- }
- case CMD_HF_ISO15693_READER: {
- ReaderIso15693(packet->oldarg[0]);
- break;
- }
- case CMD_HF_ISO15693_SIMULATE: {
- SimTagIso15693(packet->oldarg[0], packet->data.asBytes);
- break;
- }
-#endif
-
-#ifdef WITH_LEGICRF
- case CMD_HF_LEGIC_SIMULATE: {
- LegicRfSimulate(packet->oldarg[0]);
- break;
- }
- case CMD_HF_LEGIC_WRITER: {
- LegicRfWriter(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_LEGIC_READER: {
- LegicRfReader(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
- break;
- }
- case CMD_HF_LEGIC_INFO: {
- LegicRfInfo();
- break;
- }
- case CMD_HF_LEGIC_ESET: {
- //-----------------------------------------------------------------------------
- // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
- // involved in dealing with emulator memory. But if it is called later, it might
- // destroy the Emulator Memory.
- //-----------------------------------------------------------------------------
- // arg0 = offset
- // arg1 = num of bytes
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- emlSet(packet->data.asBytes, packet->oldarg[0], packet->oldarg[1]);
- break;
- }
-#endif
-
-#ifdef WITH_ISO14443b
- case CMD_HF_SRI_READ: {
- ReadSTMemoryIso14443b(packet->oldarg[0]);
- break;
- }
- case CMD_HF_ISO14443B_SNIFF: {
- SniffIso14443b();
- break;
- }
- case CMD_HF_ISO14443B_SIMULATE: {
- SimulateIso14443bTag(packet->oldarg[0]);
- break;
- }
- case CMD_HF_ISO14443B_COMMAND: {
- //SendRawCommand14443B(packet->oldarg[0],packet->oldarg[1],packet->oldarg[2],packet->data.asBytes);
- SendRawCommand14443B_Ex(packet);
- break;
- }
-#endif
-
-#ifdef WITH_FELICA
- case CMD_HF_FELICA_COMMAND: {
- felica_sendraw(packet);
- break;
- }
- case CMD_HF_FELICALITE_SIMULATE: {
- felica_sim_lite(packet->oldarg[0]);
- break;
- }
- case CMD_HF_FELICA_SNIFF: {
- felica_sniff(packet->oldarg[0], packet->oldarg[1]);
- break;
- }
- case CMD_HF_FELICALITE_DUMP: {
- felica_dump_lite_s();
- break;
- }
-#endif
-
-#ifdef WITH_ISO14443a
- case CMD_HF_ISO14443A_SNIFF: {
- SniffIso14443a(packet->data.asBytes[0]);
- break;
- }
- case CMD_HF_ISO14443A_READER: {
- ReaderIso14443a(packet);
- break;
- }
- case CMD_HF_ISO14443A_SIMULATE: {
- struct p {
- uint8_t tagtype;
- uint8_t flags;
- uint8_t uid[10];
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid); // ## Simulate iso14443a tag - pass tag type & UID
- break;
- }
- case CMD_HF_ISO14443A_ANTIFUZZ: {
- iso14443a_antifuzz(packet->oldarg[0]);
- break;
- }
- case CMD_HF_EPA_COLLECT_NONCE: {
- EPA_PACE_Collect_Nonce(packet);
- break;
- }
- case CMD_HF_EPA_REPLAY: {
- EPA_PACE_Replay(packet);
- break;
- }
- case CMD_HF_MIFARE_READER: {
- struct p {
- uint8_t first_run;
- uint8_t blockno;
- uint8_t key_type;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- ReaderMifare(payload->first_run, payload->blockno, payload->key_type);
- break;
- }
- case CMD_HF_MIFARE_READBL: {
- mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes;
- MifareReadBlock(payload->blockno, payload->keytype, payload->key);
- break;
- }
- case CMD_HF_MIFAREU_READBL: {
- MifareUReadBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFAREUC_AUTH: {
- MifareUC_Auth(packet->oldarg[0], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFAREU_READCARD: {
- MifareUReadCard(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFAREUC_SETPWD: {
- MifareUSetPwd(packet->oldarg[0], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_READSC: {
- MifareReadSector(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_WRITEBL: {
- MifareWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFAREU_WRITEBL: {
- MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: {
- MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_ACQ_NONCES: {
- MifareAcquireNonces(packet->oldarg[0], packet->oldarg[2]);
- break;
- }
- case CMD_HF_MIFARE_NESTED: {
- struct p {
- uint8_t block;
- uint8_t keytype;
- uint8_t target_block;
- uint8_t target_keytype;
- bool calibrate;
- uint8_t key[6];
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- MifareNested(payload->block, payload->keytype, payload->target_block, payload->target_keytype, payload->calibrate, payload->key);
- break;
- }
- case CMD_HF_MIFARE_STATIC_NESTED: {
- struct p {
- uint8_t block;
- uint8_t keytype;
- uint8_t target_block;
- uint8_t target_keytype;
- uint8_t key[6];
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- MifareStaticNested(payload->block, payload->keytype, payload->target_block, payload->target_keytype, payload->key);
- break;
- }
- case CMD_HF_MIFARE_CHKKEYS: {
- MifareChkKeys(packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_CHKKEYS_FAST: {
- MifareChkKeys_fast(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_CHKKEYS_FILE: {
- struct p {
- uint8_t filename[32];
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- MifareChkKeys_file(payload->filename);
- break;
- }
- case CMD_HF_MIFARE_SIMULATE: {
- struct p {
- uint16_t flags;
- uint8_t exitAfter;
- uint8_t uid[10];
- uint16_t atqa;
- uint8_t sak;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- Mifare1ksim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak);
- break;
- }
- case CMD_HF_MIFARE_EML_MEMCLR: {
- MifareEMemClr();
- reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0);
- break;
- }
- case CMD_HF_MIFARE_EML_MEMSET: {
- struct p {
- uint8_t blockno;
- uint8_t blockcnt;
- uint8_t blockwidth;
- uint8_t data[];
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- MifareEMemSet(payload->blockno, payload->blockcnt, payload->blockwidth, payload->data);
- break;
- }
- case CMD_HF_MIFARE_EML_MEMGET: {
- struct p {
- uint8_t blockno;
- uint8_t blockcnt;
- } PACKED;
- struct p *payload = (struct p *) packet->data.asBytes;
- MifareEMemGet(payload->blockno, payload->blockcnt);
- break;
- }
- case CMD_HF_MIFARE_EML_LOAD: {
- mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes;
- MifareECardLoadExt(payload->sectorcnt, payload->keytype);
- break;
- }
- // Work with "magic Chinese" card
- case CMD_HF_MIFARE_CSETBL: {
- MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_CGETBL: {
- MifareCGetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_CIDENT: {
- MifareCIdent();
- break;
- }
- // mifare sniffer
-// case CMD_HF_MIFARE_SNIFF: {
-// SniffMifare(packet->oldarg[0]);
-// break;
-// }
- case CMD_HF_MIFARE_SETMOD: {
- MifareSetMod(packet->data.asBytes);
- break;
- }
- //mifare desfire
- case CMD_HF_DESFIRE_READBL: {
- break;
- }
- case CMD_HF_DESFIRE_WRITEBL: {
- break;
- }
- case CMD_HF_DESFIRE_AUTH1: {
- MifareDES_Auth1(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_DESFIRE_AUTH2: {
- //MifareDES_Auth2(packet->oldarg[0],packet->data.asBytes);
- break;
- }
- case CMD_HF_DESFIRE_READER: {
- //readermifaredes(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_DESFIRE_INFO: {
- MifareDesfireGetInformation();
- break;
- }
- case CMD_HF_DESFIRE_COMMAND: {
- MifareSendCommand(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_MIFARE_NACK_DETECT: {
- DetectNACKbug();
- break;
- }
- case CMD_HF_MFU_OTP_TEAROFF: {
- MifareU_Otp_Tearoff();
- break;
- }
- case CMD_HF_MIFARE_STATIC_NONCE: {
- MifareHasStaticNonce();
- break;
- }
-#endif
-
-#ifdef WITH_NFCBARCODE
- case CMD_HF_THINFILM_READ: {
- ReadThinFilm();
- break;
- }
- case CMD_HF_THINFILM_SIMULATE: {
- SimulateThinFilm(packet->data.asBytes, packet->length);
- break;
- }
-#endif
-
-#ifdef WITH_ICLASS
- // Makes use of ISO14443a FPGA Firmware
- case CMD_HF_ICLASS_SNIFF: {
- SniffIClass();
- break;
- }
- case CMD_HF_ICLASS_SIMULATE: {
- SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
- break;
- }
- case CMD_HF_ICLASS_READER: {
- ReaderIClass(packet->oldarg[0]);
- break;
- }
- case CMD_HF_ICLASS_REPLAY: {
- ReaderIClass_Replay(packet->oldarg[0], packet->data.asBytes);
- break;
- }
- case CMD_HF_ICLASS_EML_MEMSET: {
- //iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- emlSet(packet->data.asBytes, packet->oldarg[0], packet->oldarg[1]);
- break;
- }
- case CMD_HF_ICLASS_WRITEBL: {
- struct p {
- uint8_t blockno;
- uint8_t data[12];
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- iClass_WriteBlock(payload->blockno, payload->data);
- break;
- }
- // iceman2019, unused?
- case CMD_HF_ICLASS_READCHECK: { // auth step 1
- iClass_ReadCheck(packet->oldarg[0], packet->oldarg[1]);
- break;
- }
- case CMD_HF_ICLASS_READBL: {
- /*
- struct p {
- uint8_t blockno;
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- */
- iClass_ReadBlk(packet->data.asBytes[0]);
- break;
- }
- case CMD_HF_ICLASS_AUTH: { //check
- /*
- struct p {
- uint8_t mac[4];
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- */
- iClass_Authentication(packet->data.asBytes);
- break;
- }
- case CMD_HF_ICLASS_CHKKEYS: {
- iClass_Authentication_fast(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_HF_ICLASS_DUMP: {
- iClass_Dump(packet->oldarg[0], packet->oldarg[1]);
- break;
- }
- case CMD_HF_ICLASS_CLONE: {
- struct p {
- uint8_t startblock;
- uint8_t endblock;
- uint8_t data[];
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
- iClass_Clone(payload->startblock, payload->endblock, payload->data);
- break;
- }
-#endif
-
-#ifdef WITH_HFSNIFF
- case CMD_HF_SNIFF: {
- HfSniff(packet->oldarg[0], packet->oldarg[1]);
- break;
- }
-#endif
-
-#ifdef WITH_HFPLOT
- case CMD_FPGAMEM_DOWNLOAD: {
- HfPlotDownload();
- break;
- }
-#endif
-
-#ifdef WITH_SMARTCARD
- case CMD_SMART_ATR: {
- SmartCardAtr();
- break;
- }
- case CMD_SMART_SETBAUD: {
- SmartCardSetBaud(packet->oldarg[0]);
- break;
- }
- case CMD_SMART_SETCLOCK: {
- SmartCardSetClock(packet->oldarg[0]);
- break;
- }
- case CMD_SMART_RAW: {
- SmartCardRaw(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
- break;
- }
- case CMD_SMART_UPLOAD: {
- // upload file from client
- uint8_t *mem = BigBuf_get_addr();
- memcpy(mem + packet->oldarg[0], packet->data.asBytes, PM3_CMD_DATA_SIZE);
- reply_old(CMD_ACK, 1, 0, 0, 0, 0);
- break;
- }
- case CMD_SMART_UPGRADE: {
- SmartCardUpgrade(packet->oldarg[0]);
- break;
- }
-#endif
-
-#ifdef WITH_FPC_USART
- case CMD_USART_TX: {
- LED_B_ON();
- usart_writebuffer_sync(packet->data.asBytes, packet->length);
- reply_ng(CMD_USART_TX, PM3_SUCCESS, NULL, 0);
- LED_B_OFF();
- break;
- }
- case CMD_USART_RX: {
- LED_B_ON();
- struct p {
- uint32_t waittime;
- } PACKED;
- struct p *payload = (struct p *) &packet->data.asBytes;
- uint16_t available;
- uint16_t pre_available = 0;
- uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
- uint32_t wait = payload->waittime;
- uint32_t ti = GetTickCount();
- while (true) {
- WaitMS(50);
- available = usart_rxdata_available();
- if (available > pre_available) {
- // When receiving data, reset timer and shorten timeout
- ti = GetTickCount();
- wait = 50;
- pre_available = available;
- continue;
- }
- // We stop either after waittime if no data or 50ms after last data received
- if (GetTickCountDelta(ti) > wait)
- break;
- }
- if (available > 0) {
- uint16_t len = usart_read_ng(dest, available);
- reply_ng(CMD_USART_RX, PM3_SUCCESS, dest, len);
- } else {
- reply_ng(CMD_USART_RX, PM3_ENODATA, NULL, 0);
- }
- BigBuf_free();
- LED_B_OFF();
- break;
- }
- case CMD_USART_TXRX: {
- LED_B_ON();
- struct p {
- uint32_t waittime;
- uint8_t data[];
- } PACKED;
- struct p *payload = (struct p *) &packet->data.asBytes;
- usart_writebuffer_sync(payload->data, packet->length - sizeof(payload));
- uint16_t available;
- uint16_t pre_available = 0;
- uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
- uint32_t wait = payload->waittime;
- uint32_t ti = GetTickCount();
- while (true) {
- WaitMS(50);
- available = usart_rxdata_available();
- if (available > pre_available) {
- // When receiving data, reset timer and shorten timeout
- ti = GetTickCount();
- wait = 50;
- pre_available = available;
- continue;
- }
- // We stop either after waittime if no data or 50ms after last data received
- if (GetTickCountDelta(ti) > wait)
- break;
- }
- if (available > 0) {
- uint16_t len = usart_read_ng(dest, available);
- reply_ng(CMD_USART_TXRX, PM3_SUCCESS, dest, len);
- } else {
- reply_ng(CMD_USART_TXRX, PM3_ENODATA, NULL, 0);
- }
- BigBuf_free();
- LED_B_OFF();
- break;
- }
- case CMD_USART_CONFIG: {
- struct p {
- uint32_t baudrate;
- uint8_t parity;
- } PACKED;
- struct p *payload = (struct p *) &packet->data.asBytes;
- usart_init(payload->baudrate, payload->parity);
- reply_ng(CMD_USART_CONFIG, PM3_SUCCESS, NULL, 0);
- break;
- }
-#endif
- case CMD_BUFF_CLEAR: {
- BigBuf_Clear();
- BigBuf_free();
- break;
- }
- case CMD_MEASURE_ANTENNA_TUNING: {
- MeasureAntennaTuning();
- break;
- }
- case CMD_MEASURE_ANTENNA_TUNING_HF: {
- if (packet->length != 1)
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_EINVARG, NULL, 0);
-
- switch (packet->data.asBytes[0]) {
- case 1: // MEASURE_ANTENNA_TUNING_HF_START
- // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_SUCCESS, NULL, 0);
- break;
- case 2:
- if (button_status == BUTTON_SINGLE_CLICK)
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_EOPABORTED, NULL, 0);
- uint16_t volt = MeasureAntennaTuningHfData();
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_SUCCESS, (uint8_t *)&volt, sizeof(volt));
- break;
- case 3:
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_SUCCESS, NULL, 0);
- break;
- default:
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_EINVARG, NULL, 0);
- break;
- }
- break;
- }
- case CMD_MEASURE_ANTENNA_TUNING_LF: {
- if (packet->length != 2)
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_EINVARG, NULL, 0);
-
- switch (packet->data.asBytes[0]) {
- case 1: // MEASURE_ANTENNA_TUNING_LF_START
- // Let the FPGA drive the low-frequency antenna around 125kHz
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, packet->data.asBytes[1]);
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_SUCCESS, NULL, 0);
- break;
- case 2:
- if (button_status == BUTTON_SINGLE_CLICK)
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_EOPABORTED, NULL, 0);
-
- uint32_t volt = MeasureAntennaTuningLfData();
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_SUCCESS, (uint8_t *)&volt, sizeof(volt));
- break;
- case 3:
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_SUCCESS, NULL, 0);
- break;
- default:
- reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_EINVARG, NULL, 0);
- break;
- }
- break;
- }
- case CMD_LISTEN_READER_FIELD: {
- if (packet->length != sizeof(uint8_t))
- break;
- ListenReaderField(packet->data.asBytes[0]);
- break;
- }
- case CMD_FPGA_MAJOR_MODE_OFF: { // ## FPGA Control
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(200);
- LED_D_OFF(); // LED D indicates field ON or OFF
- break;
- }
- case CMD_DOWNLOAD_BIGBUF: {
- LED_B_ON();
- uint8_t *mem = BigBuf_get_addr();
- uint32_t startidx = packet->oldarg[0];
- uint32_t numofbytes = packet->oldarg[1];
-
- // arg0 = startindex
- // arg1 = length bytes to transfer
- // arg2 = BigBuf tracelen
- //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, packet->oldarg[2]);
-
- for (size_t i = 0; i < numofbytes; i += PM3_CMD_DATA_SIZE) {
- size_t len = MIN((numofbytes - i), PM3_CMD_DATA_SIZE);
- int result = reply_old(CMD_DOWNLOADED_BIGBUF, i, len, BigBuf_get_traceLen(), mem + startidx + i, len);
- if (result != PM3_SUCCESS)
- Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
- }
- // Trigger a finish downloading signal with an ACK frame
- // iceman, when did sending samplingconfig array got attached here?!?
- // arg0 = status of download transfer
- // arg1 = RFU
- // arg2 = tracelen?
- // asbytes = samplingconfig array
- reply_old(CMD_ACK, 1, 0, BigBuf_get_traceLen(), getSamplingConfig(), sizeof(sample_config));
- LED_B_OFF();
- break;
- }
-#ifdef WITH_LF
- case CMD_LF_UPLOAD_SIM_SAMPLES: {
- // iceman; since changing fpga_bitstreams clears bigbuff, Its better to call it before.
- // to be able to use this one for uploading data to devices
- // flag =
- // b0 0 skip
- // 1 clear bigbuff
- struct p {
- uint8_t flag;
- uint16_t offset;
- uint8_t *data;
- } PACKED;
- struct p *payload = (struct p *)packet->data.asBytes;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- if ((payload->flag & 0x1) == 0x1) {
- BigBuf_Clear_ext(false);
- BigBuf_free();
- }
-
- // 40 000 - (512-3) 509 = 39491
- uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset);
-
- // need to copy len bytes of data, not PM3_CMD_DATA_SIZE - 3 - offset
- // ensure len bytes copied wont go past end of bigbuf
- uint16_t len = MIN(BIGBUF_SIZE - offset, PM3_CMD_DATA_SIZE - 3);
-
- uint8_t *mem = BigBuf_get_addr();
-
- // x + 394
- memcpy(mem + offset, &payload->data, len);
- // memcpy(mem + offset, &payload->data, PM3_CMD_DATA_SIZE - 3 - offset);
- reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_SUCCESS, NULL, 0);
- break;
- }
-#endif
- case CMD_DOWNLOAD_EML_BIGBUF: {
- LED_B_ON();
- uint8_t *mem = BigBuf_get_EM_addr();
- uint32_t startidx = packet->oldarg[0];
- uint32_t numofbytes = packet->oldarg[1];
-
- // arg0 = startindex
- // arg1 = length bytes to transfer
- // arg2 = RFU
-
- for (size_t i = 0; i < numofbytes; i += PM3_CMD_DATA_SIZE) {
- size_t len = MIN((numofbytes - i), PM3_CMD_DATA_SIZE);
- int result = reply_old(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len);
- if (result != PM3_SUCCESS)
- Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
- }
- // Trigger a finish downloading signal with an ACK frame
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- case CMD_READ_MEM: {
- if (packet->length != sizeof(uint32_t))
- break;
- ReadMem(packet->data.asDwords[0]);
- break;
- }
-#ifdef WITH_FLASH
- case CMD_SPIFFS_TEST: {
- test_spiffs();
- break;
- }
- case CMD_SPIFFS_CHECK: {
- rdv40_spiffs_check();
- break;
- }
- case CMD_SPIFFS_MOUNT: {
- rdv40_spiffs_lazy_mount();
- break;
- }
- case CMD_SPIFFS_UNMOUNT: {
- rdv40_spiffs_lazy_unmount();
- break;
- }
- case CMD_SPIFFS_PRINT_TREE: {
- rdv40_spiffs_safe_print_tree(false);
- break;
- }
- case CMD_SPIFFS_PRINT_FSINFO: {
- rdv40_spiffs_safe_print_fsinfo();
- break;
- }
- case CMD_SPIFFS_DOWNLOAD: {
- LED_B_ON();
- uint8_t filename[32];
- uint8_t *pfilename = packet->data.asBytes;
- memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
- if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs dump : %s", filename);
-
- //uint32_t size = 0;
- //rdv40_spiffs_stat((char *)filename, (uint32_t *)size,RDV40_SPIFFS_SAFETY_SAFE);
- uint32_t size = packet->oldarg[1];
- //uint8_t buff[size];
-
- uint8_t *buff = BigBuf_malloc(size);
- rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)buff, size, RDV40_SPIFFS_SAFETY_SAFE);
-
- // arg0 = filename
- // arg1 = size
- // arg2 = RFU
-
- for (size_t i = 0; i < size; i += PM3_CMD_DATA_SIZE) {
- size_t len = MIN((size - i), PM3_CMD_DATA_SIZE);
- int result = reply_old(CMD_SPIFFS_DOWNLOADED, i, len, 0, buff + i, len);
- if (result != PM3_SUCCESS)
- Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
- }
- // Trigger a finish downloading signal with an ACK frame
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- case CMD_SPIFFS_STAT: {
- LED_B_ON();
- uint8_t filename[32];
- uint8_t *pfilename = packet->data.asBytes;
- memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
- if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs STAT : %s", filename);
- int changed = rdv40_spiffs_lazy_mount();
- uint32_t size = size_in_spiffs((char *)filename);
- if (changed) rdv40_spiffs_lazy_unmount();
- reply_old(CMD_ACK, size, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- case CMD_SPIFFS_REMOVE: {
- LED_B_ON();
- uint8_t filename[32];
- uint8_t *pfilename = packet->data.asBytes;
- memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
- if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs REMOVE : %s", filename);
- rdv40_spiffs_remove((char *) filename, RDV40_SPIFFS_SAFETY_SAFE);
- LED_B_OFF();
- break;
- }
- case CMD_SPIFFS_RENAME: {
- LED_B_ON();
- uint8_t src[32];
- uint8_t dest[32];
- uint8_t *pfilename = packet->data.asBytes;
- char *token;
- token = strtok((char *)pfilename, ",");
- strncpy((char *)src, token, sizeof(src) - 1);
- token = strtok(NULL, ",");
- strncpy((char *)dest, token, sizeof(dest) - 1);
- if (DBGLEVEL > 1) {
- Dbprintf("> Filename received as source for spiffs RENAME : %s", src);
- Dbprintf("> Filename received as destination for spiffs RENAME : %s", dest);
- }
- rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
- LED_B_OFF();
- break;
- }
- case CMD_SPIFFS_COPY: {
- LED_B_ON();
- uint8_t src[32];
- uint8_t dest[32];
- uint8_t *pfilename = packet->data.asBytes;
- char *token;
- token = strtok((char *)pfilename, ",");
- strncpy((char *)src, token, sizeof(src) - 1);
- token = strtok(NULL, ",");
- strncpy((char *)dest, token, sizeof(dest) - 1);
- if (DBGLEVEL > 1) {
- Dbprintf("> Filename received as source for spiffs COPY : %s", src);
- Dbprintf("> Filename received as destination for spiffs COPY : %s", dest);
- }
- rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
- LED_B_OFF();
- break;
- }
- case CMD_SPIFFS_WRITE: {
- LED_B_ON();
- uint8_t filename[32];
- uint32_t append = packet->oldarg[0];
- uint32_t size = packet->oldarg[1];
- uint8_t *data = packet->data.asBytes;
-
- //rdv40_spiffs_lazy_mount();
-
- uint8_t *pfilename = packet->data.asBytes;
- memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
- data += SPIFFS_OBJ_NAME_LEN;
-
- if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append);
- if (!append) {
- rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
- } else {
- rdv40_spiffs_append((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
- }
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- case CMD_FLASHMEM_SET_SPIBAUDRATE: {
- if (packet->length != sizeof(uint32_t))
- break;
- FlashmemSetSpiBaudrate(packet->data.asDwords[0]);
- break;
- }
- case CMD_FLASHMEM_WRITE: {
- LED_B_ON();
- uint8_t isok = 0;
- uint16_t res = 0;
- uint32_t startidx = packet->oldarg[0];
- uint16_t len = packet->oldarg[1];
- uint8_t *data = packet->data.asBytes;
-
- if (!FlashInit()) {
- break;
- }
-
- if (startidx == DEFAULT_T55XX_KEYS_OFFSET) {
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase4k(3, 0xC);
- } else if (startidx == DEFAULT_MF_KEYS_OFFSET) {
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase4k(3, 0x9);
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase4k(3, 0xA);
- } else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET) {
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase4k(3, 0xB);
- }
-
- res = Flash_Write(startidx, data, len);
- isok = (res == len) ? 1 : 0;
-
- reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- case CMD_FLASHMEM_WIPE: {
- LED_B_ON();
- uint8_t page = packet->oldarg[0];
- uint8_t initalwipe = packet->oldarg[1];
- bool isok = false;
- if (initalwipe) {
- isok = Flash_WipeMemory();
- reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- if (page < 3)
- isok = Flash_WipeMemoryPage(page);
-
- reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
- LED_B_OFF();
- break;
- }
- case CMD_FLASHMEM_DOWNLOAD: {
-
- LED_B_ON();
- uint8_t *mem = BigBuf_malloc(PM3_CMD_DATA_SIZE);
- uint32_t startidx = packet->oldarg[0];
- uint32_t numofbytes = packet->oldarg[1];
- // arg0 = startindex
- // arg1 = length bytes to transfer
- // arg2 = RFU
-
- if (!FlashInit()) {
- break;
- }
-
- for (size_t i = 0; i < numofbytes; i += PM3_CMD_DATA_SIZE) {
- size_t len = MIN((numofbytes - i), PM3_CMD_DATA_SIZE);
- Flash_CheckBusy(BUSY_TIMEOUT);
- bool isok = Flash_ReadDataCont(startidx + i, mem, len);
- if (!isok)
- Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len);
-
- isok = reply_old(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len);
- if (isok != 0)
- Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
- }
- FlashStop();
-
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- BigBuf_free();
- LED_B_OFF();
- break;
- }
- case CMD_FLASHMEM_INFO: {
-
- LED_B_ON();
- rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_malloc(sizeof(rdv40_validation_t));
-
- bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN);
-
- if (FlashInit()) {
- Flash_UniqueID(info->flashid);
- FlashStop();
- }
- reply_old(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t));
- BigBuf_free();
-
- LED_B_OFF();
- break;
- }
-#endif
- case CMD_LF_SET_DIVISOR: {
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, packet->data.asBytes[0]);
- break;
- }
- case CMD_SET_ADC_MUX: {
- switch (packet->data.asBytes[0]) {
- case 0:
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- break;
- case 2:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- break;
-#ifndef WITH_FPC_USART
- case 1:
- SetAdcMuxFor(GPIO_MUXSEL_LORAW);
- break;
- case 3:
- SetAdcMuxFor(GPIO_MUXSEL_HIRAW);
- break;
-#endif
- }
- break;
- }
- case CMD_VERSION: {
- SendVersion();
- break;
- }
- case CMD_STATUS: {
- SendStatus();
- break;
- }
- case CMD_TIA: {
-
- while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
- uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF;
- Dbprintf(" Slow clock old measured value:.........%d Hz", (16 * MAINCK) / mainf);
- TimingIntervalAcquisition();
-
- while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
- mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF;
- Dbprintf(""); // first message gets lost
- Dbprintf(" Slow clock new measured value:.........%d Hz", (16 * MAINCK) / mainf);
- reply_ng(CMD_TIA, PM3_SUCCESS, NULL, 0);
- break;
- }
- case CMD_STANDALONE: {
- RunMod();
- break;
- }
- case CMD_CAPABILITIES: {
- SendCapabilities();
- break;
- }
- case CMD_PING: {
- reply_ng(CMD_PING, PM3_SUCCESS, packet->data.asBytes, packet->length);
- break;
- }
-#ifdef WITH_LCD
- case CMD_LCD_RESET: {
- LCDReset();
- break;
- }
- case CMD_LCD: {
- LCDSend(packet->oldarg[0]);
- break;
- }
-#endif
- case CMD_FINISH_WRITE:
- case CMD_HARDWARE_RESET: {
- usb_disable();
-
- // (iceman) why this wait?
- SpinDelay(1000);
- AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
- // We're going to reset, and the bootrom will take control.
- for (;;) {}
- break;
- }
- case CMD_START_FLASH: {
- if (common_area.flags.bootrom_present) {
- common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
- }
- usb_disable();
- AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
- // We're going to flash, and the bootrom will take control.
- for (;;) {}
- break;
- }
- case CMD_DEVICE_INFO: {
- uint32_t dev_info = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
- if (common_area.flags.bootrom_present) {
- dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
- }
- reply_old(CMD_DEVICE_INFO, dev_info, 0, 0, 0, 0);
- break;
- }
- default: {
- Dbprintf("%s: 0x%04x", "unknown command:", packet->cmd);
- break;
- }
- }
-}
-
-void __attribute__((noreturn)) AppMain(void) {
-
- SpinDelay(100);
- clear_trace();
-
- if (common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
- /* Initialize common area */
- memset(&common_area, 0, sizeof(common_area));
- common_area.magic = COMMON_AREA_MAGIC;
- common_area.version = 1;
- }
- common_area.flags.osimage_present = 1;
-
- LEDsoff();
-
- // The FPGA gets its clock from us from PCK0 output, so set that up.
- AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
- AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;
- AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK0;
- // PCK0 is PLL clock / 4 = 96MHz / 4 = 24MHz
- AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_4; // 4 for 24MHz pck0, 2 for 48 MHZ pck0
- AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;
-
- // Reset SPI
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; // errata says it needs twice to be correctly set.
-
- // Reset SSC
- AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
-
- // Configure MUX
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Load the FPGA image, which we have stored in our flash.
- // (the HF version by default)
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- StartTickCount();
-
-#ifdef WITH_LCD
- LCDInit();
-#endif
-
-#ifdef WITH_SMARTCARD
- I2C_init();
-#endif
-
-#ifdef WITH_FPC_USART
- usart_init(USART_BAUD_RATE, USART_PARITY);
-#endif
-
- // This is made as late as possible to ensure enumeration without timeout
- // against devices such as http://www.hobbytronics.co.uk/usb-host-board-v2
- usb_disable();
- usb_enable();
- allow_send_wtx = true;
-
-#ifdef WITH_FLASH
- // If flash is not present, BUSY_TIMEOUT kicks in, let's do it after USB
- loadT55xxConfig();
-
- //
- // Enforce a spiffs check/garbage collection at boot so we are likely to never
- // fall under the 2 contigous free blocks availables
- rdv40_spiffs_check();
-#endif
-
- for (;;) {
- WDT_HIT();
-
- // Check if there is a packet available
- PacketCommandNG rx;
- memset(&rx.data, 0, sizeof(rx.data));
-
- int ret = receive_ng(&rx);
- if (ret == PM3_SUCCESS) {
- PacketReceived(&rx);
- } else if (ret != PM3_ENODATA) {
-
- Dbprintf("Error in frame reception: %d %s", ret, (ret == PM3_EIO) ? "PM3_EIO" : "");
- // TODO if error, shall we resync ?
- }
-
- // Press button for one second to enter a possible standalone mode
- button_status = BUTTON_HELD(1000);
- if (button_status == BUTTON_HOLD) {
- /*
- * So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile
- * All standalone mod "main loop" should be the RunMod() function.
- */
- allow_send_wtx = false;
- RunMod();
- allow_send_wtx = true;
- }
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/appmain.h b/pm3rdv4rrg/src/main/cpp/armsrc/appmain.h
deleted file mode 100644
index 141c943f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/appmain.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __APPMAIN_H
-#define __APPMAIN_H
-
-#include "common.h"
-
-extern const uint8_t OddByteParity[256];
-extern int rsamples; // = 0;
-extern uint8_t trigger;
-extern bool allow_send_wtx;
-
-// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
-#define MAX_ADC_HF_VOLTAGE 36300
-// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV
-#define MAX_ADC_HF_VOLTAGE_RDV40 140800
-// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV
-#define MAX_ADC_LF_VOLTAGE 140800
-
-extern int ToSendMax;
-extern uint8_t ToSend[];
-
-void send_wtx(uint16_t wtx);
-void ReadMem(int addr);
-void __attribute__((noreturn)) AppMain(void);
-
-uint16_t AvgAdc(int ch);
-
-//void PrintToSendBuffer(void);
-void ToSendStuffBit(int b);
-void ToSendReset(void);
-void ListenReaderField(uint8_t limit);
-void StandAloneMode(void);
-void printStandAloneModes(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/buzzer_disabled.c b/pm3rdv4rrg/src/main/cpp/armsrc/buzzer_disabled.c
deleted file mode 100644
index 708b7d3f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/buzzer_disabled.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "buzzer.h"
-
-void Ring_BEE_ONCE(uint16_t music_note) {
- BEE_ON();
- SpinDelayUs(music_note);
- BEE_OFF();
- SpinDelayUs(music_note);
-}
-
-void ring_2_7khz(uint16_t count) {
- Ring_BEE_TIME(n_2_7khz, count);
-}
-
-void Ring_BEE_TIME(uint16_t music_note, uint16_t count) {
- for (uint16_t i = 0 ; i < count; i++)
- Ring_BEE_ONCE(music_note);
- SpinDelay(9);
-}
-
-void Ring_ALL(uint16_t count) {
- Ring_BEE_TIME(note_1, count);
- Ring_BEE_TIME(note_2, count);
- Ring_BEE_TIME(note_3, count);
- Ring_BEE_TIME(note_4, count);
- Ring_BEE_TIME(note_5, count);
- Ring_BEE_TIME(note_6, count);
- Ring_BEE_TIME(note_7, count);
- SpinDelay(10);
-}
-
-void Ring_Little_Star(uint16_t count) {
- Ring_BEE_TIME(note_1, count);
- Ring_BEE_TIME(note_1, count);
- Ring_BEE_TIME(note_5, count);
- Ring_BEE_TIME(note_5, count);
- Ring_BEE_TIME(note_6, count);
- Ring_BEE_TIME(note_6, count);
- Ring_BEE_TIME(note_5, 2 * count);
- LED_A_ON();
- /*
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_2,count);
- Ring_BEE_TIME(note_2,count);
- Ring_BEE_TIME(note_1,2*count);
- LED_A_OFF();
-
- Ring_BEE_TIME(note_5,count);
- Ring_BEE_TIME(note_5,count);
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_2,2*count);
- LED_A_ON();
-
- Ring_BEE_TIME(note_5,count);
- Ring_BEE_TIME(note_5,count);
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_2,2*count);
- LED_A_OFF();
-
- Ring_BEE_TIME(note_1,count);
- Ring_BEE_TIME(note_1,count);
- Ring_BEE_TIME(note_5,count);
- Ring_BEE_TIME(note_5,count);
- Ring_BEE_TIME(note_6,count);
- Ring_BEE_TIME(note_6,count);
- Ring_BEE_TIME(note_5,2*count);
- LED_A_ON();
-
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_4,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_3,count);
- Ring_BEE_TIME(note_2,count);
- Ring_BEE_TIME(note_2,count);
- Ring_BEE_TIME(note_1,2*count);
- LED_B_ON();
- */
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/buzzer_disabled.h b/pm3rdv4rrg/src/main/cpp/armsrc/buzzer_disabled.h
deleted file mode 100644
index c8b6e447..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/buzzer_disabled.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******
---by sww.2017.4.6
-*******/
-
-#ifndef __BUZZER_H
-#define __BUZZER_H
-
-#include "common.h"
-
-#define n_2_7khz 185
-#define note_1 956
-#define note_2 851
-#define note_3 758
-#define note_4 715
-#define note_5 638
-#define note_6 568
-#define note_7 506
-#define note_8 0
-
-void Ring_BEE_ONCE(uint16_t music_note);
-void Ring_BEE_TIME(uint16_t music_note, uint16_t count);
-void ring_2_7khz(uint16_t count);
-void Ring_ALL(uint16_t count);
-void Ring_Little_Star(uint16_t count);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/cmd.c b/pm3rdv4rrg/src/main/cpp/armsrc/cmd.c
deleted file mode 100644
index 5164809f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/cmd.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Proxmark write and read commands
- *
- * Copyright (c) 2012, Roel Verdult
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @file cmd.c
- * @brief
- */
-#include "cmd.h"
-#include "usb_cdc.h"
-#include "usart.h"
-#include "crc16.h"
-#include "string.h"
-
-// Flags to tell where to add CRC on sent replies
-bool reply_with_crc_on_usb = false;
-bool reply_with_crc_on_fpc = true;
-// "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART
-bool reply_via_fpc = false;
-bool reply_via_usb = false;
-
-int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) {
- PacketResponseOLD txcmd = {CMD_UNKNOWN, {0, 0, 0}, {{0}}};
-
-// for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
-// ((uint8_t *)&txcmd)[i] = 0x00;
-
- // Compose the outgoing command frame
- txcmd.cmd = cmd;
- txcmd.arg[0] = arg0;
- txcmd.arg[1] = arg1;
- txcmd.arg[2] = arg2;
-
- // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
- if (data && len) {
- len = MIN(len, PM3_CMD_DATA_SIZE);
- for (size_t i = 0; i < len; i++) {
- txcmd.d.asBytes[i] = ((uint8_t *)data)[i];
- }
- }
-
- int resultfpc = PM3_EUNDEF;
- int resultusb = PM3_EUNDEF;
- // Send frame and make sure all bytes are transmitted
-
- if (reply_via_usb) {
- resultusb = usb_write((uint8_t *)&txcmd, sizeof(PacketResponseOLD));
- }
-
- if (reply_via_fpc) {
-#ifdef WITH_FPC_USART_HOST
- resultfpc = usart_writebuffer_sync((uint8_t *)&txcmd, sizeof(PacketResponseOLD));
-#else
- return PM3_EDEVNOTSUPP;
-#endif
- }
- // we got two results, let's prioritize the faulty one and USB over FPC.
- if (reply_via_usb && (resultusb != PM3_SUCCESS)) return resultusb;
- if (reply_via_fpc && (resultfpc != PM3_SUCCESS)) return resultfpc;
- return PM3_SUCCESS;
-}
-
-static int reply_ng_internal(uint16_t cmd, int16_t status, uint8_t *data, size_t len, bool ng) {
- PacketResponseNGRaw txBufferNG;
- size_t txBufferNGLen;
-
- // Compose the outgoing command frame
- txBufferNG.pre.magic = RESPONSENG_PREAMBLE_MAGIC;
- txBufferNG.pre.cmd = cmd;
- txBufferNG.pre.status = status;
- txBufferNG.pre.ng = ng;
- if (len > PM3_CMD_DATA_SIZE) {
- len = PM3_CMD_DATA_SIZE;
- // overwrite status
- txBufferNG.pre.status = PM3_EOVFLOW;
- }
- txBufferNG.pre.length = len;
-
- // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
- if (data && len) {
- for (size_t i = 0; i < len; i++) {
- txBufferNG.data[i] = data[i];
- }
- }
-
- PacketResponseNGPostamble *tx_post = (PacketResponseNGPostamble *)((uint8_t *)&txBufferNG + sizeof(PacketResponseNGPreamble) + len);
- // Note: if we write to both FPC & USB, we'll set CRC for both if any of them require CRC
- if ((reply_via_fpc && reply_with_crc_on_fpc) || ((reply_via_usb) && reply_with_crc_on_usb)) {
- uint8_t first, second;
- compute_crc(CRC_14443_A, (uint8_t *)&txBufferNG, sizeof(PacketResponseNGPreamble) + len, &first, &second);
- tx_post->crc = (first << 8) + second;
- } else {
- tx_post->crc = RESPONSENG_POSTAMBLE_MAGIC;
- }
- txBufferNGLen = sizeof(PacketResponseNGPreamble) + len + sizeof(PacketResponseNGPostamble);
-
- int resultfpc = PM3_EUNDEF;
- int resultusb = PM3_EUNDEF;
- // Send frame and make sure all bytes are transmitted
-
- if (reply_via_usb) {
- resultusb = usb_write((uint8_t *)&txBufferNG, txBufferNGLen);
- }
- if (reply_via_fpc) {
-#ifdef WITH_FPC_USART_HOST
- resultfpc = usart_writebuffer_sync((uint8_t *)&txBufferNG, txBufferNGLen);
-#else
- return PM3_EDEVNOTSUPP;
-#endif
- }
- // we got two results, let's prioritize the faulty one and USB over FPC.
- if (reply_via_usb && (resultusb != PM3_SUCCESS)) return resultusb;
- if (reply_via_fpc && (resultfpc != PM3_SUCCESS)) return resultfpc;
- return PM3_SUCCESS;
-}
-
-int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len) {
- return reply_ng_internal(cmd, status, data, len, true);
-}
-
-int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) {
- uint16_t status = PM3_SUCCESS;
- uint64_t arg[3] = {arg0, arg1, arg2};
- if (len > PM3_CMD_DATA_SIZE - sizeof(arg)) {
- len = PM3_CMD_DATA_SIZE - sizeof(arg);
- status = PM3_EOVFLOW;
- }
- uint8_t cmddata[PM3_CMD_DATA_SIZE];
- memcpy(cmddata, arg, sizeof(arg));
- if (len && data)
- memcpy(cmddata + sizeof(arg), data, len);
-
- return reply_ng_internal(cmd, status, cmddata, len + sizeof(arg), false);
-}
-
-static int receive_ng_internal(PacketCommandNG *rx, uint32_t read_ng(uint8_t *data, size_t len), bool usb, bool fpc) {
- PacketCommandNGRaw rx_raw;
- size_t bytes = read_ng((uint8_t *)&rx_raw.pre, sizeof(PacketCommandNGPreamble));
-
- if (bytes == 0)
- return PM3_ENODATA;
-
- if (bytes != sizeof(PacketCommandNGPreamble))
- return PM3_EIO;
-
- rx->magic = rx_raw.pre.magic;
- rx->ng = rx_raw.pre.ng;
- uint16_t length = rx_raw.pre.length;
- rx->cmd = rx_raw.pre.cmd;
-
- if (rx->magic == COMMANDNG_PREAMBLE_MAGIC) { // New style NG command
- if (length > PM3_CMD_DATA_SIZE)
- return PM3_EOVFLOW;
-
- // Get the core and variable length payload
- bytes = read_ng((uint8_t *)&rx_raw.data, length);
- if (bytes != length)
- return PM3_EIO;
-
- if (rx->ng) {
- memcpy(rx->data.asBytes, rx_raw.data, length);
- rx->length = length;
- } else {
- uint64_t arg[3];
- if (length < sizeof(arg))
- return PM3_EIO;
-
- memcpy(arg, rx_raw.data, sizeof(arg));
- rx->oldarg[0] = arg[0];
- rx->oldarg[1] = arg[1];
- rx->oldarg[2] = arg[2];
- memcpy(rx->data.asBytes, rx_raw.data + sizeof(arg), length - sizeof(arg));
- rx->length = length - sizeof(arg);
- }
- // Get the postamble
- bytes = read_ng((uint8_t *)&rx_raw.foopost, sizeof(PacketCommandNGPostamble));
- if (bytes != sizeof(PacketCommandNGPostamble))
- return PM3_EIO;
-
- // Check CRC, accept MAGIC as placeholder
- rx->crc = rx_raw.foopost.crc;
- if (rx->crc != COMMANDNG_POSTAMBLE_MAGIC) {
- uint8_t first, second;
- compute_crc(CRC_14443_A, (uint8_t *)&rx_raw, sizeof(PacketCommandNGPreamble) + length, &first, &second);
- if ((first << 8) + second != rx->crc)
- return PM3_EIO;
- }
- reply_via_usb = usb;
- reply_via_fpc = fpc;
- } else { // Old style command
- PacketCommandOLD rx_old;
- memcpy(&rx_old, &rx_raw.pre, sizeof(PacketCommandNGPreamble));
- bytes = read_ng(((uint8_t *)&rx_old) + sizeof(PacketCommandNGPreamble), sizeof(PacketCommandOLD) - sizeof(PacketCommandNGPreamble));
- if (bytes != sizeof(PacketCommandOLD) - sizeof(PacketCommandNGPreamble))
- return PM3_EIO;
-
- reply_via_usb = usb;
- reply_via_fpc = fpc;
- rx->ng = false;
- rx->magic = 0;
- rx->crc = 0;
- rx->cmd = rx_old.cmd;
- rx->oldarg[0] = rx_old.arg[0];
- rx->oldarg[1] = rx_old.arg[1];
- rx->oldarg[2] = rx_old.arg[2];
- rx->length = PM3_CMD_DATA_SIZE;
- memcpy(&rx->data, &rx_old.d.asBytes, rx->length);
- }
- return PM3_SUCCESS;
-}
-
-int receive_ng(PacketCommandNG *rx) {
-
- // Check if there is a packet available
- if (usb_poll_validate_length())
- return receive_ng_internal(rx, usb_read_ng, true, false);
-
-#ifdef WITH_FPC_USART_HOST
- // Check if there is a FPC packet available
- if (usart_rxdata_available() > 0)
- return receive_ng_internal(rx, usart_read_ng, false, true);
-#endif
- return PM3_ENODATA;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/cmd.h b/pm3rdv4rrg/src/main/cpp/armsrc/cmd.h
deleted file mode 100644
index 3cca6c10..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/cmd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Proxmark write and read commands
- *
- * Copyright (c) 2010, Roel Verdult
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @file cmd.h
- * @brief
- */
-
-#ifndef _PROXMARK_CMD_H_
-#define _PROXMARK_CMD_H_
-
-#include "common.h"
-#include "pm3_cmd.h"
-
-// Flags to tell where to add CRC on sent replies
-extern bool reply_with_crc_on_usb;
-extern bool reply_with_crc_on_fpc;
-// "Session" flag, to tell via which interface next msgs should be sent: USB and/or FPC USART
-extern bool reply_via_fpc;
-extern bool reply_via_usb;
-
-int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
-int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len);
-int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
-int receive_ng(PacketCommandNG *rx);
-
-#endif // _PROXMARK_CMD_H_
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/dbprint.c b/pm3rdv4rrg/src/main/cpp/armsrc/dbprint.c
deleted file mode 100644
index 9b18b7ac..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/dbprint.c
+++ /dev/null
@@ -1,130 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Mar 2006
-// Edits by Gerhard de Koning Gans, Sep 2007 (##)
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// The main application code. This is the first thing called after start.c
-// executes.
-//-----------------------------------------------------------------------------
-
-#include "dbprint.h"
-
-#include "string.h"
-#include "cmd.h"
-#include "printf.h"
-
-#define DEBUG 1
-
-//=============================================================================
-// Debug print functions, to go out over USB, to the usual PC-side client.
-//=============================================================================
-
-void DbpStringEx(uint32_t flags, char *src, size_t srclen) {
-#if DEBUG
- struct {
- uint16_t flag;
- uint8_t buf[PM3_CMD_DATA_SIZE - sizeof(uint16_t)];
- } PACKED data;
- data.flag = flags;
- uint16_t len = MIN(srclen, sizeof(data.buf));
- memcpy(data.buf, src, len);
- reply_ng(CMD_DEBUG_PRINT_STRING, PM3_SUCCESS, (uint8_t *)&data, sizeof(data.flag) + len);
-#endif
-}
-
-void DbpString(char *str) {
-#if DEBUG
- DbpStringEx(FLAG_LOG, str, strlen(str));
-#endif
-}
-
-void DbprintfEx(uint32_t flags, const char *fmt, ...) {
-#if DEBUG
- // should probably limit size here; oh well, let's just use a big buffer
- char s[PM3_CMD_DATA_SIZE] = {0x00};
- va_list ap;
- va_start(ap, fmt);
- kvsprintf(fmt, s, 10, ap);
- va_end(ap);
-
- DbpStringEx(flags, s, strlen(s));
-#endif
-}
-
-void Dbprintf(const char *fmt, ...) {
-#if DEBUG
- // should probably limit size here; oh well, let's just use a big buffer
- char output_string[PM3_CMD_DATA_SIZE] = {0x00};
- va_list ap;
-
- va_start(ap, fmt);
- kvsprintf(fmt, output_string, 10, ap);
- va_end(ap);
-
- DbpString(output_string);
-#endif
-}
-
-// prints HEX & ASCII
-void Dbhexdump(int len, uint8_t *d, bool bAsci) {
-#if DEBUG
- char ascii[9];
-
- while (len > 0) {
-
- int l = (len > 8) ? 8 : len;
-
- memcpy(ascii, d, l);
- ascii[l] = 0;
-
- // filter safe ascii
- for (int i = 0; i < l; i++) {
- if (ascii[i] < 32 || ascii[i] > 126) {
- ascii[i] = '.';
- }
- }
-
- if (bAsci)
- Dbprintf("%-8s %*D", ascii, l, d, " ");
- else
- Dbprintf("%*D", l, d, " ");
-
- len -= 8;
- d += 8;
- }
-#endif
-}
-
-void print_result(char *name, uint8_t *buf, size_t len) {
-
- uint8_t *p = buf;
- uint16_t tmp = len & 0xFFF0;
-
- for (; p - buf < tmp; p += 16) {
- Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
- name,
- p - buf,
- len,
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
- );
- }
- if (len % 16 != 0) {
- char s[46] = {0};
- char *sp = s;
- for (; p - buf < len; p++) {
- sprintf(sp, "%02x ", p[0]);
- sp += 3;
- }
- Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s);
- }
-}
-
-/* useful when debugging new protocol implementations like FeliCa
-void PrintToSendBuffer(void) {
- DbpString("Printing ToSendBuffer:");
- Dbhexdump(ToSendMax, ToSend, 0);
-}
-*/
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/dbprint.h b/pm3rdv4rrg/src/main/cpp/armsrc/dbprint.h
deleted file mode 100644
index c3229f46..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/dbprint.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __DBPRINT_H
-#define __DBPRINT_H
-
-#include "common.h"
-#include "ansi.h"
-
-#define Dbprintf_usb(...) {\
- bool tmpfpc = reply_via_fpc;\
- bool tmpusb = reply_via_usb;\
- reply_via_fpc = false;\
- reply_via_usb = true;\
- Dbprintf(__VA_ARGS__);\
- reply_via_fpc = tmpfpc;\
- reply_via_usb = tmpusb;}
-
-#define Dbprintf_fpc(...) {\
- bool tmpfpc = reply_via_fpc;\
- bool tmpusb = reply_via_usb;\
- reply_via_fpc = true;\
- reply_via_usb = false;\
- Dbprintf(__VA_ARGS__);\
- reply_via_fpc = tmpfpc;\
- reply_via_usb = tmpusb;}
-
-#define Dbprintf_all(...) {\
- bool tmpfpc = reply_via_fpc;\
- bool tmpusb = reply_via_usb;\
- reply_via_fpc = true;\
- reply_via_usb = true;\
- Dbprintf(__VA_ARGS__);\
- reply_via_fpc = tmpfpc;\
- reply_via_usb = tmpusb;}
-
-
-void DbpString(char *str);
-void DbpStringEx(uint32_t flags, char *src, size_t srclen);
-void Dbprintf(const char *fmt, ...);
-void DbprintfEx(uint32_t flags, const char *fmt, ...);
-void Dbhexdump(int len, uint8_t *d, bool bAsci);
-void print_result(char *name, uint8_t *buf, size_t len);
-//void PrintToSendBuffer(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/des.c b/pm3rdv4rrg/src/main/cpp/armsrc/des.c
deleted file mode 100644
index ccd32be7..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/des.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/* des.c */
-/*
- This file is part of the ARM-Crypto-Lib.
- Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-/**
- * \file des.c
- * \author Daniel Otte
- * \email daniel.otte@rub.de
- * \date 2007-06-16
- * \brief DES and EDE-DES implementation
- * \license GPLv3 or later
- *
- */
-
-#include "des.h"
-#include "string.h"
-
-const uint8_t sbox[256] = {
- /* S-box 1 */
- 0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
- 0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
- 0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
- 0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
- /* S-box 2 */
- 0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
- 0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
- 0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
- 0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
- /* S-box 3 */
- 0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
- 0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
- 0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
- 0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
- /* S-box 4 */
- 0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
- 0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
- 0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
- 0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
- /* S-box 5 */
- 0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
- 0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
- 0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
- 0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
- /* S-box 6 */
- 0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
- 0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
- 0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
- 0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
- /* S-box 7 */
- 0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
- 0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
- 0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
- 0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
- /* S-box 8 */
- 0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
- 0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
- 0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
- 0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
-};
-
-const uint8_t e_permtab[] = {
- 4, 6, /* 4 bytes in 6 bytes out*/
- 32, 1, 2, 3, 4, 5,
- 4, 5, 6, 7, 8, 9,
- 8, 9, 10, 11, 12, 13,
- 12, 13, 14, 15, 16, 17,
- 16, 17, 18, 19, 20, 21,
- 20, 21, 22, 23, 24, 25,
- 24, 25, 26, 27, 28, 29,
- 28, 29, 30, 31, 32, 1
-};
-
-const uint8_t p_permtab[] = {
- 4, 4, /* 32 bit -> 32 bit */
- 16, 7, 20, 21,
- 29, 12, 28, 17,
- 1, 15, 23, 26,
- 5, 18, 31, 10,
- 2, 8, 24, 14,
- 32, 27, 3, 9,
- 19, 13, 30, 6,
- 22, 11, 4, 25
-};
-
-const uint8_t ip_permtab[] = {
- 8, 8, /* 64 bit -> 64 bit */
- 58, 50, 42, 34, 26, 18, 10, 2,
- 60, 52, 44, 36, 28, 20, 12, 4,
- 62, 54, 46, 38, 30, 22, 14, 6,
- 64, 56, 48, 40, 32, 24, 16, 8,
- 57, 49, 41, 33, 25, 17, 9, 1,
- 59, 51, 43, 35, 27, 19, 11, 3,
- 61, 53, 45, 37, 29, 21, 13, 5,
- 63, 55, 47, 39, 31, 23, 15, 7
-};
-
-const uint8_t inv_ip_permtab[] = {
- 8, 8, /* 64 bit -> 64 bit */
- 40, 8, 48, 16, 56, 24, 64, 32,
- 39, 7, 47, 15, 55, 23, 63, 31,
- 38, 6, 46, 14, 54, 22, 62, 30,
- 37, 5, 45, 13, 53, 21, 61, 29,
- 36, 4, 44, 12, 52, 20, 60, 28,
- 35, 3, 43, 11, 51, 19, 59, 27,
- 34, 2, 42, 10, 50, 18, 58, 26,
- 33, 1, 41, 9, 49, 17, 57, 25
-};
-
-const uint8_t pc1_permtab[] = {
- 8, 7, /* 64 bit -> 56 bit*/
- 57, 49, 41, 33, 25, 17, 9,
- 1, 58, 50, 42, 34, 26, 18,
- 10, 2, 59, 51, 43, 35, 27,
- 19, 11, 3, 60, 52, 44, 36,
- 63, 55, 47, 39, 31, 23, 15,
- 7, 62, 54, 46, 38, 30, 22,
- 14, 6, 61, 53, 45, 37, 29,
- 21, 13, 5, 28, 20, 12, 4
-};
-
-const uint8_t pc2_permtab[] = {
- 7, 6, /* 56 bit -> 48 bit */
- 14, 17, 11, 24, 1, 5,
- 3, 28, 15, 6, 21, 10,
- 23, 19, 12, 4, 26, 8,
- 16, 7, 27, 20, 13, 2,
- 41, 52, 31, 37, 47, 55,
- 30, 40, 51, 45, 33, 48,
- 44, 49, 39, 56, 34, 53,
- 46, 42, 50, 36, 29, 32
-};
-
-const uint8_t splitin6bitword_permtab[] = {
- 8, 8, /* 64 bit -> 64 bit */
- 64, 64, 1, 6, 2, 3, 4, 5,
- 64, 64, 7, 12, 8, 9, 10, 11,
- 64, 64, 13, 18, 14, 15, 16, 17,
- 64, 64, 19, 24, 20, 21, 22, 23,
- 64, 64, 25, 30, 26, 27, 28, 29,
- 64, 64, 31, 36, 32, 33, 34, 35,
- 64, 64, 37, 42, 38, 39, 40, 41,
- 64, 64, 43, 48, 44, 45, 46, 47
-};
-
-const uint8_t shiftkey_permtab[] = {
- 7, 7, /* 56 bit -> 56 bit */
- 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 1,
- 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 29
-};
-
-const uint8_t shiftkeyinv_permtab[] = {
- 7, 7,
- 28, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27,
- 56, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55
-};
-
-/*
-1 0
-1 0
-2 1
-2 1
-2 1
-2 1
-2 1
-2 1
-----
-1 0
-2 1
-2 1
-2 1
-2 1
-2 1
-2 1
-1 0
-*/
-#define ROTTABLE 0x7EFC
-#define ROTTABLE_INV 0x3F7E
-/******************************************************************************/
-
-void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out) {
- uint8_t ob; /* in-bytes and out-bytes */
- uint8_t byte, bit; /* counter for bit and byte */
- ob = ptable[1];
- ptable = &(ptable[2]);
- for (byte = 0; byte < ob; ++byte) {
- uint8_t t = 0;
- for (bit = 0; bit < 8; ++bit) {
- uint8_t x = *ptable++ - 1;
- t <<= 1;
- if ((in[x / 8]) & (0x80 >> (x % 8))) {
- t |= 0x01;
- }
- }
- out[byte] = t;
- }
-}
-
-/******************************************************************************/
-
-void changeendian32(uint32_t *a) {
- *a = (*a & 0x000000FF) << 24 |
- (*a & 0x0000FF00) << 8 |
- (*a & 0x00FF0000) >> 8 |
- (*a & 0xFF000000) >> 24;
-}
-
-/******************************************************************************/
-static inline
-void shiftkey(uint8_t *key) {
- uint8_t k[7];
- memcpy(k, key, 7);
- permute((uint8_t *)shiftkey_permtab, k, key);
-}
-
-/******************************************************************************/
-static inline
-void shiftkey_inv(uint8_t *key) {
- uint8_t k[7];
- memcpy(k, key, 7);
- permute((uint8_t *)shiftkeyinv_permtab, k, key);
-
-}
-
-/******************************************************************************/
-static inline
-uint64_t splitin6bitwords(uint64_t a) {
- uint64_t ret = 0;
- a &= 0x0000ffffffffffffLL;
- permute((uint8_t *)splitin6bitword_permtab, (uint8_t *)&a, (uint8_t *)&ret);
- return ret;
-}
-
-/******************************************************************************/
-
-static inline
-uint8_t substitute(uint8_t a, uint8_t *sbp) {
- uint8_t x;
- x = sbp[a >> 1];
- x = (a & 1) ? x & 0x0F : x >> 4;
- return x;
-
-}
-
-/******************************************************************************/
-
-uint32_t des_f(uint32_t r, uint8_t *kr) {
- uint8_t i;
- uint32_t t = 0, ret;
- uint64_t data = 0;
- uint8_t *sbp; /* sboxpointer */
- permute((uint8_t *)e_permtab, (uint8_t *)&r, (uint8_t *)&data);
- for (i = 0; i < 6; ++i)
- ((uint8_t *)&data)[i] ^= kr[i];
-
- /* Sbox substitution */
- data = splitin6bitwords(data);
- sbp = (uint8_t *)sbox;
- for (i = 0; i < 8; ++i) {
- uint8_t x;
- x = substitute(((uint8_t *)&data)[i], sbp);
- t <<= 4;
- t |= x;
- sbp += 32;
- }
- changeendian32(&t);
-
- permute((uint8_t *)p_permtab, (uint8_t *)&t, (uint8_t *)&ret);
-
- return ret;
-}
-
-/******************************************************************************/
-
-typedef struct {
- union {
- uint8_t v8[8];
- uint32_t v32[2];
- } d;
-} data_t;
-#define R (data.d.v32[1])
-#define L (data.d.v32[0])
-
-void des_enc(void *out, const void *in, const void *key) {
-
- uint8_t kr[6], k[7];
- uint8_t i;
- data_t data;
-
- permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
- permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
-
- for (i = 0; i < 8; ++i) {
- shiftkey(k);
- if (ROTTABLE & ((1 << ((i << 1) + 0))))
- shiftkey(k);
- permute((uint8_t *)pc2_permtab, k, kr);
- L ^= des_f(R, kr);
-
- shiftkey(k);
- if (ROTTABLE & ((1 << ((i << 1) + 1))))
- shiftkey(k);
- permute((uint8_t *)pc2_permtab, k, kr);
- R ^= des_f(L, kr);
-
- }
- /* L <-> R*/
- R ^= L;
- L ^= R;
- R ^= L;
-
- permute((uint8_t *)inv_ip_permtab, data.d.v8, (uint8_t *)out);
-}
-
-/******************************************************************************/
-
-void des_dec(void *out, const void *in, const uint8_t *key) {
-
- uint8_t kr[6], k[7];
- int8_t i;
- data_t data;
-
- permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
- permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
- for (i = 7; i >= 0; --i) {
-
- permute((uint8_t *)pc2_permtab, k, kr);
- L ^= des_f(R, kr);
- shiftkey_inv(k);
- if (ROTTABLE & ((1 << ((i << 1) + 1)))) {
- shiftkey_inv(k);
- }
-
- permute((uint8_t *)pc2_permtab, k, kr);
- R ^= des_f(L, kr);
- shiftkey_inv(k);
- if (ROTTABLE & ((1 << ((i << 1) + 0)))) {
- shiftkey_inv(k);
- }
-
- }
- /* L <-> R*/
- R ^= L;
- L ^= R;
- R ^= L;
-
- permute((uint8_t *)inv_ip_permtab, data.d.v8, (uint8_t *)out);
-}
-
-/******************************************************************************/
-
-void tdes_enc(void *out, void *in, const void *key) {
- des_enc(out, in, (uint8_t *)key + 0);
- des_dec(out, out, (uint8_t *)key + 8);
- des_enc(out, out, (uint8_t *)key + 16);
-}
-
-/******************************************************************************/
-
-void tdes_dec(void *out, void *in, const uint8_t *key) {
- des_dec(out, in, (uint8_t *)key + 16);
- des_enc(out, out, (uint8_t *)key + 8);
- des_dec(out, out, (uint8_t *)key + 0);
-}
-
-void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) {
-
- if (length % 8) return;
-
- uint8_t i;
- uint8_t *tin = (uint8_t *) in;
- uint8_t *tout = (uint8_t *) out;
-
- while (length > 0) {
- for (i = 0; i < 8; i++)
- tout[i] = (unsigned char)(tin[i] ^ iv[i]);
-
- des_enc(tout, tin, (uint8_t *)key + 0);
- des_dec(tout, tout, (uint8_t *)key + 8);
- des_enc(tout, tout, (uint8_t *)key + 0);
-
- memcpy(iv, tout, 8);
-
- tin += 8;
- tout += 8;
- length -= 8;
- }
-}
-
-void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) {
-
- if (length % 8) return;
-
- uint8_t i;
- unsigned char temp[8];
- uint8_t *tin = (uint8_t *) in;
- uint8_t *tout = (uint8_t *) out;
-
- while (length > 0) {
- memcpy(temp, tin, 8);
-
- des_dec(tout, tin, (uint8_t *)key + 0);
- des_enc(tout, tout, (uint8_t *)key + 8);
- des_dec(tout, tout, (uint8_t *)key + 0);
-
- for (i = 0; i < 8; i++)
- tout[i] = (unsigned char)(tout[i] ^ iv[i]);
-
- memcpy(iv, temp, 8);
-
- tin += 8;
- tout += 8;
- length -= 8;
- }
-}
-
-
-/******************************************************************************/
-
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/des.h b/pm3rdv4rrg/src/main/cpp/armsrc/des.h
deleted file mode 100644
index 8cf41b8a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/des.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* des.h */
-/*
- This file is part of the ARM-Crypto-Lib.
- Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-/**
- * \file des.h
- * \author Daniel Otte
- * \date 2007-06-16
- * \brief des and tdes declarations
- * \license GPLv3 or later
- *
- */
-#ifndef __DES_H_
-#define __DES_H_
-
-#include "common.h"
-
-/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
- * Also we only implement the three key mode */
-
-/** \def tdea_enc
- * \brief defining an alias for void tdes_enc(void* out, const void* in, const void* key)
- */
-
-/** \def tdea_dec
- * \brief defining an alias for void tdes_dec(void* out, const void* in, const void* key)
- */
-
-#define tdea_enc tdes_enc
-#define tdea_dec tdes_dec
-
-/** \fn void des_enc(void* out, const void* in, const void* key)
- * \brief encrypt a block with DES
- *
- * This function encrypts a block of 64 bits (8 bytes) with the DES algorithm.
- * Key expansion is done automatically. The key is 64 bits long, but note that
- * only 56 bits are used (the LSB of each byte is dropped). The input and output
- * blocks may overlap.
- *
- * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
- * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
- * \param key pointer to the key (64 bit = 8 byte)
- */
-void des_enc(void *out, const void *in, const void *key);
-
-/** \fn void des_dec(void* out, const void* in, const void* key)
- * \brief decrypt a block with DES
- *
- * This function decrypts a block of 64 bits (8 bytes) with the DES algorithm.
- * Key expansion is done automatically. The key is 64 bits long, but note that
- * only 56 bits are used (the LSB of each byte is dropped). The input and output
- * blocks may overlap.
- *
- * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
- * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
- * \param key pointer to the key (64 bit = 8 byte)
- */
-//void des_dec(void* out, const void* in, const void* key);
-void des_dec(void *out, const void *in, const uint8_t *key);
-
-/** \fn void tdes_enc(void* out, const void* in, const void* key)
- * \brief encrypt a block with Tripple-DES
- *
- * This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
- * algorithm. Key expansion is done automatically. The key is 192 bits long, but
- * note that only 178 bits are used (the LSB of each byte is dropped). The input
- * and output blocks may overlap.
- *
- * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
- * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
- * \param key pointer to the key (192 bit = 24 byte)
- */
-//void tdes_enc(void* out, const void* in, const void* key);
-void tdes_enc(void *out, void *in, const void *key);
-
-/** \fn void tdes_dec(void* out, const void* in, const void* key)
- * \brief decrypt a block with Tripple-DES
- *
- * This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
- * algorithm. Key expansion is done automatically. The key is 192 bits long, but
- * note that only 178 bits are used (the LSB of each byte is dropped). The input
- * and output blocks may overlap.
- *
- * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
- * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
- * \param key pointer to the key (192 bit = 24 byte)
- */
-//void tdes_dec(void* out, const void* in, const void* key);
-void tdes_dec(void *out, void *in, const uint8_t *key);
-
-void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
-void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
-
-// Copied from des.h in desfire imp.
-typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */
-typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */
-
-extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */
-
-#endif /*DES_H_*/
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/desfire.h b/pm3rdv4rrg/src/main/cpp/armsrc/desfire.h
deleted file mode 100644
index 9fc6441b..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/desfire.h
+++ /dev/null
@@ -1,171 +0,0 @@
-#ifndef __DESFIRE_H
-#define __DESFIRE_H
-
-#include "common.h"
-#include "mifare.h"
-
-#define MAX_CRYPTO_BLOCK_SIZE 16
-/* Mifare DESFire EV1 Application crypto operations */
-#define APPLICATION_CRYPTO_DES 0x00
-#define APPLICATION_CRYPTO_3K3DES 0x40
-#define APPLICATION_CRYPTO_AES 0x80
-
-#define MAC_LENGTH 4
-#define CMAC_LENGTH 8
-
-typedef enum {
- MCD_SEND,
- MCD_RECEIVE
-} MifareCryptoDirection;
-
-typedef enum {
- MCO_ENCYPHER,
- MCO_DECYPHER
-} MifareCryptoOperation;
-
-#define MDCM_MASK 0x000F
-
-#define CMAC_NONE 0
-
-// Data write to the PICC is used to update the CMAC
-#define CMAC_COMMAND 0x010
-// Data received from the PICC is used to update the CMAC
-#define CMAC_VERIFY 0x020
-
-// MAC the command (when MDCM_MACED)
-#define MAC_COMMAND 0x100
-// The command returns a MAC to verify (when MDCM_MACED)
-#define MAC_VERIFY 0x200
-
-#define ENC_COMMAND 0x1000
-#define NO_CRC 0x2000
-
-#define MAC_MASK 0x0F0
-#define CMAC_MACK 0xF00
-
-/* Communication mode */
-#define MDCM_PLAIN 0x00
-#define MDCM_MACED 0x01
-#define MDCM_ENCIPHERED 0x03
-
-/* Error code managed by the library */
-#define CRYPTO_ERROR 0x01
-
-
-enum DESFIRE_AUTH_SCHEME {
- AS_LEGACY,
- AS_NEW
-};
-
-enum DESFIRE_CRYPTOALGO {
- T_DES = 0x00,
- T_3DES = 0x01,
- T_3K3DES = 0x02,
- T_AES = 0x03
-};
-
-
-#define DESFIRE_KEY(key) ((struct desfire_key *) key)
-struct desfire_key {
- enum DESFIRE_CRYPTOALGO type;
- uint8_t data[24];
- uint8_t cmac_sk1[24];
- uint8_t cmac_sk2[24];
- uint8_t aes_version;
-};
-typedef struct desfire_key *desfirekey_t;
-
-#define DESFIRE(tag) ((struct desfire_tag *) tag)
-struct desfire_tag {
- iso14a_card_select_t info;
- int active;
- uint8_t last_picc_error;
- uint8_t last_internal_error;
- uint8_t last_pcd_error;
- desfirekey_t session_key;
- enum DESFIRE_AUTH_SCHEME authentication_scheme;
- uint8_t authenticated_key_no;
-
- uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE];
- uint8_t cmac[16];
- uint8_t *crypto_buffer;
- size_t crypto_buffer_size;
- uint32_t selected_application;
-};
-typedef struct desfire_tag *desfiretag_t;
-
-
-/* File types */
-enum DESFIRE_FILE_TYPES {
- MDFT_STANDARD_DATA_FILE = 0x00,
- MDFT_BACKUP_DATA_FILE = 0x01,
- MDFT_VALUE_FILE_WITH_BACKUP = 0x02,
- MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03,
- MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04
-};
-
-enum DESFIRE_STATUS {
- OPERATION_OK = 0x00,
- NO_CHANGES = 0x0c,
- OUT_OF_EEPROM_ERROR = 0x0e,
- ILLEGAL_COMMAND_CODE = 0x1c,
- INTEGRITY_ERROR = 0x1e,
- NO_SUCH_KEY = 0x40,
- LENGTH_ERROR = 0x7e,
- PERMISSION_DENIED = 0x9d,
- PARAMETER_ERROR = 0x9e,
- APPLICATION_NOT_FOUND = 0xa0,
- APPL_INTEGRITY_ERROR = 0xa1,
- AUTHENTICATION_ERROR = 0xae,
- ADDITIONAL_FRAME = 0xaf,
- BOUNDARY_ERROR = 0xbe,
- PICC_INTEGRITY_ERROR = 0xc1,
- COMMAND_ABORTED = 0xca,
- PICC_DISABLED_ERROR = 0xcd,
- COUNT_ERROR = 0xce,
- DUPLICATE_ERROR = 0xde,
- EEPROM_ERROR = 0xee,
- FILE_NOT_FOUND = 0xf0,
- FILE_INTEGRITY_ERROR = 0xf1
-};
-
-enum DESFIRE_CMD {
- CREATE_APPLICATION = 0xca,
- DELETE_APPLICATION = 0xda,
- GET_APPLICATION_IDS = 0x6a,
- SELECT_APPLICATION = 0x5a,
- FORMAT_PICC = 0xfc,
- GET_VERSION = 0x60,
- READ_DATA = 0xbd,
- WRITE_DATA = 0x3d,
- GET_VALUE = 0x6c,
- CREDIT = 0x0c,
- DEBIT = 0xdc,
- LIMITED_CREDIT = 0x1c,
- WRITE_RECORD = 0x3b,
- READ_RECORDS = 0xbb,
- CLEAR_RECORD_FILE = 0xeb,
- COMMIT_TRANSACTION = 0xc7,
- ABORT_TRANSACTION = 0xa7,
- GET_FREE_MEMORY = 0x6e,
- GET_FILE_IDS = 0x6f,
- GET_FILE_SETTINGS = 0xf5,
- CHANGE_FILE_SETTINGS = 0x5f,
- CREATE_STD_DATA_FILE = 0xcd,
- CREATE_BACKUP_DATA_FILE = 0xcb,
- CREATE_VALUE_FILE = 0xcc,
- CREATE_LINEAR_RECORD_FILE = 0xc1,
- CREATE_CYCLIC_RECORD_FILE = 0xc0,
- DELETE_FILE = 0xdf,
- AUTHENTICATE = 0x0a, // AUTHENTICATE_NATIVE
- AUTHENTICATE_ISO = 0x1a, // AUTHENTICATE_STANDARD
- AUTHENTICATE_AES = 0xaa,
- CHANGE_KEY_SETTINGS = 0x54,
- GET_KEY_SETTINGS = 0x45,
- CHANGE_KEY = 0xc4,
- GET_KEY_VERSION = 0x64,
- AUTHENTICATION_FRAME = 0xAF
-};
-
-#endif
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_crypto_disabled.c b/pm3rdv4rrg/src/main/cpp/armsrc/desfire_crypto_disabled.c
deleted file mode 100644
index eabd4f4a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_crypto_disabled.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*-
- * Copyright (C) 2010, Romain Tartiere.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see
- *
- * $Id$
- */
-
-/*
- * This implementation was written based on information provided by the
- * following documents:
- *
- * NIST Special Publication 800-38B
- * Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
- * May 2005
- */
-#include
-
-#include "desfire_crypto.h"
-
-#include "crc32.h"
-#include "printf.h"
-#include "desfire.h"
-#include "iso14443a.h"
-#include "mbedtls/aes.h"
-
-static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
-static size_t key_macing_length(desfirekey_t key);
-
-// iceman, see memxor inside string.c, dest/src swapped..
-static void xor(const uint8_t *ivect, uint8_t *data, const size_t len) {
- for (size_t i = 0; i < len; i++) {
- data[i] ^= ivect[i];
- }
-}
-
-void cmac_generate_subkeys(desfirekey_t key) {
- int kbs = key_block_size(key);
- const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
-
- uint8_t l[kbs];
- memset(l, 0, kbs);
-
- uint8_t ivect[kbs];
- memset(ivect, 0, kbs);
-
- mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
-
- bool xor = false;
-
- // Used to compute CMAC on complete blocks
- memcpy(key->cmac_sk1, l, kbs);
- xor = l[0] & 0x80;
- lsl(key->cmac_sk1, kbs);
- if (xor)
- key->cmac_sk1[kbs - 1] ^= R;
-
- // Used to compute CMAC on the last block if non-complete
- memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
- xor = key->cmac_sk1[0] & 0x80;
- lsl(key->cmac_sk2, kbs);
- if (xor)
- key->cmac_sk2[kbs - 1] ^= R;
-}
-
-void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) {
- int kbs = key_block_size(key);
- uint8_t *buffer = malloc(padded_data_length(len, kbs));
-
- memcpy(buffer, data, len);
-
- if ((!len) || (len % kbs)) {
- buffer[len++] = 0x80;
- while (len % kbs) {
- buffer[len++] = 0x00;
- }
- xor(key->cmac_sk2, buffer + len - kbs, kbs);
- } else {
- xor(key->cmac_sk1, buffer + len - kbs, kbs);
- }
-
- mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
-
- memcpy(cmac, ivect, kbs);
- free(buffer);
-}
-
-size_t key_block_size(const desfirekey_t key) {
- if (key == NULL)
- return 0;
- size_t block_size = 8;
- switch (key->type) {
- case T_DES:
- case T_3DES:
- case T_3K3DES:
- block_size = 8;
- break;
- case T_AES:
- block_size = 16;
- break;
- }
- return block_size;
-}
-
-/*
- * Size of MACing produced with the key.
- */
-static size_t key_macing_length(const desfirekey_t key) {
- size_t mac_length = MAC_LENGTH;
- switch (key->type) {
- case T_DES:
- case T_3DES:
- mac_length = MAC_LENGTH;
- break;
- case T_3K3DES:
- case T_AES:
- mac_length = CMAC_LENGTH;
- break;
- }
- return mac_length;
-}
-
-/*
- * Size required to store nbytes of data in a buffer of size n*block_size.
- */
-size_t padded_data_length(const size_t nbytes, const size_t block_size) {
- if ((!nbytes) || (nbytes % block_size))
- return ((nbytes / block_size) + 1) * block_size;
- else
- return nbytes;
-}
-
-/*
- * Buffer size required to MAC nbytes of data
- */
-size_t maced_data_length(const desfirekey_t key, const size_t nbytes) {
- return nbytes + key_macing_length(key);
-}
-/*
- * Buffer size required to encipher nbytes of data and a two bytes CRC.
- */
-size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings) {
- size_t crc_length = 0;
- if (!(communication_settings & NO_CRC)) {
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- crc_length = 2;
- break;
- case AS_NEW:
- crc_length = 4;
- break;
- }
- }
-
- size_t block_size = DESFIRE(tag)->session_key ? key_block_size(DESFIRE(tag)->session_key) : 1;
-
- return padded_data_length(nbytes + crc_length, block_size);
-}
-
-void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings) {
- uint8_t *res = data;
- uint8_t mac[4];
- size_t edl;
- bool append_mac = true;
- desfirekey_t key = DESFIRE(tag)->session_key;
-
- if (!key)
- return data;
-
- switch (communication_settings & MDCM_MASK) {
- case MDCM_PLAIN:
- if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
- break;
-
- /*
- * When using new authentication methods, PLAIN data transmission from
- * the PICC to the PCD are CMACed, so we have to maintain the
- * cryptographic initialisation vector up-to-date to check data
- * integrity later.
- *
- * The only difference with CMACed data transmission is that the CMAC
- * is not apended to the data write by the PCD to the PICC.
- */
-
- append_mac = false;
-
- /* pass through */
- case MDCM_MACED:
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- if (!(communication_settings & MAC_COMMAND))
- break;
-
- /* pass through */
- edl = padded_data_length(*nbytes - offset, key_block_size(DESFIRE(tag)->session_key)) + offset;
-
- // Fill in the crypto buffer with data ...
- memcpy(res, data, *nbytes);
- // ... and 0 padding
- memset(res + *nbytes, 0, edl - *nbytes);
-
- mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
-
- memcpy(mac, res + edl - 8, 4);
-
- // Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
- memcpy(res, data, *nbytes);
-
- if (!(communication_settings & MAC_COMMAND))
- break;
- // Append MAC
- size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
- bla++;
-
- memcpy(res + *nbytes, mac, 4);
-
- *nbytes += 4;
- break;
- case AS_NEW:
- if (!(communication_settings & CMAC_COMMAND))
- break;
- cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
-
- if (append_mac) {
- size_t len = maced_data_length(key, *nbytes);
- ++len;
- memcpy(res, data, *nbytes);
- memcpy(res + *nbytes, DESFIRE(tag)->cmac, CMAC_LENGTH);
- *nbytes += CMAC_LENGTH;
- }
- break;
- }
-
- break;
- case MDCM_ENCIPHERED:
- /* |<-------------- data -------------->|
- * |<--- offset -->| |
- * +---------------+--------------------+-----+---------+
- * | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING |
- * +---------------+--------------------+-----+---------+ ----------------
- * | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES)
- * | | `---- crc16() ----' | |
- * | | | ^ | | ----- *or* -----
- * |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES)
- * | `---- crc32() ----' | |
- * | | ---- *then* ----
- * |<---------------------------------->|
- * encypher()/decypher()
- */
-
- if (!(communication_settings & ENC_COMMAND))
- break;
- edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
-
- // Fill in the crypto buffer with data ...
- memcpy(res, data, *nbytes);
- if (!(communication_settings & NO_CRC)) {
- // ... CRC ...
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- AddCrc14A(res + offset, *nbytes - offset);
- *nbytes += 2;
- break;
- case AS_NEW:
- crc32_append(res, *nbytes);
- *nbytes += 4;
- break;
- }
- }
- // ... and padding
- memset(res + *nbytes, 0, edl - *nbytes);
-
- *nbytes = edl;
-
- mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
- break;
- default:
-
- *nbytes = -1;
- res = NULL;
- break;
- }
-
- return res;
-
-}
-
-void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
- void *res = data;
- void *edata = NULL;
- uint8_t first_cmac_byte = 0x00;
-
- desfirekey_t key = DESFIRE(tag)->session_key;
-
- if (!key)
- return data;
-
- // Return directly if we just have a status code.
- if (1 == *nbytes)
- return res;
-
- switch (communication_settings & MDCM_MASK) {
- case MDCM_PLAIN:
-
- if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
- break;
-
- /* pass through */
- case MDCM_MACED:
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- if (communication_settings & MAC_VERIFY) {
- *nbytes -= key_macing_length(key);
- if (*nbytes == 0) {
- *nbytes = -1;
- res = NULL;
-#ifdef WITH_DEBUG
- Dbprintf("No room for MAC!");
-#endif
- break;
- }
-
- size_t edl = enciphered_data_length(tag, *nbytes - 1, communication_settings);
- edata = malloc(edl);
-
- memcpy(edata, data, *nbytes - 1);
- memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
-
- mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
-
- if (0 != memcmp((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
-#ifdef WITH_DEBUG
- Dbprintf("MACing not verified");
- hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0);
- hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0);
-#endif
- DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
- *nbytes = -1;
- res = NULL;
- }
- }
- break;
- case AS_NEW:
- if (!(communication_settings & CMAC_COMMAND))
- break;
- if (communication_settings & CMAC_VERIFY) {
- if (*nbytes < 9) {
- *nbytes = -1;
- res = NULL;
- break;
- }
- first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
- ((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
- }
-
- int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
- cmac(key, DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE(tag)->cmac);
-
- if (communication_settings & CMAC_VERIFY) {
- ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
- if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
-#ifdef WITH_DEBUG
- Dbprintf("CMAC NOT verified :-(");
- hexdump((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
- hexdump(DESFIRE(tag)->cmac, 8, "Actual ", 0);
-#endif
- DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
- *nbytes = -1;
- res = NULL;
- } else {
- *nbytes -= 8;
- }
- }
- break;
- }
-
- free(edata);
-
- break;
- case MDCM_ENCIPHERED:
- (*nbytes)--;
- bool verified = false;
- int crc_pos = 0x00;
- int end_crc_pos = 0x00;
- uint8_t x;
-
- /*
- * AS_LEGACY:
- * ,-----------------+-------------------------------+--------+
- * \ BLOCK n-1 | BLOCK n | STATUS |
- * / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
- * `-----------------+-------------------------------+--------+
- *
- * <------------ DATA ------------>
- * FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
- *
- * AS_NEW:
- * ,-------------------------------+-----------------------------------------------+--------+
- * \ BLOCK n-1 | BLOCK n | STATUS |
- * / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
- * `-------------------------------+-----------------------------------------------+--------+
- * <----------------------------------- DATA ------------------------------------->|
- *
- * <----------------- DATA ---------------->
- * FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
- * `------------------'
- */
-
- mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
-
- /*
- * Look for the CRC and ensure it is followed by NULL padding. We
- * can't start by the end because the CRC is supposed to be 0 when
- * verified, and accumulating 0's in it should not change it.
- */
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
- if (crc_pos < 0) {
- /* Single block */
- crc_pos = 0;
- }
- break;
- case AS_NEW:
- /* Move status between payload and CRC */
- res = DESFIRE(tag)->crypto_buffer;
- memcpy(res, data, *nbytes);
-
- crc_pos = (*nbytes) - 16 - 3;
- if (crc_pos < 0) {
- /* Single block */
- crc_pos = 0;
- }
- memcpy((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
- ((uint8_t *)res)[crc_pos] = 0x00;
- crc_pos++;
- *nbytes += 1;
- break;
- }
-
- do {
- uint16_t crc_16 = 0x00;
- uint32_t crc;
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- AddCrc14A((uint8_t *)res, end_crc_pos);
- end_crc_pos = crc_pos + 2;
- //
-
-
- crc = crc_16;
- break;
- case AS_NEW:
- end_crc_pos = crc_pos + 4;
- crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
- break;
- }
- if (!crc) {
- verified = true;
- for (int n = end_crc_pos; n < *nbytes - 1; n++) {
- uint8_t byte = ((uint8_t *)res)[n];
- if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos))))
- verified = false;
- }
- }
- if (verified) {
- *nbytes = crc_pos;
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- ((uint8_t *)data)[(*nbytes)++] = 0x00;
- break;
- case AS_NEW:
- /* The status byte was already before the CRC */
- break;
- }
- } else {
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- break;
- case AS_NEW:
- x = ((uint8_t *)res)[crc_pos - 1];
- ((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
- ((uint8_t *)res)[crc_pos] = x;
- break;
- }
- crc_pos++;
- }
- } while (!verified && (end_crc_pos < *nbytes));
-
- if (!verified) {
-#ifdef WITH_DEBUG
- /* FIXME In some configurations, the file is transmitted PLAIN */
- Dbprintf("CRC not verified in decyphered stream");
-#endif
- DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
- *nbytes = -1;
- res = NULL;
- }
-
- break;
- default:
- Dbprintf("Unknown communication settings");
- *nbytes = -1;
- res = NULL;
- break;
-
- }
- return res;
-}
-
-
-void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) {
- uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
-
- if (direction == MCD_SEND) {
- xor(ivect, data, block_size);
- } else {
- memcpy(ovect, data, block_size);
- }
-
- uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
-
- switch (key->type) {
- case T_DES:
- switch (operation) {
- case MCO_ENCYPHER:
- //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
- des_enc(edata, data, key->data);
- break;
- case MCO_DECYPHER:
- //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
- des_dec(edata, data, key->data);
- break;
- }
- break;
- case T_3DES:
- switch (operation) {
- case MCO_ENCYPHER:
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
- // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
- tdes_enc(edata, data, key->data);
- break;
- case MCO_DECYPHER:
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
- // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
- tdes_dec(data, edata, key->data);
- break;
- }
- break;
- case T_3K3DES:
- switch (operation) {
- case MCO_ENCYPHER:
- tdes_enc(edata, data, key->data);
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
- // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
- break;
- case MCO_DECYPHER:
- tdes_dec(data, edata, key->data);
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
- // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
- // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
- break;
- }
- break;
- case T_AES:
- switch (operation) {
- case MCO_ENCYPHER: {
- mbedtls_aes_context ctx;
- mbedtls_aes_init(&ctx);
- mbedtls_aes_setkey_enc(&ctx, key->data, 128);
- mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, sizeof(edata), ivect, data, edata);
- mbedtls_aes_free(&ctx);
- break;
- }
- case MCO_DECYPHER: {
- mbedtls_aes_context ctx;
- mbedtls_aes_init(&ctx);
- mbedtls_aes_setkey_dec(&ctx, key->data, 128);
- mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, sizeof(edata), ivect, edata, data);
- mbedtls_aes_free(&ctx);
- break;
- }
- }
- break;
- }
-
- memcpy(data, edata, block_size);
-
- if (direction == MCD_SEND) {
- memcpy(ivect, data, block_size);
- } else {
- xor(ivect, data, block_size);
- memcpy(ivect, ovect, block_size);
- }
-}
-
-/*
- * This function performs all CBC cyphering / deciphering.
- *
- * The tag argument may be NULL, in which case both key and ivect shall be set.
- * When using the tag session_key and ivect for processing data, these
- * arguments should be set to NULL.
- *
- * Because the tag may contain additional data, one may need to call this
- * function with tag, key and ivect defined.
- */
-void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) {
- size_t block_size;
-
- if (tag) {
- if (!key)
- key = DESFIRE(tag)->session_key;
- if (!ivect)
- ivect = DESFIRE(tag)->ivect;
-
- switch (DESFIRE(tag)->authentication_scheme) {
- case AS_LEGACY:
- memset(ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
- break;
- case AS_NEW:
- break;
- }
- }
-
- block_size = key_block_size(key);
-
- size_t offset = 0;
- while (offset < data_size) {
- mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size);
- offset += block_size;
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_crypto_disabled.h b/pm3rdv4rrg/src/main/cpp/armsrc/desfire_crypto_disabled.h
deleted file mode 100644
index 23043b30..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_crypto_disabled.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __DESFIRE_CRYPTO_H
-#define __DESFIRE_CRYPTO_H
-
-#include "common.h"
-#include "desfire.h"
-
-void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
-void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
-void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
-void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
-size_t key_block_size(const desfirekey_t key);
-size_t padded_data_length(const size_t nbytes, const size_t block_size);
-size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
-size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
-void cmac_generate_subkeys(desfirekey_t key);
-void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_key.c b/pm3rdv4rrg/src/main/cpp/armsrc/desfire_key.c
deleted file mode 100644
index 272f1856..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_key.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*-
- * Copyright (C) 2010, Romain Tartiere.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see
- *
- * $Id$
- */
-
-#include "desfire_key.h"
-#include "string.h"
-
-static inline void update_key_schedules(desfirekey_t key);
-
-static inline void update_key_schedules(desfirekey_t key) {
- // DES_set_key ((DES_cblock *)key->data, &(key->ks1));
- // DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
- // if (T_3K3DES == key->type) {
- // DES_set_key ((DES_cblock *)(key->data + 16), &(key->ks3));
- // }
-}
-
-void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) {
- uint8_t data[8];
- memcpy(data, value, 8);
- for (int n = 0; n < 8; n++)
- data[n] &= 0xfe;
- Desfire_des_key_new_with_version(data, key);
-}
-
-void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key) {
- if (key != NULL) {
- key->type = T_DES;
- memcpy(key->data, value, 8);
- memcpy(key->data + 8, value, 8);
- update_key_schedules(key);
- }
-}
-
-void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key) {
- uint8_t data[16];
- memcpy(data, value, 16);
- for (int n = 0; n < 8; n++)
- data[n] &= 0xfe;
- for (int n = 8; n < 16; n++)
- data[n] |= 0x01;
- Desfire_3des_key_new_with_version(data, key);
-}
-
-void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key) {
- if (key != NULL) {
- key->type = T_3DES;
- memcpy(key->data, value, 16);
- memcpy(key->data + 16, value, 8);
- update_key_schedules(key);
- }
-}
-
-void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key) {
- uint8_t data[24];
- memcpy(data, value, 24);
- for (int n = 0; n < 8; n++)
- data[n] &= 0xfe;
- Desfire_3k3des_key_new_with_version(data, key);
-}
-
-void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key) {
- if (key != NULL) {
- key->type = T_3K3DES;
- memcpy(key->data, value, 24);
- update_key_schedules(key);
- }
-}
-
-void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key) {
- Desfire_aes_key_new_with_version(value, 0, key);
-}
-
-void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key) {
-
- if (key != NULL) {
- memcpy(key->data, value, 16);
- key->type = T_AES;
- key->aes_version = version;
- }
-}
-
-uint8_t Desfire_key_get_version(desfirekey_t key) {
- uint8_t version = 0;
-
- for (int n = 0; n < 8; n++) {
- version |= ((key->data[n] & 1) << (7 - n));
- }
- return version;
-}
-
-void Desfire_key_set_version(desfirekey_t key, uint8_t version) {
- for (int n = 0; n < 8; n++) {
- uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n));
- key->data[n] &= 0xfe;
- key->data[n] |= version_bit;
- if (key->type == T_DES) {
- key->data[n + 8] = key->data[n];
- } else {
- // Write ~version to avoid turning a 3DES key into a DES key
- key->data[n + 8] &= 0xfe;
- key->data[n + 8] |= ~version_bit;
- }
- }
-}
-
-void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
-
- uint8_t buffer[24];
-
- switch (authkey->type) {
- case T_DES:
- memcpy(buffer, rnda, 4);
- memcpy(buffer + 4, rndb, 4);
- Desfire_des_key_new_with_version(buffer, key);
- break;
- case T_3DES:
- memcpy(buffer, rnda, 4);
- memcpy(buffer + 4, rndb, 4);
- memcpy(buffer + 8, rnda + 4, 4);
- memcpy(buffer + 12, rndb + 4, 4);
- Desfire_3des_key_new_with_version(buffer, key);
- break;
- case T_3K3DES:
- memcpy(buffer, rnda, 4);
- memcpy(buffer + 4, rndb, 4);
- memcpy(buffer + 8, rnda + 6, 4);
- memcpy(buffer + 12, rndb + 6, 4);
- memcpy(buffer + 16, rnda + 12, 4);
- memcpy(buffer + 20, rndb + 12, 4);
- Desfire_3k3des_key_new(buffer, key);
- break;
- case T_AES:
- memcpy(buffer, rnda, 4);
- memcpy(buffer + 4, rndb, 4);
- memcpy(buffer + 8, rnda + 12, 4);
- memcpy(buffer + 12, rndb + 12, 4);
- Desfire_aes_key_new(buffer, key);
- break;
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_key.h b/pm3rdv4rrg/src/main/cpp/armsrc/desfire_key.h
deleted file mode 100644
index 603fd566..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/desfire_key.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __DESFIRE_KEY_INCLUDED
-#define __DESFIRE_KEY_INCLUDED
-
-#include "common.h"
-#include "desfire.h"
-void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
-void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
-void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
-void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key);
-void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key);
-void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key);
-void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key);
-void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key);
-uint8_t Desfire_key_get_version(desfirekey_t key);
-void Desfire_key_set_version(desfirekey_t key, uint8_t version);
-void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/emvtags.h b/pm3rdv4rrg/src/main/cpp/armsrc/emvtags.h
deleted file mode 100644
index 40499f7a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/emvtags.h
+++ /dev/null
@@ -1,248 +0,0 @@
-//-----------------------------------------------------------------------------
-// Peter Fillmore 2014
-// code derived off merloks mifare code
-//
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// structure to hold EMV card and terminal parameters
-//-----------------------------------------------------------------------------
-#ifndef __EMVCARD_H
-#define __EMVCARD_H
-
-#include "common.h"
-
-//structure to hold received/set tag values
-//variable data inputs have length specifiers
-typedef struct {
- //ISO14443-A card stuff
- uint8_t ATQA[2]; //Answer to Request
- uint8_t UID_len;
- uint8_t UID[10];
- uint8_t SAK1; //SAK for UID 1
- uint8_t SAK2; //SAK for UID 2
- uint8_t ATS_len; //Answer to select
- uint8_t ATS[256];
- //ATS
- uint8_t TL;
- uint8_t T0;
- uint8_t TA1;
- uint8_t TB1;
- uint8_t TC1;
- uint8_t *historicalbytes;
- //PPS response
- uint8_t PPSS;
- //SFI 2 record 1
- uint8_t tag_4F_len; //length of AID
- uint8_t tag_4F[16]; //Application Identifier (AID)
- uint8_t tag_50_len; //length of maps label
- uint8_t tag_50[16]; //Application Label
- uint8_t tag_56_len; //track1 length
- uint8_t tag_56[76]; //Track 1 Data
- uint8_t tag_57_len; //track2 equiv len
- uint8_t tag_57[19]; //Track 2 Equivalent Data
- uint8_t tag_5A_len; //PAN length
- uint8_t tag_5A[10]; //Application Primary Account Number (PAN)
- //uint8_t tag_6F[]; //File Control Information (FCI) Template
- //uint8_t tag_70[255]; //Record Template
- //uint8_t tag_77[]; //Response Message Template Format 2
- //uint8_t tag_80[]; //Response Message Template Format 1
- uint8_t tag_82[2]; //Application Interchange Profile AIP
- //uint8_t tag_83[]; //Command Template
- uint8_t tag_84_len;
- uint8_t tag_84[16]; //DF Name
- uint8_t tag_86_len;
- uint8_t tag_86[261]; //Issuer Script Command
- uint8_t tag_87[1]; //Application Priority Indicator
- uint8_t tag_88[1]; //Short File Identifier
- uint8_t tag_8A[2]; //Authorisation Response Code
- uint8_t tag_8C_len;
- uint8_t tag_8C[252]; //CDOL1
- uint8_t tag_8D_len;
- uint8_t tag_8D[252]; //CDOL2
- uint8_t tag_8E_len;
- uint8_t tag_8E[252]; //Cardholder Verification Method (CVM) List
- uint8_t tag_8F[1]; //Certification Authority Public Key Index
- uint8_t tag_90_len;
- uint8_t tag_90[255]; //ssuer Public Key Certificate
- uint8_t tag_92_len;
- uint8_t tag_92[255]; //Issuer Public Key Remainder
- uint8_t tag_93_len;
- uint8_t tag_93[255]; //Signed Static Application Data
- uint8_t tag_94_len;
- uint8_t tag_94[252]; //Application File Locator AFL
- uint8_t tag_95[5]; //Terminal Verification Results
- uint8_t tag_97_len;
- uint8_t tag_97[252]; //Transaction Certificate Data Object List (TDOL)
- uint8_t tag_98[20]; //Transaction Certificate (TC) Hash Value
- //assume 20 bytes, change after testing
- uint8_t tag_99_len;
- uint8_t tag_99[20]; //Transaction Personal Identification Number (PIN) Data
- uint8_t tag_9A[3]; //Transaction Date
- uint8_t tag_9B[2]; //Transaction Status Information
- uint8_t tag_9C[1]; //Transaction Type
- uint8_t tag_9D_len;
- uint8_t tag_9D[16]; //Directory Definition File
-
- uint8_t tag_CD[3]; //Card Issuer Action Codes Paypass
- uint8_t tag_CE[3];
- uint8_t tag_CF[3];
-
- uint8_t tag_D7[3]; //Application Control (PayPass)
- uint8_t tag_D8[2]; //Application Interchange Profile (PayPass)
- uint8_t tag_D9_len; //Application File Locator (PayPass)
- uint8_t tag_D9[16];
- uint8_t tag_DA[2]; //Static CVC3track1
- uint8_t tag_DB[2]; //Static CVC3track2
- uint8_t tag_DC[2]; //IVCVC3 CVC3track1
- uint8_t tag_DD[2]; //IVCVC3 CVC3track2
-
- uint8_t tag_AF_len;
- uint8_t tag_AF[255]; //Proprietary Information
-
- uint8_t tag_5F20_len;
- uint8_t tag_5F20[26]; //Cardholder Name
- uint8_t tag_5F24[3]; //Application Expiry Date
- uint8_t tag_5F25[3]; //Application Effective Date YYMMDD
- uint8_t tag_5F28[2]; //Issuer Country Code
- uint8_t tag_5F2A[2]; //Transaction Currency Code
- uint8_t tag_5F2D_len;
- uint8_t tag_5F2D[8]; //Language Preference
- uint8_t tag_5F30[2]; //Service Code
- uint8_t tag_5F34[1]; //Application Primary Account Number (PAN) Sequence Number
- uint8_t tag_5F36[2]; //ATC
- uint8_t tag_5F50_len;
- uint8_t tag_5F50[255]; //Issuer URL
- uint8_t tag_5F54_len;
- uint8_t tag_5F54[11]; //Bank Identifier Code (BIC)
- uint8_t tag_9F01[6]; //Acquirer Identifier
- uint8_t tag_9F02[6]; // Amount, Authorised (Numeric)
- uint8_t tag_9F03[6]; //Amount, Other (Numeric)
- uint8_t tag_9F04[4]; //Amount, Other (Binary)
- uint8_t tag_9F05_len;
- uint8_t tag_9F05[32]; //Application Discretionary Data
- uint8_t tag_9F06_len;
- uint8_t tag_9F06[16]; //AID terminal
- uint8_t tag_9F07[2]; //Application Usage Control
- uint8_t tag_9F08[2]; //Application Version Number
- uint8_t tag_9F09[2]; //Application Version Number
- //uint8_t tag_9F0A[2]
- uint8_t tag_9F0B_len;
- uint8_t tag_9F0B[45]; //Cardholder Name Extended
- uint8_t tag_9F0D[5]; //Issuer Action Code - Default
- uint8_t tag_9F0E[5]; //Issuer Action Code - Denial
- uint8_t tag_9F0F[5]; //Issuer Action Code - Online
- uint8_t tag_9F10_len; //Issuer Application Data
- uint8_t tag_9F10[32];
- uint8_t tag_9F11[1]; //Issuer Code Table Index
- uint8_t tag_9F12_len;
- uint8_t tag_9F12[255]; //Application Preferred Name
- uint8_t tag_9F13[2]; //Last Online Application Transaction Counter (ATC) Registerjk
- uint8_t tag_9F14[1]; //Lower Consecutive Offline Limit
- uint8_t tag_9F15[2]; //Merchant Category Code
- uint8_t tag_9F16[15]; //Merchant Identifier
- uint8_t tag_9F17[1]; //Personal Identification Number (PIN) Try Counter
- uint8_t tag_9F18[4]; //Issuer Script Identifier
- //uint8_t tag_9F19[]
- uint8_t tag_9F1A[2]; //Terminal Country Code
- uint8_t tag_9F1B[4]; //Terminal Floor Limit
- uint8_t tag_9F1C[8]; //Terminal Identification
- uint8_t tag_9F1D_len;
- uint8_t tag_9F1D[8]; //Terminal Risk Management Data
- uint8_t tag_9F1E[8]; //Interface Device (IFD) Serial Number
- uint8_t tag_9F1F_len;
- uint8_t tag_9F1F[255]; //Track 1 Discretionary Data
- uint8_t tag_9F20_len;
- uint8_t tag_9F20[255]; //Track 2 DD
- uint8_t tag_9F21[3]; //Transaction Time
- uint8_t tag_9F22[1]; //Certification Authority Public Key Index
- uint8_t tag_9F23[1]; //Upper Consecutive Offline Limit
- //uint8_t tag_9F24
- //uint8_t tag_9F25
- uint8_t tag_9F26[8]; //Application Cryptogram
- uint8_t tag_9F27[1]; //Cryptogram Information Data
- //uint8_t tag_9F28
- //uint8_t tag_9F29
- //uint8_t tag_9F2A
- //uint8_t tag_9F2B
- //uint8_t tag_9F2C
- uint8_t tag_9F2D_len;
- uint8_t tag_9F2D[255]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Certificate
- uint8_t tag_9F2E[3]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Exponent
- uint8_t tag_9F2F_len;
- uint8_t tag_9F2F[255]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Remainder
- //uint8_t tag_9F30
- //uint8_t tag_9F31
- uint8_t tag_9F32_len;
- uint8_t tag_9F32[3]; //Issuer Public Key Exponent
- uint8_t tag_9F33[3]; //Terminal Capabilities
- uint8_t tag_9F34[3]; //Cardholder Verification Method (CVM) Results
- uint8_t tag_9F35[1]; //Terminal Type
- uint8_t tag_9F36[2]; //Application Transaction Counter (ATC)
- uint8_t tag_9F37[8]; //Unpredictable Number
- uint8_t tag_9F38_len;
- uint8_t tag_9F38[255]; //PDOL
- uint8_t tag_9F39[1]; //Point-of-Service (POS) Entry Mode
- uint8_t tag_9F40[5]; //Additional Terminal Capabilities
- uint8_t tag_9F41[4]; //Transaction Sequence Counter
- uint8_t tag_9F42[2]; //Application Currency Code
- uint8_t tag_9F43[4]; //Application Reference Currency Exponent
- uint8_t tag_9F44[1]; //Application Currency Exponent
- uint8_t tag_9F45[2]; //Data Authentication Code
- uint8_t tag_9F46_len;
- uint8_t tag_9F46[255]; //ICC Public Key Certificate
- uint8_t tag_9F47_len;
- uint8_t tag_9F47[3]; //ICC Public Key Exponent
- uint8_t tag_9F48_len;
- uint8_t tag_9F48[255]; //ICC Public Key Remainder
- uint8_t tag_9F49_len;
- uint8_t tag_9F49[252];
- uint8_t tag_9F4A[1]; //SDA Tag list
- uint8_t tag_9F4B_len;
- uint8_t tag_9F4B[255]; //Signed Dynamic Application Data
- uint8_t tag_9F4C[8]; //ICC Dynamic Number
- uint8_t tag_9F4D[2]; //Log Entry
- uint8_t tag_9F4E[255]; //Merchant Name and Location
- //9F50-9F7F are payment system specific
- uint8_t tag_9F60[2]; //CVC3 track1
- uint8_t tag_9F61[2]; //CVC3 track2
- uint8_t tag_9F62[6]; //Track 1 Bit Map for CVC3 (PCVC3TRACK1)
- uint8_t tag_9F63[6]; //Track 1 Bit Map for UN and ATC (PUNATCTRACK1)
- uint8_t tag_9F64[1]; //Track 1 Number of ATC Digits (NATCTRACK1)
- uint8_t tag_9F65[2]; //rack 2 Bit Map for CVC3 (PCVC3TRACK2)
- uint8_t tag_9F66[4]; //Track 2 Bit Map for UN and ATC (PUNATCTRACK2), or VISA card type
- uint8_t tag_9F67[1]; //Track 2 Number of ATC Digits (NATCTRACK2)
- uint8_t tag_9F68_len;
- uint8_t tag_9F68[252]; //Mag Stripe CVM List
- uint8_t tag_9F69_len;
- uint8_t tag_9F69[255]; //Unpredictable Number Data Object List (UDOL)
- uint8_t tag_9F6A[8]; //Unpredictable Number (Numeric)
- uint8_t tag_9F6B_len;
- uint8_t tag_9F6B[19]; //track 2 data
- uint8_t tag_9F6C[2]; //Mag Stripe Application Version Number(Card)
- //template holders
- uint8_t tag_61_len;
- uint8_t tag_61[255]; //Application template
- uint8_t tag_6F_len;
- uint8_t tag_6F[255]; //6F template
- uint8_t tag_A5_len;
- uint8_t tag_A5[255]; //A5 template
- uint8_t tag_DFNAME_len;
- uint8_t tag_DFNAME[255]; //A5 template
- uint8_t tag_70_len;
- uint8_t tag_70[255]; //70 template
- uint8_t tag_77_len;
- uint8_t tag_77[255]; //77 template
- uint8_t tag_80_len;
- uint8_t tag_80[255]; //80 template
- uint8_t tag_91_len; //Issuer Authentication Data
- uint8_t tag_91[16];
- uint8_t tag_BF0C_len;
- uint8_t tag_BF0C[222]; //File Control Information (FCI) Issuer Discretionary Data
- uint8_t tag_DFName[16];
- uint8_t tag_DFName_len;
-} emvtags;
-
-#endif //__EMVCARD_H
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/epa.c b/pm3rdv4rrg/src/main/cpp/armsrc/epa.c
deleted file mode 100644
index 1fa43386..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/epa.c
+++ /dev/null
@@ -1,544 +0,0 @@
-//-----------------------------------------------------------------------------
-// Frederik Möllers - August 2012
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support the German electronic "Personalausweis" (ID card)
-// Note that the functions which do not implement USB commands do NOT initialize
-// the card (with iso14443a_select_card etc.). If You want to use these
-// functions, You need to do the setup before calling them!
-//-----------------------------------------------------------------------------
-#include "epa.h"
-
-#include "cmd.h"
-#include "fpgaloader.h"
-#include "iso14443a.h"
-#include "iso14443b.h"
-#include "string.h"
-#include "util.h"
-#include "dbprint.h"
-#include "commonutil.h"
-#include "ticks.h"
-
-// Protocol and Parameter Selection Request for ISO 14443 type A cards
-// use regular (1x) speed in both directions
-// CRC is already included
-static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6};
-
-// APDUs for communication with German Identification Card
-
-// General Authenticate (request encrypted nonce) WITHOUT the Le at the end
-static const uint8_t apdu_general_authenticate_pace_get_nonce[] = {
- 0x10, // CLA
- 0x86, // INS
- 0x00, // P1
- 0x00, // P2
- 0x02, // Lc
- 0x7C, // Type: Dynamic Authentication Data
- 0x00, // Length: 0 bytes
-};
-
-// MSE: Set AT (only CLA, INS, P1 and P2)
-static const uint8_t apdu_mse_set_at_start[] = {
- 0x00, // CLA
- 0x22, // INS
- 0xC1, // P1
- 0xA4, // P2
-};
-
-// SELECT BINARY with the ID for EF.CardAccess
-static const uint8_t apdu_select_binary_cardaccess[] = {
- 0x00, // CLA
- 0xA4, // INS
- 0x02, // P1
- 0x0C, // P2
- 0x02, // Lc
- 0x01, // ID
- 0x1C // ID
-};
-
-// READ BINARY
-static const uint8_t apdu_read_binary[] = {
- 0x00, // CLA
- 0xB0, // INS
- 0x00, // P1
- 0x00, // P2
- 0x38 // Le
-};
-
-
-// the leading bytes of a PACE OID
-static const uint8_t oid_pace_start[] = {
- 0x04, // itu-t, identified-organization
- 0x00, // etsi
- 0x7F, // reserved
- 0x00, // etsi-identified-organization
- 0x07, // bsi-de
- 0x02, // protocols
- 0x02, // smartcard
- 0x04 // id-PACE
-};
-
-// APDUs for replaying:
-// MSE: Set AT (initiate PACE)
-static uint8_t apdu_replay_mse_set_at_pace[41];
-// General Authenticate (Get Nonce)
-static uint8_t apdu_replay_general_authenticate_pace_get_nonce[8];
-// General Authenticate (Map Nonce)
-static uint8_t apdu_replay_general_authenticate_pace_map_nonce[75];
-// General Authenticate (Mutual Authenticate)
-static uint8_t apdu_replay_general_authenticate_pace_mutual_authenticate[75];
-// General Authenticate (Perform Key Agreement)
-static uint8_t apdu_replay_general_authenticate_pace_perform_key_agreement[18];
-// pointers to the APDUs (for iterations)
-static struct {
- uint8_t len;
- uint8_t *data;
-} const apdus_replay[] = {
- {sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace},
- {sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce},
- {sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce},
- {sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate},
- {sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement}
-};
-
-// lengths of the replay APDUs
-static uint8_t apdu_lengths_replay[5];
-
-// type of card (ISO 14443 A or B)
-static char iso_type = 0;
-
-//-----------------------------------------------------------------------------
-// Wrapper for sending APDUs to type A and B cards
-//-----------------------------------------------------------------------------
-int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) {
- switch (iso_type) {
- case 'a':
- return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
- break;
- case 'b':
- return iso14443b_apdu(apdu, length, response);
- break;
- default:
- return 0;
- break;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Closes the communication channel and turns off the field
-//-----------------------------------------------------------------------------
-void EPA_Finish() {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- iso_type = 0;
-}
-
-//-----------------------------------------------------------------------------
-// Parses DER encoded data, e.g. from EF.CardAccess and fills out the given
-// structs. If a pointer is 0, it is ignored.
-// The function returns 0 on success and if an error occurred, it returns the
-// offset where it occurred.
-//
-// TODO: This function can access memory outside of the given data if the DER
-// encoding is broken
-// TODO: Support skipping elements with a length > 0x7F
-// TODO: Support OIDs with a length > 7F
-// TODO: Support elements with long tags (tag is longer than 1 byte)
-// TODO: Support proprietary PACE domain parameters
-//-----------------------------------------------------------------------------
-size_t EPA_Parse_CardAccess(uint8_t *data,
- size_t length,
- pace_version_info_t *pace_info) {
- size_t index = 0;
-
- while (index <= length - 2) {
- // determine type of element
- // SET or SEQUENCE
- if (data[index] == 0x31 || data[index] == 0x30) {
- // enter the set (skip tag + length)
- index += 2;
- // check for extended length
- if ((data[index - 1] & 0x80) != 0) {
- index += (data[index - 1] & 0x7F);
- }
- }
- // OID
- else if (data[index] == 0x06) {
- // is this a PACE OID?
- if (data[index + 1] == 0x0A // length matches
- && memcmp(data + index + 2,
- oid_pace_start,
- sizeof(oid_pace_start)) == 0 // content matches
- && pace_info != NULL) {
- // first, clear the pace_info struct
- memset(pace_info, 0, sizeof(pace_version_info_t));
- memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid));
- // a PACE OID is followed by the version
- index += data[index + 1] + 2;
- if (data[index] == 02 && data[index + 1] == 01) {
- pace_info->version = data[index + 2];
- index += 3;
- } else {
- return index;
- }
- // after that there might(!) be the parameter ID
- if (data[index] == 02 && data[index + 1] == 01) {
- pace_info->parameter_id = data[index + 2];
- index += 3;
- }
- } else {
- // skip this OID
- index += 2 + data[index + 1];
- }
- }
- // if the length is 0, something is wrong
- // TODO: This needs to be extended to support long tags
- else if (data[index + 1] == 0) {
- return index;
- } else {
- // skip this part
- // TODO: This needs to be extended to support long tags
- // TODO: This needs to be extended to support unknown elements with
- // a size > 0x7F
- index += 2 + data[index + 1];
- }
- }
-
- // TODO: We should check whether we reached the end in error, but for that
- // we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO)
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-// Read the file EF.CardAccess and save it into a buffer (at most max_length bytes)
-// Returns -1 on failure or the length of the data on success
-// TODO: for the moment this sends only 1 APDU regardless of the requested length
-//-----------------------------------------------------------------------------
-int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
- // the response APDU of the card
- // since the card doesn't always care for the expected length we write it,
- // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
- uint8_t response_apdu[262];
- int rapdu_length = 0;
-
- // select the file EF.CardAccess
- rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess,
- sizeof(apdu_select_binary_cardaccess),
- response_apdu);
- if (rapdu_length < 6
- || response_apdu[rapdu_length - 4] != 0x90
- || response_apdu[rapdu_length - 3] != 0x00) {
- DbpString("Failed to select EF.CardAccess!");
- return -1;
- }
-
- // read the file
- rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary,
- sizeof(apdu_read_binary),
- response_apdu);
- if (rapdu_length <= 6
- || response_apdu[rapdu_length - 4] != 0x90
- || response_apdu[rapdu_length - 3] != 0x00) {
- Dbprintf("Failed to read EF.CardAccess!");
- return -1;
- }
-
- // copy the content into the buffer
- // length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
- size_t to_copy = rapdu_length - 6;
- to_copy = to_copy < max_length ? to_copy : max_length;
- memcpy(buffer, response_apdu + 2, to_copy);
- return to_copy;
-}
-
-//-----------------------------------------------------------------------------
-// Abort helper function for EPA_PACE_Collect_Nonce
-// sets relevant data in ack, sends the response
-//-----------------------------------------------------------------------------
-static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) {
- // power down the field
- EPA_Finish();
-
- // write the USB packet
- reply_old(CMD_ACK, step, func_return, 0, 0, 0);
-}
-
-//-----------------------------------------------------------------------------
-// Acquire one encrypted PACE nonce
-//-----------------------------------------------------------------------------
-void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
- /*
- * ack layout:
- * arg:
- * 1. element
- * step where the error occurred or 0 if no error occurred
- * 2. element
- * return code of the last executed function
- * d:
- * Encrypted nonce
- */
-
- // return value of a function
- int func_return = 0;
-
- // set up communication
- func_return = EPA_Setup();
- if (func_return != 0) {
- EPA_PACE_Collect_Nonce_Abort(1, func_return);
- return;
- }
-
- // read the CardAccess file
- // this array will hold the CardAccess file
- uint8_t card_access[256] = {0};
- int card_access_length = EPA_Read_CardAccess(card_access, 256);
- // the response has to be at least this big to hold the OID
- if (card_access_length < 18) {
- EPA_PACE_Collect_Nonce_Abort(2, card_access_length);
- return;
- }
-
- // this will hold the PACE info of the card
- pace_version_info_t pace_version_info;
- // search for the PACE OID
- func_return = EPA_Parse_CardAccess(card_access,
- card_access_length,
- &pace_version_info);
- if (func_return != 0 || pace_version_info.version == 0) {
- EPA_PACE_Collect_Nonce_Abort(3, func_return);
- return;
- }
-
- // initiate the PACE protocol
- // use the CAN for the password since that doesn't change
- func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
- // check if the command succeeded
- if (func_return != 0) {
- EPA_PACE_Collect_Nonce_Abort(4, func_return);
- return;
- }
-
- // now get the nonce
- uint8_t nonce[256] = {0};
- uint8_t requested_size = (uint8_t)c->oldarg[0];
- func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
- // check if the command succeeded
- if (func_return < 0) {
- EPA_PACE_Collect_Nonce_Abort(5, func_return);
- return;
- }
-
- // all done, return
- EPA_Finish();
-
- // save received information
- reply_old(CMD_ACK, 0, func_return, 0, nonce, func_return);
-}
-
-//-----------------------------------------------------------------------------
-// Performs the "Get Nonce" step of the PACE protocol and saves the returned
-// nonce. The caller is responsible for allocating enough memory to store the
-// nonce. Note that the returned size might be less or than or greater than the
-// requested size!
-// Returns the actual size of the nonce on success or a less-than-zero error
-// code on failure.
-//-----------------------------------------------------------------------------
-int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) {
- // build the APDU
- uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1];
- // copy the constant part
- memcpy(apdu,
- apdu_general_authenticate_pace_get_nonce,
- sizeof(apdu_general_authenticate_pace_get_nonce));
- // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
- apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
-
- // write it
- uint8_t response_apdu[262];
- int send_return = EPA_APDU(apdu,
- sizeof(apdu),
- response_apdu);
- // check if the command succeeded
- if (send_return < 6
- || response_apdu[send_return - 4] != 0x90
- || response_apdu[send_return - 3] != 0x00) {
- return -1;
- }
-
- // if there is no nonce in the RAPDU, return here
- if (send_return < 10) {
- // no error
- return 0;
- }
- // get the actual length of the nonce
- uint8_t nonce_length = response_apdu[5];
- if (nonce_length > send_return - 10) {
- nonce_length = send_return - 10;
- }
- // copy the nonce
- memcpy(nonce, response_apdu + 6, nonce_length);
-
- return nonce_length;
-}
-
-//-----------------------------------------------------------------------------
-// Initializes the PACE protocol by performing the "MSE: Set AT" step
-// Returns 0 on success or a non-zero error code on failure
-//-----------------------------------------------------------------------------
-int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) {
- // create the MSE: Set AT APDU
- uint8_t apdu[23];
- // the minimum length (will be increased as more data is added)
- size_t apdu_length = 20;
- // copy the constant part
- memcpy(apdu,
- apdu_mse_set_at_start,
- sizeof(apdu_mse_set_at_start));
- // type: OID
- apdu[5] = 0x80;
- // length of the OID
- apdu[6] = sizeof(pace_version_info.oid);
- // copy the OID
- memcpy(apdu + 7,
- pace_version_info.oid,
- sizeof(pace_version_info.oid));
- // type: password
- apdu[17] = 0x83;
- // length: 1
- apdu[18] = 1;
- // password
- apdu[19] = password;
- // if standardized domain parameters are used, copy the ID
- if (pace_version_info.parameter_id != 0) {
- apdu_length += 3;
- // type: domain parameter
- apdu[20] = 0x84;
- // length: 1
- apdu[21] = 1;
- // copy the parameter ID
- apdu[22] = pace_version_info.parameter_id;
- }
- // now set Lc to the actual length
- apdu[4] = apdu_length - 5;
- // write it
- uint8_t response_apdu[6];
- int send_return = EPA_APDU(apdu,
- apdu_length,
- response_apdu);
- // check if the command succeeded
- if (send_return != 6
- || response_apdu[send_return - 4] != 0x90
- || response_apdu[send_return - 3] != 0x00) {
- return 1;
- }
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-// Perform the PACE protocol by replaying given APDUs
-//-----------------------------------------------------------------------------
-void EPA_PACE_Replay(PacketCommandNG *c) {
- uint32_t timings[ARRAYLEN(apdu_lengths_replay)] = {0};
-
- // if an APDU has been passed, save it
- if (c->oldarg[0] != 0) {
- // make sure it's not too big
- if (c->oldarg[2] > apdus_replay[c->oldarg[0] - 1].len) {
- reply_old(CMD_ACK, 1, 0, 0, NULL, 0);
- }
- memcpy(apdus_replay[c->oldarg[0] - 1].data + c->oldarg[1],
- c->data.asBytes,
- c->oldarg[2]);
- // save/update APDU length
- if (c->oldarg[1] == 0) {
- apdu_lengths_replay[c->oldarg[0] - 1] = c->oldarg[2];
- } else {
- apdu_lengths_replay[c->oldarg[0] - 1] += c->oldarg[2];
- }
- reply_old(CMD_ACK, 0, 0, 0, NULL, 0);
- return;
- }
-
- // return value of a function
- int func_return;
-
- // set up communication
- func_return = EPA_Setup();
- if (func_return != 0) {
- EPA_Finish();
- reply_old(CMD_ACK, 2, func_return, 0, NULL, 0);
- return;
- }
-
- // increase the timeout (at least some cards really do need this!)/////////////
- // iso14a_set_timeout(0x0003FFFF);
-
- // response APDU
- uint8_t response_apdu[300] = {0};
-
- // now replay the data and measure the timings
- for (int i = 0; i < ARRAYLEN(apdu_lengths_replay); i++) {
- StartCountUS();
- func_return = EPA_APDU(apdus_replay[i].data,
- apdu_lengths_replay[i],
- response_apdu);
- timings[i] = GetCountUS();
- // every step but the last one should succeed
- if (i < ARRAYLEN(apdu_lengths_replay) - 1
- && (func_return < 6
- || response_apdu[func_return - 4] != 0x90
- || response_apdu[func_return - 3] != 0x00)) {
- EPA_Finish();
- reply_old(CMD_ACK, 3 + i, func_return, 0, timings, 20);
- return;
- }
- }
- EPA_Finish();
- reply_old(CMD_ACK, 0, 0, 0, timings, 20);
- return;
-}
-
-//-----------------------------------------------------------------------------
-// Set up a communication channel (Card Select, PPS)
-// Returns 0 on success or a non-zero error code on failure
-//-----------------------------------------------------------------------------
-int EPA_Setup() {
- uint8_t uid[10];
- iso14a_card_select_t card_a_info;
-
- // first, look for type A cards
- // power up the field
- iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
- // select the card
- int return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false);
- if (return_code == 1) {
- uint8_t pps_response[3];
- uint8_t pps_response_par[1];
- // write the PPS request
- ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
- return_code = ReaderReceive(pps_response, pps_response_par);
- if (return_code != 3 || pps_response[0] != 0xD0) {
- return return_code == 0 ? 2 : return_code;
- }
- Dbprintf("ISO 14443 Type A");
- iso_type = 'a';
- return 0;
- }
-
- // if we're here, there is no type A card, so we look for type B
- // power up the field
- iso14443b_setup();
- iso14b_card_select_t card_b_info;
- // select the card
- return_code = iso14443b_select_card(&card_b_info);
- if (return_code == 0) {
- Dbprintf("ISO 14443 Type B");
- iso_type = 'b';
- return 0;
- }
- Dbprintf("No card found.");
- return 1;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/epa.h b/pm3rdv4rrg/src/main/cpp/armsrc/epa.h
deleted file mode 100644
index 66a95c05..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/epa.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//-----------------------------------------------------------------------------
-// Frederik Möllers - August 2012
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support the German eletronic "Personalausweis" (ID card)
-//-----------------------------------------------------------------------------
-
-#ifndef __EPA_H
-#define __EPA_H
-
-#include "common.h"
-#include "pm3_cmd.h"
-
-// this struct is used by EPA_Parse_CardAccess and contains info about the
-// PACE protocol supported by the chip
-typedef struct {
- uint8_t oid[10];
- uint8_t version;
- uint8_t parameter_id;
-} pace_version_info_t;
-
-// general functions
-void EPA_Finish();
-size_t EPA_Parse_CardAccess(uint8_t *data,
- size_t length,
- pace_version_info_t *pace_info);
-int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length);
-int EPA_Setup();
-
-// PACE related functions
-int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password);
-int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce);
-
-void EPA_PACE_Collect_Nonce(PacketCommandNG *c);
-void EPA_PACE_Replay(PacketCommandNG *c);
-
-#endif /* __EPA_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/felica.c b/pm3rdv4rrg/src/main/cpp/armsrc/felica.c
deleted file mode 100644
index b1e0253a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/felica.c
+++ /dev/null
@@ -1,816 +0,0 @@
-#include "felica.h"
-#include "proxmark3_arm.h"
-#include "BigBuf.h"
-#include "util.h"
-#include "protocols.h"
-#include "crc16.h"
-#include "fpgaloader.h"
-#include "string.h"
-#include "commonutil.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "mifare.h"
-
-// FeliCa timings
-// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
-#ifndef FELICA_REQUEST_GUARD_TIME
-# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) // 426
-#endif
-// FRAME DELAY TIME 2672 carrier cycles
-#ifndef FELICA_FRAME_DELAY_TIME
-# define FELICA_FRAME_DELAY_TIME (2672/16 + 1) // 168
-#endif
-#ifndef DELAY_AIR2ARM_AS_READER
-#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) // 91
-#endif
-#ifndef DELAY_ARM2AIR_AS_READER
-#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) // 209
-#endif
-#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
-
-static uint32_t felica_timeout;
-static uint32_t felica_nexttransfertime;
-static uint32_t felica_lasttime_prox2air_start;
-
-static void iso18092_setup(uint8_t fpga_minor_mode);
-static uint8_t felica_select_card(felica_card_select_t *card);
-static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed);
-bool WaitForFelicaReply(uint16_t maxbytes);
-
-void iso18092_set_timeout(uint32_t timeout) {
- felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) + 2;
-}
-
-uint32_t iso18092_get_timeout(void) {
- return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2;
-}
-
-#ifndef FELICA_MAX_FRAME_SIZE
-#define FELICA_MAX_FRAME_SIZE 260
-#endif
-
-//structure to hold outgoing NFC frame
-static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE + 4];
-
-//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
-static struct {
- enum {
- STATE_UNSYNCD,
- STATE_TRYING_SYNC,
- STATE_GET_LENGTH,
- STATE_GET_DATA,
- STATE_GET_CRC,
- STATE_FULL
- } state;
-
- uint16_t shiftReg; //for synchronization and offset calculation
- int posCnt;
- bool crc_ok;
- int rem_len;
- uint16_t len;
- uint8_t byte_offset;
- uint8_t *framebytes;
-//should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc
-// 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
-} FelicaFrame;
-
-//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in
-//bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in
-#ifndef SYNC_16BIT
-# define SYNC_16BIT 0xB24D
-#endif
-
-static void FelicaFrameReset() {
- FelicaFrame.state = STATE_UNSYNCD;
- FelicaFrame.posCnt = 0;
- FelicaFrame.crc_ok = false;
- FelicaFrame.byte_offset = 0;
-}
-static void FelicaFrameinit(uint8_t *data) {
- FelicaFrame.framebytes = data;
- FelicaFrameReset();
-}
-
-//shift byte into frame, reversing it at the same time
-static void shiftInByte(uint8_t bt) {
- uint8_t j;
- for (j = 0; j < FelicaFrame.byte_offset; j++) {
- FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
- bt >>= 1;
- }
- FelicaFrame.posCnt++;
- FelicaFrame.rem_len--;
- for (j = FelicaFrame.byte_offset; j < 8; j++) {
- FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
- bt >>= 1;
- }
-}
-
-static void Process18092Byte(uint8_t bt) {
- switch (FelicaFrame.state) {
- case STATE_UNSYNCD: {
- //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case
- if (bt > 0) {
- FelicaFrame.shiftReg = reflect8(bt);
- FelicaFrame.state = STATE_TRYING_SYNC;
- }
- break;
- }
- case STATE_TRYING_SYNC: {
- if (bt == 0) {
- //desync
- FelicaFrame.shiftReg = bt;
- FelicaFrame.state = STATE_UNSYNCD;
- } else {
- for (uint8_t i = 0; i < 8; i++) {
-
- if (FelicaFrame.shiftReg == SYNC_16BIT) {
- //SYNC done!
- FelicaFrame.state = STATE_GET_LENGTH;
- FelicaFrame.framebytes[0] = 0xb2;
- FelicaFrame.framebytes[1] = 0x4d;
- FelicaFrame.byte_offset = i;
- //shift in remaining byte, slowly...
- for (uint8_t j = i; j < 8; j++) {
- FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1);
- bt >>= 1;
- }
-
- FelicaFrame.posCnt = 2;
- if (i == 0)
- break;
- }
- FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1);
- bt >>= 1;
- }
-
- //that byte was last byte of sync
- if (FelicaFrame.shiftReg == SYNC_16BIT) {
- //Force SYNC on next byte
- FelicaFrame.state = STATE_GET_LENGTH;
- FelicaFrame.framebytes[0] = 0xb2;
- FelicaFrame.framebytes[1] = 0x4d;
- FelicaFrame.byte_offset = 0;
- FelicaFrame.posCnt = 1;
- }
- }
- break;
- }
- case STATE_GET_LENGTH: {
- shiftInByte(bt);
- FelicaFrame.rem_len = FelicaFrame.framebytes[2] - 1;
- FelicaFrame.len = FelicaFrame.framebytes[2] + 4; //with crc and sync
- FelicaFrame.state = STATE_GET_DATA;
- break;
- }
- case STATE_GET_DATA: {
- shiftInByte(bt);
- if (FelicaFrame.rem_len <= 0) {
- FelicaFrame.state = STATE_GET_CRC;
- FelicaFrame.rem_len = 2;
- }
- break;
- }
- case STATE_GET_CRC: {
- shiftInByte(bt);
- if (FelicaFrame.rem_len <= 0) {
- FelicaFrame.rem_len = 0;
- // skip sync 2bytes. IF ok, residue should be 0x0000
- FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
- FelicaFrame.state = STATE_FULL;
- }
- break;
- }
- case STATE_FULL: //ignore byte. Don't forget to clear frame to receive next one...
- default:
- break;
- }
-}
-
-/* Perform FeliCa polling card
- * Currently does NOT do any collision handling.
- * It expects 0-1 cards in the device's range.
- * return 0 if selection was successful
- */
-static uint8_t felica_select_card(felica_card_select_t *card) {
-
- // POLL command
- // 0xB2 0x4B = sync code
- // 0x06 = len
- // 0x00 = rfu
- // 0xff = system code service
- // 0xff = system code service
- // 0x00 = request code
- // b7 = automatic switching of data rate
- // b6-b2 = reserved
- // b1 = fc/32 (414kbps)
- // b0 = fc/64 (212kbps)
- // 0x00 = timeslot
- // 0x09 0x21 = crc
- static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
- int len = 20;
-
- // We try 20 times, or if answer was received.
- do {
- // end-of-reception response packet data, wait approx. 501μs
- // end-of-transmission command packet data, wait approx. 197μs
- // polling card
- TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0);
-
- // polling card, break if success
- if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK)
- break;
-
- WDT_HIT();
-
- } while (--len);
-
- // timed-out
- if (len == 0) {
- if (DBGLEVEL >= DBG_DEBUG)
- Dbprintf("Error: Time out card selection!");
- return 1;
- }
-
- // wrong answer
- if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) {
- if (DBGLEVEL >= DBG_DEBUG)
- Dbprintf("Error: Wrong answer selecting card!");
- return 2;
- }
-
- // VALIDATE CRC residue is 0, hence if crc is a value it failed.
- if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2)) {
- if (DBGLEVEL >= DBG_DEBUG) {
- Dbprintf("Error: CRC check failed!");
- Dbprintf("CRC check was done on Frame: ");
- Dbhexdump(FelicaFrame.len - 2, FelicaFrame.framebytes + 2, 0);
- }
- return 3;
- }
-
- if (DBGLEVEL >= DBG_DEBUG)
- Dbprintf("Card selection successful!");
- // copy UID
- // idm 8
- if (card) {
- memcpy(card->IDm, FelicaFrame.framebytes + 4, 8);
- memcpy(card->PMm, FelicaFrame.framebytes + 4 + 8, 8);
- //memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2);
- memcpy(card->code, card->IDm, 2);
- memcpy(card->uid, card->IDm + 2, 6);
- memcpy(card->iccode, card->PMm, 2);
- memcpy(card->mrt, card->PMm + 2, 6);
- if (DBGLEVEL >= DBG_DEBUG) {
- Dbprintf("Received Frame: ");
- Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
- }
- }
- // more status bytes?
- return 0;
-}
-
-// poll-0: 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21,
-// resp: 0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80,0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f,
-// poll-1 (reply with available system codes - NFC Tag3 specs, IIRC): 0xb2,0x4d,0x06,0x00,0xff,0xff,0x01,0x00,0x3a,0x10
-// resp: 0xb2,0x4d,0x14,0x01, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0x0c,0xe2,
-// page-req: 0xb2,0x4d,0x10,0x06, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x01, 0x0b,0x00, 0x01, 0x80,0x00, 0x2e,0xb3,
-// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num)
-// page-resp: 0xb2,0x4d,0x1d,0x07, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00, 0x00, 0x01, 0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23, 0xcb,0x6e,
-
-// builds a readblock frame for felica lite(s). Using SERVICE: SERVICE_FELICA_LITE_READONLY
-// Felica standard has a different file system, AFAIK,
-// 8-byte IDm, number of blocks, blocks numbers
-// number of blocks limited to 4 for FelicaLite(S)
-static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
- if (blocknum > 4 || blocknum <= 0)
- Dbprintf("Invalid number of blocks, %d != 4", blocknum);
-
- uint8_t c = 0, i = 0;
-
- // Sync bytes
- frameSpace[c++] = 0xb2;
- frameSpace[c++] = 0x4d;
-
- c++; //set length later
-
- frameSpace[c++] = FELICA_RDBLK_REQ; //command number
-
- //card IDm, from poll
- frameSpace[c++] = idm[0];
- frameSpace[c++] = idm[1];
- frameSpace[c++] = idm[2];
- frameSpace[c++] = idm[3];
- frameSpace[c++] = idm[4];
- frameSpace[c++] = idm[5];
- frameSpace[c++] = idm[6];
- frameSpace[c++] = idm[7];
-
- //number of services
- frameSpace[c++] = 0x01;
-
- //service code
- frameSpace[c++] = (SERVICE_FELICA_LITE_READONLY >> 8);
- frameSpace[c++] = SERVICE_FELICA_LITE_READONLY & 0xFF;
-
- //number of blocks
- frameSpace[c++] = blocknum;
-
- for (i = 0; i < blocknum; i++) {
-
- //3-byte block
- if (blocks[i] >= 256) {
- frameSpace[c++] = 0x00;
- frameSpace[c++] = (blocks[i] >> 8); //block number, little endian....
- frameSpace[c++] = (blocks[i] & 0xff);
- } else {
- frameSpace[c++] = 0x80;
- frameSpace[c++] = blocks[i];
- }
- }
-
- //set length
- frameSpace[2] = c - 2;
- //Add CRC
- AddCrc(frameSpace + 2, c - 2);
-}
-
-static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
- uint8_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
- if (power)
- flags |= FPGA_HF_ISO18092_FLAG_READER;
- if (highspeed)
- flags |= FPGA_HF_ISO18092_FLAG_424K;
-
- FpgaWriteConfWord(flags);
-
- uint32_t curr_transfer_time = ((MAX(felica_nexttransfertime, GetCountSspClk()) & 0xfffffff8) + 8);
-
- while (GetCountSspClk() < curr_transfer_time) {};
-
- felica_lasttime_prox2air_start = curr_transfer_time;
-
- // preamble
- // sending 0x00 0x00 0x00 0x00 0x00 0x00
- uint16_t c = 0;
- while (c < 6) {
- // keep tx buffer in a defined state anyway.
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00;
- c++;
- }
- }
- // sending data with sync bytes
- c = 0;
- if (DBGLEVEL >= DBG_DEBUG) {
- Dbprintf("Sending frame:");
- Dbhexdump(len, frame, 0);
- }
-
- while (c < len) {
- // Put byte into tx holding register as soon as it is ready
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = frame[c++];
- }
- }
-
- /**/
- while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
- AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay
-
- while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
- AT91C_BASE_SSC->SSC_THR = 0x00; //spin
- /**/
-
- // log
- LogTrace(
- frame,
- len,
- (felica_lasttime_prox2air_start << 4) + DELAY_ARM2AIR_AS_READER,
- ((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start) << 4) + DELAY_ARM2AIR_AS_READER,
- NULL,
- true
- );
-
- felica_nexttransfertime = MAX(felica_nexttransfertime, felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME);
-}
-
-// Wait for tag reply
-// stop when button is pressed
-// or return TRUE when command is captured
-bool WaitForFelicaReply(uint16_t maxbytes) {
- if (DBGLEVEL >= DBG_DEBUG)
- Dbprintf("WaitForFelicaReply Start");
- uint32_t c = 0;
- // power, no modulation
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
- FelicaFrameReset();
-
- // clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint32_t timeout = iso18092_get_timeout();
-
- for (;;) {
- WDT_HIT();
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
- Process18092Byte(b);
- if (FelicaFrame.state == STATE_FULL) {
- felica_nexttransfertime = MAX(felica_nexttransfertime,
- (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME);
-
- LogTrace(
- FelicaFrame.framebytes,
- FelicaFrame.len,
- ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
- ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
- NULL,
- false
- );
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("All bytes received! STATE_FULL");
- return true;
- } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) {
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Timeout! STATE_UNSYNCD");
- return false;
- }
- }
- }
-}
-
-// Set up FeliCa communication (similar to iso14443a_setup)
-// field is setup for "Sending as Reader"
-static void iso18092_setup(uint8_t fpga_minor_mode) {
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Start iso18092_setup");
-
- LEDsoff();
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- // allocate command receive buffer
- BigBuf_free();
- BigBuf_Clear_ext(false);
-
- // Initialize Demod and Uart structs
- // DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
- FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE));
-
- felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER;
- iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card
-
- init_table(CRC_FELICA);
-
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Set up the synchronous serial port
- FpgaSetupSsc();
-
- // LSB transfer. Remember to set it back to MSB with
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
-
- // Signal field is on with the appropriate LED
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | fpga_minor_mode);
-
- //20.4 ms generate field, start sending polling command afterwars.
- SpinDelay(100);
-
- // Start the timer
- StartCountSspClk();
-
- LED_D_ON();
-}
-
-void felica_reset_frame_mode() {
- switch_off();
- //Resetting Frame mode (First set in fpgaloader.c)
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
-}
-
-
-//-----------------------------------------------------------------------------
-// RAW FeliCa commands. Send out commands and store answers.
-//-----------------------------------------------------------------------------
-// arg0 FeliCa flags
-// arg1 len of commandbytes
-// d.asBytes command bytes to send
-void felica_sendraw(PacketCommandNG *c) {
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Enter");
-
- felica_command_t param = c->oldarg[0];
- size_t len = c->oldarg[1] & 0xffff;
- uint8_t *cmd = c->data.asBytes;
- uint32_t arg0;
-
- felica_card_select_t card;
-
- if ((param & FELICA_CONNECT))
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Clear trace");
- clear_trace();
-
- set_tracing(true);
- iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
-
- if ((param & FELICA_CONNECT)) {
- // notify client selecting status.
- // if failed selecting, turn off antenna and quite.
- if (!(param & FELICA_NO_SELECT)) {
- arg0 = felica_select_card(&card);
- reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
- if (arg0 > 0) {
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Failed selecting card! ");
- felica_reset_frame_mode();
- return;
- }
- }
- } else {
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("No card selection");
- }
-
- if ((param & FELICA_RAW)) {
-
- // 2 sync, 1 len, 2crc == 5
- uint8_t *buf = BigBuf_malloc(len + 5);
- // add sync bits
- buf[0] = 0xb2;
- buf[1] = 0x4d;
- buf[2] = len;
-
- // copy command
- memcpy(buf + 2, cmd, len);
-
- if ((param & FELICA_APPEND_CRC)) {
- // Don't append crc on empty bytearray...
- if (len > 0) {
- AddCrc(buf, len);
- }
- }
- if (DBGLEVEL >= DBG_DEBUG) {
- Dbprintf("Transmit Frame (no CRC shown):");
- Dbhexdump(len, buf, 0);
- Dbprintf("Buffer Length: %i", buf[2] + 4);
- };
- TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
- arg0 = WaitForFelicaReply(1024);
- if (DBGLEVEL >= DBG_DEBUG) {
- Dbprintf("Received Frame Code: %d", arg0);
- Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
- };
-
- uint32_t result = reply_mix(CMD_ACK, FelicaFrame.len, arg0, 0, FelicaFrame.framebytes, FelicaFrame.len);
- if (result) {
- Dbprintf("Reply to Client Error Code: %i", result);
- }
- }
- if ((param & FELICA_NO_DISCONNECT)) {
- Dbprintf("Disconnect");
- }
- if (DBGLEVEL >= DBG_DEBUG)
- Dbprintf("FeliCa_sendraw Exit");
- felica_reset_frame_mode();
- return;
-}
-
-void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
- int remFrames = (samplesToSkip) ? samplesToSkip : 0;
- Dbprintf("Sniff Felica: Getting first %d frames, Skipping after %d triggers.\n", samplesToSkip, triggersToSkip);
- clear_trace();
- set_tracing(true);
- iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
- LED_D_ON();
- uint16_t numbts = 0;
- int trigger_cnt = 0;
- uint32_t timeout = iso18092_get_timeout();
- bool isReaderFrame = true;
- while (!BUTTON_PRESS()) {
- WDT_HIT();
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
- Process18092Byte(dist);
- if ((dist >= 178) && (++trigger_cnt > triggersToSkip)) {
- Dbprintf("triggersToSkip kicked %d", dist);
- break;
- }
- if (FelicaFrame.state == STATE_FULL) {
- if ((FelicaFrame.framebytes[3] % 2) == 0) {
- isReaderFrame = true; // All Reader Frames are even and all Tag frames are odd
- } else {
- isReaderFrame = false;
- }
- remFrames--;
- if (remFrames <= 0) {
- Dbprintf("Stop Sniffing - samplesToSkip reached!");
- break;
- }
- LogTrace(FelicaFrame.framebytes,
- FelicaFrame.len,
- ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
- ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
- NULL,
- isReaderFrame
- );
- numbts += FelicaFrame.len;
- FelicaFrameReset();
- }
- }
- }
- switch_off();
- //reset framing
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
- set_tracelen(numbts);
- set_tracelen(BigBuf_max_traceLen());
-
- Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
- reply_old(CMD_ACK, 1, numbts, 0, 0, 0);
- LED_D_OFF();
-}
-
-#define R_POLL0_LEN 0x16
-#define R_POLL1_LEN 0x18
-#define R_READBLK_LEN 0x21
-//simulate NFC Tag3 card - for now only poll response works
-// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
-void felica_sim_lite(uint64_t uid) {
-
- int i, curlen = 0;
- uint8_t *curresp = 0;
-
- uint8_t ndef[8];
- num_to_bytes(uid, 8, ndef);
-
- //prepare our 3 responses...
- uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
- uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2, 0x4d, 0x14, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x88, 0xb4, 0xb3, 0x7f};
- uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2, 0x4d, 0x1d, FELICA_RDBLK_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x23, 0xcb, 0x6e};
-
- //NFC tag 3/ ISo technically. Many overlapping standards
- DbpString("Felica Lite-S sim start");
- Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x",
- ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7]
- );
-
- //fill in blanks
- for (i = 0; i < 8; i++) {
- resp_poll0[i + 4] = ndef[i];
- resp_poll1[i + 4] = ndef[i];
- resp_readblk[i + 4] = ndef[i];
- }
-
- //calculate and set CRC
- AddCrc(resp_poll0, resp_poll0[2]);
- AddCrc(resp_poll1, resp_poll1[2]);
- AddCrc(resp_readblk, resp_readblk[2]);
-
- iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
-
- bool listenmode = true;
- //uint32_t frtm = GetCountSspClk();
- for (;;) {
- if (BUTTON_PRESS()) break;
- WDT_HIT();
-
- if (listenmode) {
- //waiting for request...
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
-
- uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
- //frtm = GetCountSspClk();
- Process18092Byte(dist);
-
- if (FelicaFrame.state == STATE_FULL) {
-
- if (FelicaFrame.crc_ok) {
-
- if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) {
-
- //polling... there are two types of polling we answer to
- if (FelicaFrame.framebytes[6] == 0) {
- curresp = resp_poll0;
- curlen = R_POLL0_LEN;
- listenmode = false;
- }
- if (FelicaFrame.framebytes[6] == 1) {
- curresp = resp_poll1;
- curlen = R_POLL1_LEN;
- listenmode = true;
- }
- }
-
- if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) {
- //we should rebuild it depending on page size, but...
- //Let's see first
- curresp = resp_readblk;
- curlen = R_READBLK_LEN;
- listenmode = false;
- }
- //clear frame
- FelicaFrameReset();
- } else {
- //frame invalid, clear it out to allow for the next one
- FelicaFrameReset();
- }
- }
- }
- }
- if (!listenmode) {
- //trying to answer... here to start answering immediately.
- //this one is a bit finicky. Seems that being a bit late is better than earlier
- //TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0);
- TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0);
-
- //switch back
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
-
- FelicaFrameReset();
- listenmode = true;
- curlen = 0;
- curresp = NULL;
- }
- }
-
- switch_off();
-
- //reset framing
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
-
- DbpString("Felica Lite-S sim end");
-}
-
-#define RES_SVC_LEN 11 + 3
-
-void felica_dump_lite_s() {
- uint8_t ndef[8];
- uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
- uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
-
- // setup device.
- iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
-
- uint8_t blknum;
- bool isOK = false;
- uint16_t cnt = 0, cntfails = 0;
- uint8_t *dest = BigBuf_get_addr();
-
- while (!BUTTON_PRESS() && !data_available()) {
- WDT_HIT();
- // polling?
- //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0);
- TransmitFor18092_AsReader(poll, 10, NULL, 1, 0);
-
- if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) {
- // copy 8bytes to ndef.
- memcpy(ndef, FelicaFrame.framebytes + 4, 8);
- // for (c=0; c < 8; c++)
- // ndef[c] = FelicaFrame.framebytes[c+4];
-
- for (blknum = 0; blknum < ARRAYLEN(liteblks);) {
- // block to read.
- BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
-
- //TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0);
-
-
-
- TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0);
- // read block
- if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) {
-
- dest[cnt++] = liteblks[blknum];
-
- uint8_t *fb = FelicaFrame.framebytes;
- dest[cnt++] = fb[12];
- dest[cnt++] = fb[13];
-
- //memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16);
- //cnt += 16;
- for (uint8_t j = 0; j < 16; j++)
- dest[cnt++] = fb[15 + j];
-
- blknum++;
- cntfails = 0;
-
- // // print raw log.
- // Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt);
- Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes + 15, 0);
- } else {
- cntfails++;
- if (cntfails > 12) {
- blknum++;
- cntfails = 0;
- }
- }
- }
-
- isOK = true;
- break;
- }
- }
- switch_off();
-
- //Resetting Frame mode (First set in fpgaloader.c)
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
-
- //setting tracelen - important! it was set by buffer overflow before
- set_tracelen(cnt);
- reply_old(CMD_ACK, isOK, cnt, 0, 0, 0);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/felica.h b/pm3rdv4rrg/src/main/cpp/armsrc/felica.h
deleted file mode 100644
index ef34dc10..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/felica.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __FELICA_H
-#define __FELICA_H
-
-#include "common.h"
-#include "cmd.h"
-
-void felica_sendraw(PacketCommandNG *c);
-void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
-void felica_sim_lite(uint64_t uid);
-void felica_dump_lite_s();
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/flashmem.c b/pm3rdv4rrg/src/main/cpp/armsrc/flashmem.c
deleted file mode 100644
index 60c45845..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/flashmem.c
+++ /dev/null
@@ -1,598 +0,0 @@
-#include "flashmem.h"
-#include "pmflash.h"
-
-#include "proxmark3_arm.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "string.h"
-
-/* here: use NCPS2 @ PA10: */
-#define SPI_CSR_NUM 2
-#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
-/// Calculates the value of the CSR SCBR field given the baudrate and MCK.
-#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
-/// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
-#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
-/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
-#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
-
-
-uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
-
-void FlashmemSetSpiBaudrate(uint32_t baudrate) {
- FLASHMEM_SPIBAUDRATE = baudrate;
- Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
-}
-
-// initialize
-bool FlashInit() {
- FlashSetup(FLASHMEM_SPIBAUDRATE);
-
- StartTicks();
-
- if (Flash_CheckBusy(BUSY_TIMEOUT)) {
- StopTicks();
- return false;
- }
-
- return true;
-}
-
-void FlashSetup(uint32_t baudrate) {
- //WDT_DISABLE
- AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
-
- // PA10 -> SPI_NCS2 chip select (FLASHMEM)
- // PA11 -> SPI_NCS0 chip select (FPGA)
- // PA12 -> SPI_MISO Master-In Slave-Out
- // PA13 -> SPI_MOSI Master-Out Slave-In
- // PA14 -> SPI_SPCK Serial Clock
-
- // Disable PIO control of the following pins, allows use by the SPI peripheral
- AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
-
- // Pull-up Enable
- AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
-
- // Peripheral A
- AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK);
-
- // Peripheral B
- AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2;
-
- //enable the SPI Peripheral clock
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
-
-
- //reset spi needs double SWRST, see atmel's errata on this case
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
-
- // Enable SPI
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
-
- // NPCS2 Mode 0
- AT91C_BASE_SPI->SPI_MR =
- (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
- // If DLYBCS is less than or equal to six, six MCK periods
- // will be inserted by default.
- SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
- (0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
- (1 << 4) | // Disable ModeFault Protection
- (0 << 3) | // makes spi operate at MCK (1 is MCK/2)
- (0 << 2) | // Chip selects connected directly to peripheral
- AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
- AT91C_SPI_MSTR; // Master Mode
-
- uint8_t csaat = 1;
- uint32_t dlybct = 0;
- uint8_t ncpha = 1;
- uint8_t cpol = 0;
- if (baudrate > FLASH_MINFAST) {
- baudrate = FLASH_FASTBAUD;
- //csaat = 0;
- dlybct = 1500;
- ncpha = 0;
- cpol = 0;
- }
-
- AT91C_BASE_SPI->SPI_CSR[2] =
- SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods)
- SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock
- SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection
- AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
- //AT91C_SPI_CSAAT | // Chip Select inactive after transfer
- // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
- // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
- // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
- // transferred in the shifter. This can imply for example, that the second data is sent twice.
- // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
- (csaat << 3) |
- /* Spi modes:
- Mode CPOL CPHA NCPHA
- 0 0 0 1 clock normally low read on rising edge
- 1 0 1 0 clock normally low read on falling edge
- 2 1 0 1 clock normally high read on falling edge
- 3 1 1 0 clock normally high read on rising edge
- However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
- master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
- (MISO) on the opposite edge where data clocks out (MOSI) but the same
- edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
- shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
- that the data changes sometime after the rising edge (about 2 ns). To
- be consistent with normal SPI operation, it is probably safe to say
- that the data changes on the falling edge and should be sampled on the
- rising edge. Therefore, it appears that NCPHA should be treated the
- same as CPHA. Thus:
- Mode CPOL CPHA NCPHA
- 0 0 0 0 clock normally low read on rising edge
- 1 0 1 1 clock normally low read on falling edge
- 2 1 0 0 clock normally high read on falling edge
- 3 1 1 1 clock normally high read on rising edge
- Update: for 24MHz, writing is more stable with ncpha=1, else bitflips occur.
- */
- (ncpha << 1) | // Clock Phase data captured on leading edge, changes on following edge
- (cpol << 0); // Clock Polarity inactive state is logic 0
-
- // read first, empty buffer
- if (AT91C_BASE_SPI->SPI_RDR == 0) {};
-}
-
-void FlashStop(void) {
- //Bof
- //* Reset all the Chip Select register
- AT91C_BASE_SPI->SPI_CSR[0] = 0;
- AT91C_BASE_SPI->SPI_CSR[1] = 0;
- AT91C_BASE_SPI->SPI_CSR[2] = 0;
- AT91C_BASE_SPI->SPI_CSR[3] = 0;
-
- // Reset the SPI mode
- AT91C_BASE_SPI->SPI_MR = 0;
-
- // Disable all interrupts
- AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
-
- // SPI disable
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
-
- if (DBGLEVEL > 3) Dbprintf("FlashStop");
-
- StopTicks();
-}
-
-// write one byte over SPI
-uint16_t FlashSendByte(uint32_t data) {
-
- // wait until SPI is ready for transfer
- //if you are checking for incoming data returned then the TXEMPTY flag is redundant
- //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
-
- // write the data
- AT91C_BASE_SPI->SPI_TDR = data;
-
- //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
-
- // wait recive transfer is complete
- while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {};
-
- // reading incoming data
- return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
-}
-
-// write last byte over SPI
-uint16_t FlashSendLastByte(uint32_t data) {
- return FlashSendByte(data | AT91C_SPI_LASTXFER);
-}
-
-// read state register 1
-uint8_t Flash_ReadStat1(void) {
- FlashSendByte(READSTAT1);
- return FlashSendLastByte(0xFF);
-}
-
-bool Flash_CheckBusy(uint32_t timeout) {
- WaitUS(WINBOND_WRITE_DELAY);
- StartCountUS();
- uint32_t _time = GetCountUS();
-
- if (DBGLEVEL > 3) Dbprintf("Checkbusy in...");
-
- do {
- if (!(Flash_ReadStat1() & BUSY)) {
- return false;
- }
- } while ((GetCountUS() - _time) < timeout);
-
- if (timeout <= (GetCountUS() - _time)) {
- return true;
- }
-
- return false;
-}
-
-// read ID out
-uint8_t Flash_ReadID(void) {
-
- if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
-
- // Manufacture ID / devices ID
- FlashSendByte(ID);
- FlashSendByte(0x00);
- FlashSendByte(0x00);
- FlashSendByte(0x00);
-
- uint8_t man_id = FlashSendByte(0xFF);
- uint8_t dev_id = FlashSendLastByte(0xFF);
-
- if (DBGLEVEL > 3) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
-
- if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID))
- return dev_id;
-
- return 0;
-}
-
-// read unique id for chip.
-void Flash_UniqueID(uint8_t *uid) {
-
- if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
-
- // reading unique serial number
- FlashSendByte(UNIQUE_ID);
- FlashSendByte(0xFF);
- FlashSendByte(0xFF);
- FlashSendByte(0xFF);
- FlashSendByte(0xFF);
-
- uid[7] = FlashSendByte(0xFF);
- uid[6] = FlashSendByte(0xFF);
- uid[5] = FlashSendByte(0xFF);
- uid[4] = FlashSendByte(0xFF);
- uid[3] = FlashSendByte(0xFF);
- uid[2] = FlashSendByte(0xFF);
- uid[1] = FlashSendByte(0xFF);
- uid[0] = FlashSendLastByte(0xFF);
-}
-
-uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
-
- if (!FlashInit()) return 0;
-
- // length should never be zero
- if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
-
- uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
-
- FlashSendByte(cmd);
- Flash_TransferAdresse(address);
-
- if (FASTFLASH) {
- FlashSendByte(DUMMYBYTE);
- }
-
- uint16_t i = 0;
- for (; i < (len - 1); i++)
- out[i] = FlashSendByte(0xFF);
-
- out[i] = FlashSendLastByte(0xFF);
- FlashStop();
- return len;
-}
-
-void Flash_TransferAdresse(uint32_t address) {
- FlashSendByte((address >> 16) & 0xFF);
- FlashSendByte((address >> 8) & 0xFF);
- FlashSendByte((address >> 0) & 0xFF);
-}
-
-/* This ensure we can ReadData without having to cycle through initialization everytime */
-uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
-
- // length should never be zero
- if (!len) return 0;
-
- uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
-
- FlashSendByte(cmd);
- Flash_TransferAdresse(address);
-
- if (FASTFLASH) {
- FlashSendByte(DUMMYBYTE);
- }
-
- uint16_t i = 0;
- for (; i < (len - 1); i++)
- out[i] = FlashSendByte(0xFF);
-
- out[i] = FlashSendLastByte(0xFF);
- return len;
-}
-
-
-////////////////////////////////////////
-// Write data can only program one page. A page has 256 bytes.
-// if len > 256, it might wrap around and overwrite pos 0.
-uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
-
- // length should never be zero
- if (!len)
- return 0;
-
- // Max 256 bytes write
- if (((address & 0xFF) + len) > 256) {
- Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
- return 0;
- }
-
- // out-of-range
- if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
- Dbprintf("Flash_WriteData, block out-of-range");
- return 0;
- }
-
- if (!FlashInit()) {
- if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
- return 0;
- }
-
- Flash_CheckBusy(BUSY_TIMEOUT);
-
- Flash_WriteEnable();
-
- FlashSendByte(PAGEPROG);
- FlashSendByte((address >> 16) & 0xFF);
- FlashSendByte((address >> 8) & 0xFF);
- FlashSendByte((address >> 0) & 0xFF);
-
- uint16_t i = 0;
- for (; i < (len - 1); i++)
- FlashSendByte(in[i]);
-
- FlashSendLastByte(in[i]);
-
- FlashStop();
- return len;
-}
-
-
-// length should never be zero
-// Max 256 bytes write
-// out-of-range
-uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
-
- if (!len)
- return 0;
-
- if (((address & 0xFF) + len) > 256) {
- Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
- return 0;
- }
-
- if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
- Dbprintf("Flash_WriteDataCont, block out-of-range");
- return 0;
- }
-
- FlashSendByte(PAGEPROG);
- FlashSendByte((address >> 16) & 0xFF);
- FlashSendByte((address >> 8) & 0xFF);
- FlashSendByte((address >> 0) & 0xFF);
-
- uint16_t i = 0;
- for (; i < (len - 1); i++)
- FlashSendByte(in[i]);
-
- FlashSendLastByte(in[i]);
- return len;
-}
-
-// assumes valid start 256 based 00 address
-//
-uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
-
- bool isok;
- uint16_t res, bytes_sent = 0, bytes_remaining = len;
- uint8_t buf[FLASH_MEM_BLOCK_SIZE];
- while (bytes_remaining > 0) {
-
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
-
- uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
-
- memcpy(buf, in + bytes_sent, bytes_in_packet);
-
- res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
-
- bytes_remaining -= bytes_in_packet;
- bytes_sent += bytes_in_packet;
-
- isok = (res == bytes_in_packet);
-
- if (!isok)
- goto out;
- }
-
-out:
- FlashStop();
- return len;
-}
-
-
-bool Flash_WipeMemoryPage(uint8_t page) {
- if (!FlashInit()) {
- if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
- return false;
- }
- Flash_ReadStat1();
-
- // Each block is 64Kb. One block erase takes 1s ( 1000ms )
- Flash_WriteEnable();
- Flash_Erase64k(page);
- Flash_CheckBusy(BUSY_TIMEOUT);
-
- FlashStop();
- return true;
-}
-// Wipes flash memory completely, fills with 0xFF
-bool Flash_WipeMemory() {
- if (!FlashInit()) {
- if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
- return false;
- }
- Flash_ReadStat1();
-
- // Each block is 64Kb. Four blocks
- // one block erase takes 1s ( 1000ms )
- Flash_WriteEnable();
- Flash_Erase64k(0);
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase64k(1);
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase64k(2);
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase64k(3);
- Flash_CheckBusy(BUSY_TIMEOUT);
-
- FlashStop();
- return true;
-}
-
-// enable the flash write
-void Flash_WriteEnable() {
- FlashSendLastByte(WRITEENABLE);
- if (DBGLEVEL > 3) Dbprintf("Flash Write enabled");
-}
-
-// erase 4K at one time
-// execution time: 0.8ms / 800us
-bool Flash_Erase4k(uint8_t block, uint8_t sector) {
-
- if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
-
- FlashSendByte(SECTORERASE);
- FlashSendByte(block);
- FlashSendByte(sector << 4);
- FlashSendLastByte(00);
- return true;
-}
-
-/*
-// erase 32K at one time
-// execution time: 0,3s / 300ms
-bool Flash_Erase32k(uint32_t address) {
- if (address & (32*1024 - 1)) {
- if ( DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
- return false;
- }
- FlashSendByte(BLOCK32ERASE);
- FlashSendByte((address >> 16) & 0xFF);
- FlashSendByte((address >> 8) & 0xFF);
- FlashSendLastByte((address >> 0) & 0xFF);
- return true;
-}
-*/
-
-// erase 64k at one time
-// since a block is 64kb, and there is four blocks.
-// we only need block number, as MSB
-// execution time: 1s / 1000ms
-// 0x00 00 00 -- 0x 00 FF FF == block 0
-// 0x01 00 00 -- 0x 01 FF FF == block 1
-// 0x02 00 00 -- 0x 02 FF FF == block 2
-// 0x03 00 00 -- 0x 03 FF FF == block 3
-bool Flash_Erase64k(uint8_t block) {
-
- if (block > MAX_BLOCKS) return false;
-
- FlashSendByte(BLOCK64ERASE);
- FlashSendByte(block);
- FlashSendByte(0x00);
- FlashSendLastByte(0x00);
- return true;
-}
-
-/*
-// Erase chip
-void Flash_EraseChip(void) {
- FlashSendLastByte(CHIPERASE);
-}
-*/
-
-void Flashmem_print_status(void) {
- DbpString(_BLUE_("Flash memory"));
- Dbprintf(" Baudrate................" _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
-
- if (!FlashInit()) {
- DbpString(" Init...................." _RED_("FAILED"));
- return;
- }
- DbpString(" Init...................." _GREEN_("OK"));
-
- uint8_t dev_id = Flash_ReadID();
- switch (dev_id) {
- case 0x11 :
- DbpString(" Memory size............." _YELLOW_("2 mbits / 256 kb"));
- break;
- case 0x10 :
- DbpString(" Memory size..... ......." _YELLOW_("1 mbits / 128 kb"));
- break;
- case 0x05 :
- DbpString(" Memory size............." _YELLOW_("512 kbits / 64 kb"));
- break;
- default :
- DbpString(" Device ID..............." _YELLOW_(" --> Unknown <--"));
- break;
- }
-
- uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- Flash_UniqueID(uid);
- Dbprintf(" Unique ID...............0x%02X%02X%02X%02X%02X%02X%02X%02X",
- uid[7], uid[6], uid[5], uid[4],
- uid[3], uid[2], uid[1], uid[0]
- );
-
- FlashStop();
-}
-
-void Flashmem_print_info(void) {
-
- if (!FlashInit()) return;
-
- DbpString(_BLUE_("Flash memory dictionary loaded"));
-
- // load dictionary offsets.
- uint8_t keysum[2];
- uint16_t num;
-
- Flash_CheckBusy(BUSY_TIMEOUT);
- uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
- if (isok == 2) {
- num = ((keysum[1] << 8) | keysum[0]);
- if (num != 0xFFFF && num != 0x0)
- Dbprintf(" Mifare.................."_YELLOW_("%d")"keys", num);
- }
-
- Flash_CheckBusy(BUSY_TIMEOUT);
- isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
- if (isok == 2) {
- num = ((keysum[1] << 8) | keysum[0]);
- if (num != 0xFFFF && num != 0x0)
- Dbprintf(" T55x7..................."_YELLOW_("%d")"keys", num);
- }
-
- Flash_CheckBusy(BUSY_TIMEOUT);
- isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
- if (isok == 2) {
- num = ((keysum[1] << 8) | keysum[0]);
- if (num != 0xFFFF && num != 0x0)
- Dbprintf(" iClass.................."_YELLOW_("%d")"keys", num);
- }
-
- FlashStop();
-}
-
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/flashmem.h b/pm3rdv4rrg/src/main/cpp/armsrc/flashmem.h
deleted file mode 100644
index 42fc3d2f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/flashmem.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Arduino SPIFlash Library v.2.5.0
- * Copyright (C) 2015 by Prajwal Bhattaram
- * Modified by Prajwal Bhattaram - 13/11/2016
- *
- * This file is part of the Arduino SPIFlash Library. This library is for
- * Winbond NOR flash memory modules. In its current form it enables reading
- * and writing individual data variables, structs and arrays from and to various locations;
- * reading and writing pages; continuous read functions; sector, block and chip erase;
- * suspending and resuming programming/erase and powering down for low power operation.
- *
- * This Library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License v3.0
- * along with the Arduino SPIFlash Library. If not, see
- * .
- */
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
-// Common Instructions //
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
-#ifndef __FLASHMEM_H
-#define __FLASHMEM_H
-
-#include "common.h"
-
-// Used Command
-#define ID 0x90
-#define MANID 0x90
-#define JEDECID 0x9F
-
-#define READSTAT1 0x05
-#define READSTAT2 0x35
-#define WRITESTAT 0x01
-
-#define WRITEDISABLE 0x04
-#define WRITEENABLE 0x06
-
-#define READDATA 0x03
-#define FASTREAD 0x0B
-#define PAGEPROG 0x02
-
-#define SECTORERASE 0x20
-#define BLOCK32ERASE 0x52
-#define BLOCK64ERASE 0xD8
-#define CHIPERASE 0xC7
-
-#define UNIQUE_ID 0x4B
-
-// Not used or not support command
-#define RELEASE 0xAB
-#define POWERDOWN 0xB9
-#define SUSPEND 0x75
-#define RESUME 0x7A
-
-// Flash busy timeout: 20ms is the strict minimum when writing 256kb
-#define BUSY_TIMEOUT 200000L
-
-#define WINBOND_MANID 0xEF
-#define WINBOND_DEVID 0x11
-#define PAGESIZE 0x100
-#define WINBOND_WRITE_DELAY 0x02
-
-#define SPI_CLK 48000000
-
-#define BUSY 0x01
-#define WRTEN 0x02
-#define SUS 0x40
-
-#define DUMMYBYTE 0xEE
-#define NULLBYTE 0x00
-#define NULLINT 0x0000
-#define NO_CONTINUE 0x00
-#define PASS 0x01
-#define FAIL 0x00
-#define maxAddress capacity
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
-// List of Error codes //
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
-#define SUCCESS 0x00
-#define CALLBEGIN 0x01
-#define UNKNOWNCHIP 0x02
-#define UNKNOWNCAP 0x03
-#define CHIPBUSY 0x04
-#define OUTOFBOUNDS 0x05
-#define CANTENWRITE 0x06
-#define PREVWRITTEN 0x07
-#define LOWRAM 0x08
-#define NOSUSPEND 0x09
-#define UNKNOWNERROR 0xFF
-
-// List of blocks
-#define MAX_BLOCKS 4
-#define MAX_SECTORS 16
-
-//#define FLASH_BAUD 24000000
-#define FLASH_MINFAST 24000000 //33000000
-#define FLASH_BAUD MCK/2
-#define FLASH_FASTBAUD MCK
-#define FLASH_MINBAUD FLASH_FASTBAUD
-
-#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
-
-void FlashmemSetSpiBaudrate(uint32_t baudrate);
-bool FlashInit();
-void FlashSetup(uint32_t baudrate);
-void FlashStop(void);
-bool Flash_WaitIdle(void);
-uint8_t Flash_ReadStat1(void);
-uint8_t Flash_ReadStat2(void);
-uint16_t FlashSendByte(uint32_t data);
-void Flash_TransferAdresse(uint32_t address);
-
-bool Flash_CheckBusy(uint32_t timeout);
-
-void Flash_WriteEnable();
-bool Flash_WipeMemoryPage(uint8_t page);
-bool Flash_WipeMemory();
-bool Flash_Erase4k(uint8_t block, uint8_t sector);
-//bool Flash_Erase32k(uint32_t address);
-bool Flash_Erase64k(uint8_t block);
-
-void Flash_UniqueID(uint8_t *uid);
-uint8_t Flash_ReadID(void);
-uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
-uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
-uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len);
-uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
-uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
-void Flashmem_print_status(void);
-void Flashmem_print_info(void);
-uint16_t FlashSendLastByte(uint32_t data);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/fonts_disabled.c b/pm3rdv4rrg/src/main/cpp/armsrc/fonts_disabled.c
deleted file mode 100644
index 97079f48..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/fonts_disabled.c
+++ /dev/null
@@ -1,310 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Fonts for the LCD
-//-----------------------------------------------------------------------------
-
-#include "fonts.h"
-
-const char FONT6x8[97][8] = {
- {0x06, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // columns, rows, bytes per char
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // space
- {0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00}, // !
- {0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00}, // "
- {0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00}, // #
- {0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00}, // $
- {0xC0, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x18, 0x00}, // %
- {0x40, 0xA0, 0xA0, 0x40, 0xA8, 0x90, 0x68, 0x00}, // &
- {0x30, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00}, // '
- {0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00}, // (
- {0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00}, // )
- {0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00}, // *
- {0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00}, // +
- {0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x20, 0x40}, // ,
- {0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00}, // -
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00}, // .
- {0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00}, // /
- {0x70, 0x88, 0x88, 0xA8, 0x88, 0x88, 0x70, 0x00}, // 0
- {0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // 1
- {0x70, 0x88, 0x08, 0x70, 0x80, 0x80, 0xF8, 0x00}, // 2
- {0xF8, 0x08, 0x10, 0x30, 0x08, 0x88, 0x70, 0x00}, // 3
- {0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10, 0x00}, // 4
- {0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70, 0x00}, // 5
- {0x38, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00}, // 6
- {0xF8, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00}, // 7
- {0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00}, // 8
- {0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0xE0, 0x00}, // 9
- {0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00}, // :
- {0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x40, 0x00}, // ;
- {0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00}, // <
- {0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00}, // =
- {0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00}, // >
- {0x70, 0x88, 0x08, 0x30, 0x20, 0x00, 0x20, 0x00}, // ?
- {0x70, 0x88, 0xA8, 0xB8, 0xB0, 0x80, 0x78, 0x00}, // @
- {0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00}, // A
- {0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00}, // B
- {0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00}, // C
- {0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x00}, // D
- {0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00}, // E
- {0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00}, // F
- {0x78, 0x88, 0x80, 0x80, 0x98, 0x88, 0x78, 0x00}, // G
- {0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00}, // H
- {0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // I
- {0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00}, // J
- {0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00}, // K
- {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00}, // L
- {0x88, 0xD8, 0xA8, 0xA8, 0xA8, 0x88, 0x88, 0x00}, // M
- {0x88, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x00}, // N
- {0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00}, // O
- {0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00}, // P
- {0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00}, // Q
- {0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00}, // R
- {0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00}, // S
- {0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // T
- {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00}, // U
- {0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00}, // V
- {0x88, 0x88, 0x88, 0xA8, 0xA8, 0xA8, 0x50, 0x00}, // W
- {0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00}, // X
- {0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20, 0x00}, // Y
- {0xF8, 0x08, 0x10, 0x70, 0x40, 0x80, 0xF8, 0x00}, // Z
- {0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x78, 0x00}, // [
- {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00}, // backslash
- {0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}, // ]
- {0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00}, // ^
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00}, // _
- {0x60, 0x60, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00}, // `
- {0x00, 0x00, 0x60, 0x10, 0x70, 0x90, 0x78, 0x00}, // a
- {0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00}, // b
- {0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00}, // c
- {0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00}, // d
- {0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00}, // e
- {0x10, 0x28, 0x20, 0x70, 0x20, 0x20, 0x20, 0x00}, // f
- {0x00, 0x00, 0x70, 0x98, 0x98, 0x68, 0x08, 0x70}, // g
- {0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00}, // h
- {0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00}, // i
- {0x10, 0x00, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00}, // j
- {0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x00}, // k
- {0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // l
- {0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00}, // m
- {0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00}, // n
- {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00}, // o
- {0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80}, // p
- {0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08}, // q
- {0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00}, // r
- {0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00}, // s
- {0x20, 0x20, 0xF8, 0x20, 0x20, 0x28, 0x10, 0x00}, // t
- {0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00}, // u
- {0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00}, // v
- {0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50, 0x00}, // w
- {0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00}, // x
- {0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70}, // y
- {0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00}, // z
- {0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00}, // {
- {0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x00}, // |
- {0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00}, // }
- {0x40, 0xA8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, // ~
- {0x70, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00} // DEL
-};
-/*
-const char FONT8x8F[97][8] = {
- {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
- {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // !
- {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // "
- {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // #
- {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $
- {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // %
- {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // &
- {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // '
- {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // (
- {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // )
- {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // *
- {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // +
- {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // ,
- {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // -
- {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // .
- {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // /
- {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0
- {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1
- {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2
- {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3
- {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4
- {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5
- {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6
- {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7
- {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8
- {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9
- {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
- {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ;
- {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // <
- {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // =
- {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // >
- {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ?
- {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @
- {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A
- {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B
- {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C
- {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D
- {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E
- {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F
- {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G
- {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H
- {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I
- {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J
- {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K
- {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L
- {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M
- {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N
- {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O
- {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P
- {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q
- {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R
- {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S
- {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T
- {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U
- {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V
- {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W
- {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X
- {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y
- {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z
- {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [
- {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // backslash
- {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ]
- {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _
- {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // `
- {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a
- {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b
- {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c
- {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d
- {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e
- {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f
- {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g
- {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h
- {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i
- {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j
- {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k
- {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l
- {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m
- {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n
- {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o
- {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p
- {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q
- {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r
- {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s
- {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t
- {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u
- {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v
- {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w
- {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x
- {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y
- {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z
- {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // {
- {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // |
- {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // }
- {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
- {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00} // DEL
-};
-
-const char FONT8x16[97][16] = {
- {0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
- {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // !
- {0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // "
- {0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // #
- {0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00}, // $
- {0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00}, // %
- {0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // &
- {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // '
- {0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00}, // (
- {0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00}, // )
- {0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00}, // *
- {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, // +
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ,
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // -
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // .
- {0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00}, // /
- {0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 0
- {0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00}, // 1
- {0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // 2
- {0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // 3
- {0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00}, // 4
- {0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00}, // 5
- {0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 6
- {0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, // 7
- {0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 8
- {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00}, // 9
- {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // :
- {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ;
- {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, // <
- {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, // =
- {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, // >
- {0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00}, // ?
- {0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00}, // @
- {0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // A
- {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00}, // B
- {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00}, // C
- {0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00}, // D
- {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // E
- {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // F
- {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00}, // G
- {0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // H
- {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // I
- {0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}, // J
- {0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // K
- {0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // L
- {0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // M
- {0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // N
- {0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00}, // O
- {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // P
- {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00}, // Q
- {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // R
- {0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // S
- {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // T
- {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // U
- {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00}, // V
- {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // W
- {0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00}, // X
- {0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // Y
- {0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // Z
- {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, // [
- {0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, // backslash
- {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, // ]
- {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // _
- {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // `
- {0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // a
- {0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00}, // b
- {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // c
- {0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // d
- {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // e
- {0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // f
- {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00}, // g
- {0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // h
- {0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // i
- {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00}, // j
- {0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00}, // k
- {0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // l
- {0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00}, // m
- {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00}, // n
- {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // o
- {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00}, // p
- {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00}, // q
- {0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // r
- {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // s
- {0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00}, // t
- {0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // u
- {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00}, // v
- {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00}, // w
- {0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // x
- {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00}, // y
- {0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00}, // z
- {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, // {
- {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, // |
- {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, // }
- {0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
- {0x00,0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // DEL
-};
-*/
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/fonts_disabled.h b/pm3rdv4rrg/src/main/cpp/armsrc/fonts_disabled.h
deleted file mode 100644
index 000be07a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/fonts_disabled.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Fonts for the LCD
-//-----------------------------------------------------------------------------
-
-#ifndef __FONTS_H
-#define __FONTS_H
-
-extern const char FONT6x8[97][8];
-extern const char FONT8x8F[97][8];
-extern const char FONT8x16[97][16];
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/fpgaloader.c b/pm3rdv4rrg/src/main/cpp/armsrc/fpgaloader.c
deleted file mode 100644
index 5affa055..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/fpgaloader.c
+++ /dev/null
@@ -1,530 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, April 2006
-// iZsh , 2014
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to load the FPGA image, and then to configure the FPGA's major
-// mode once it is configured.
-//-----------------------------------------------------------------------------
-#include "fpgaloader.h"
-
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "BigBuf.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "zlib.h"
-#include "fpga.h"
-#include "string.h"
-
-// remember which version of the bitstream we have already downloaded to the FPGA
-static int downloaded_bitstream = 0;
-
-// this is where the bitstreams are located in memory:
-extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end;
-
-static uint8_t *fpga_image_ptr = NULL;
-static uint32_t uncompressed_bytes_cnt;
-
-#define OUTPUT_BUFFER_LEN 80
-
-//-----------------------------------------------------------------------------
-// Set up the Serial Peripheral Interface as master
-// Used to write the FPGA config word
-// May also be used to write to other SPI attached devices like an LCD
-//-----------------------------------------------------------------------------
-static void DisableSpi(void) {
- //* Reset all the Chip Select register
- AT91C_BASE_SPI->SPI_CSR[0] = 0;
- AT91C_BASE_SPI->SPI_CSR[1] = 0;
- AT91C_BASE_SPI->SPI_CSR[2] = 0;
- AT91C_BASE_SPI->SPI_CSR[3] = 0;
-
- // Reset the SPI mode
- AT91C_BASE_SPI->SPI_MR = 0;
-
- // Disable all interrupts
- AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
-
- // SPI disable
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
-}
-
-void SetupSpi(int mode) {
- // PA1 -> SPI_NCS3 chip select (MEM)
- // PA10 -> SPI_NCS2 chip select (LCD)
- // PA11 -> SPI_NCS0 chip select (FPGA)
- // PA12 -> SPI_MISO Master-In Slave-Out
- // PA13 -> SPI_MOSI Master-Out Slave-In
- // PA14 -> SPI_SPCK Serial Clock
-
- // Disable PIO control of the following pins, allows use by the SPI peripheral
- AT91C_BASE_PIOA->PIO_PDR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK;
-
- // Peripheral A
- AT91C_BASE_PIOA->PIO_ASR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK;
-
- // Peripheral B
- //AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2;
-
- //enable the SPI Peripheral clock
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
- // Enable SPI
- AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
-
- switch (mode) {
- case SPI_FPGA_MODE:
- AT91C_BASE_SPI->SPI_MR =
- (0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
- (0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
- (0 << 7) | // Local Loopback Disabled
- AT91C_SPI_MODFDIS | // Mode Fault Detection disabled
- (0 << 2) | // Chip selects connected directly to peripheral
- AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
- AT91C_SPI_MSTR; // Master Mode
-
- AT91C_BASE_SPI->SPI_CSR[0] =
- (1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
- (1 << 16) | // Delay Before SPCK (1 MCK period)
- (6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
- AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
- (0 << 3) | // Chip Select inactive after transfer
- AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
- (0 << 0); // Clock Polarity inactive state is logic 0
- break;
- /*
- case SPI_LCD_MODE:
- AT91C_BASE_SPI->SPI_MR =
- ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
- (0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)
- ( 0 << 7) | // Local Loopback Disabled
- ( 1 << 4) | // Mode Fault Detection disabled
- ( 0 << 2) | // Chip selects connected directly to peripheral
- ( 0 << 1) | // Fixed Peripheral Select
- ( 1 << 0); // Master Mode
-
- AT91C_BASE_SPI->SPI_CSR[2] =
- ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
- ( 1 << 16) | // Delay Before SPCK (1 MCK period)
- ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
- AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
- ( 0 << 3) | // Chip Select inactive after transfer
- ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
- ( 0 << 0); // Clock Polarity inactive state is logic 0
- break;
- */
- default:
- DisableSpi();
- break;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Set up the synchronous serial port with the set of options that fits
-// the FPGA mode. Both RX and TX are always enabled.
-//-----------------------------------------------------------------------------
-void FpgaSetupSsc(void) {
- // First configure the GPIOs, and get ourselves a clock.
- AT91C_BASE_PIOA->PIO_ASR =
- GPIO_SSC_FRAME |
- GPIO_SSC_DIN |
- GPIO_SSC_DOUT |
- GPIO_SSC_CLK;
- AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
-
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);
-
- // Now set up the SSC proper, starting from a known state.
- AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
-
- // RX clock comes from TX clock, RX starts on Transmit Start,
- // data and frame signal is sampled on falling edge of RK
- AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);
-
- // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync
- // pulse, no output sync
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
-
- // TX clock comes from TK pin, no clock output, outputs change on falling
- // edge of TK, frame sync is sampled on rising edge of TK, start TX on rising edge of TF
- AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
-
- // tx framing is the same as the rx framing
- AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR;
-
- AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;
-}
-
-//-----------------------------------------------------------------------------
-// Set up DMA to read samples from the FPGA. We will use the PDC, with
-// a single buffer as a circular buffer (so that we just chain back to
-// ourselves, not to another buffer).
-//-----------------------------------------------------------------------------
-bool FpgaSetupSscDma(uint8_t *buf, int len) {
- if (buf == NULL) return false;
-
- FpgaDisableSscDma();
- AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address
- AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address
- AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes
- FpgaEnableSscDma();
- return true;
-}
-
-//----------------------------------------------------------------------------
-// Uncompress (inflate) the FPGA data. Returns one decompressed byte with
-// each call.
-//----------------------------------------------------------------------------
-static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
- if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data
- compressed_fpga_stream->next_out = output_buffer;
- compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
- fpga_image_ptr = output_buffer;
- int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH);
-
- if (res != Z_OK)
- Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg);
-
- if (res < 0)
- return res;
- }
- uncompressed_bytes_cnt++;
- return *fpga_image_ptr++;
-}
-
-//----------------------------------------------------------------------------
-// Undo the interleaving of several FPGA config files. FPGA config files
-// are combined into one big file:
-// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc.
-//----------------------------------------------------------------------------
-static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
- while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
- // skip undesired data belonging to other bitstream_versions
- get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
- }
-
- return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
-}
-
-static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) {
- return BigBuf_malloc(items * size);
-}
-
-// free eventually allocated BigBuf memory
-static void fpga_inflate_free(voidpf opaque, voidpf address) {
- BigBuf_free();
- BigBuf_Clear_ext(false);
-}
-
-//----------------------------------------------------------------------------
-// Initialize decompression of the respective (HF or LF) FPGA stream
-//----------------------------------------------------------------------------
-static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
- uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE];
-
- uncompressed_bytes_cnt = 0;
-
- // initialize z_stream structure for inflate:
- compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start;
- compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start;
- compressed_fpga_stream->next_out = output_buffer;
- compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
- compressed_fpga_stream->zalloc = &fpga_inflate_malloc;
- compressed_fpga_stream->zfree = &fpga_inflate_free;
-
- int res = inflateInit2(compressed_fpga_stream, 0);
- if (res < 0)
- return false;
-
- fpga_image_ptr = output_buffer;
-
- for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++)
- header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
-
- // Check for a valid .bit file (starts with bitparse_fixed_header)
- if (memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0)
- return true;
-
- return false;
-}
-
-static void DownloadFPGA_byte(uint8_t w) {
-#define SEND_BIT(x) { if(w & (1<PIO_OER = GPIO_FPGA_ON;
- AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON;
- HIGH(GPIO_FPGA_ON); // ensure everything is powered on
-
- SpinDelay(50);
-
- LED_D_ON();
-
- // These pins are inputs
- AT91C_BASE_PIOA->PIO_ODR =
- GPIO_FPGA_NINIT |
- GPIO_FPGA_DONE;
- // PIO controls the following pins
- AT91C_BASE_PIOA->PIO_PER =
- GPIO_FPGA_NINIT |
- GPIO_FPGA_DONE;
- // Enable pull-ups
- AT91C_BASE_PIOA->PIO_PPUER =
- GPIO_FPGA_NINIT |
- GPIO_FPGA_DONE;
-
- // setup initial logic state
- HIGH(GPIO_FPGA_NPROGRAM);
- LOW(GPIO_FPGA_CCLK);
- LOW(GPIO_FPGA_DIN);
- // These pins are outputs
- AT91C_BASE_PIOA->PIO_OER =
- GPIO_FPGA_NPROGRAM |
- GPIO_FPGA_CCLK |
- GPIO_FPGA_DIN;
-
- // enter FPGA configuration mode
- LOW(GPIO_FPGA_NPROGRAM);
- SpinDelay(50);
- HIGH(GPIO_FPGA_NPROGRAM);
-
- i = 100000;
- // wait for FPGA ready to accept data signal
- while ((i) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT))) {
- i--;
- }
-
- // crude error indicator, leave both red LEDs on and return
- if (i == 0) {
- LED_C_ON();
- LED_D_ON();
- return;
- }
-
- for (i = 0; i < FpgaImageLen; i++) {
- int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
- if (b < 0) {
- Dbprintf("Error %d during FpgaDownload", b);
- break;
- }
- DownloadFPGA_byte(b);
- }
-
- // continue to clock FPGA until ready signal goes high
- i = 100000;
- while ((i--) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE))) {
- HIGH(GPIO_FPGA_CCLK);
- LOW(GPIO_FPGA_CCLK);
- }
- // crude error indicator, leave both red LEDs on and return
- if (i == 0) {
- LED_C_ON();
- LED_D_ON();
- return;
- }
- LED_D_OFF();
-}
-
-/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence
- * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01
- * After that the format is 1 byte section type (ASCII character), 2 byte length
- * (big endian), bytes content. Except for section 'e' which has 4 bytes
- * length.
- */
-static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
- int result = 0;
-#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
- uint16_t numbytes = 0;
- while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
- char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
- numbytes++;
- uint32_t current_length = 0;
- if (current_name < 'a' || current_name > 'e') {
- /* Strange section name, abort */
- break;
- }
- current_length = 0;
- switch (current_name) {
- case 'e':
- /* Four byte length field */
- current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
- current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
- numbytes += 2;
- default: /* Fall through, two byte length field */
- current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
- current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
- numbytes += 2;
- }
-
- if (current_name != 'e' && current_length > 255) {
- /* Maybe a parse error */
- break;
- }
-
- if (current_name == section_name) {
- /* Found it */
- *section_length = current_length;
- result = 1;
- break;
- }
-
- for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
- get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
- numbytes++;
- }
- }
- return result;
-}
-
-//----------------------------------------------------------------------------
-// Check which FPGA image is currently loaded (if any). If necessary
-// decompress and load the correct (HF or LF) image to the FPGA
-//----------------------------------------------------------------------------
-void FpgaDownloadAndGo(int bitstream_version) {
-
- // check whether or not the bitstream is already loaded
- if (downloaded_bitstream == bitstream_version) {
- FpgaEnableTracing();
- return;
- }
-
- // Send waiting time extension request as this will take a while
- send_wtx(1500);
- z_stream compressed_fpga_stream;
- uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
-
- bool verbose = (DBGLEVEL > 3);
-
- // make sure that we have enough memory to decompress
- BigBuf_free();
- BigBuf_Clear_ext(verbose);
-
- if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
- return;
-
- uint32_t bitstream_length;
- if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) {
- DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer);
- downloaded_bitstream = bitstream_version;
- }
-
- inflateEnd(&compressed_fpga_stream);
-
- // turn off antenna
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
- BigBuf_Clear_ext(false);
-}
-
-//-----------------------------------------------------------------------------
-// Send a 16 bit command/data pair to the FPGA.
-// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
-// where C is the 4 bit command and D is the 12 bit data
-//
-// @params cmd and v gets or over eachother. Take careful note of overlapping bits.
-//-----------------------------------------------------------------------------
-void FpgaSendCommand(uint16_t cmd, uint16_t v) {
- SetupSpi(SPI_FPGA_MODE);
- while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
- AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // write the data
- while (!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF)) {}; // wait till transfer is complete
-}
-//-----------------------------------------------------------------------------
-// Write the FPGA setup word (that determines what mode the logic is in, read
-// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
-// avoid changing this function's occurence everywhere in the source code.
-//-----------------------------------------------------------------------------
-void FpgaWriteConfWord(uint16_t v) {
- FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
-}
-
-//-----------------------------------------------------------------------------
-// enable/disable FPGA internal tracing
-//-----------------------------------------------------------------------------
-void FpgaEnableTracing(void) {
- FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1);
-}
-
-void FpgaDisableTracing(void) {
- FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0);
-}
-
-//-----------------------------------------------------------------------------
-// Set up the CMOS switches that mux the ADC: four switches, independently
-// closable, but should only close one at a time. Not an FPGA thing, but
-// the samples from the ADC always flow through the FPGA.
-//-----------------------------------------------------------------------------
-void SetAdcMuxFor(uint32_t whichGpio) {
-
-#ifndef WITH_FPC_USART
- // When compiled without FPC USART support
- AT91C_BASE_PIOA->PIO_OER =
- GPIO_MUXSEL_HIPKD |
- GPIO_MUXSEL_LOPKD |
- GPIO_MUXSEL_LORAW |
- GPIO_MUXSEL_HIRAW;
-
- AT91C_BASE_PIOA->PIO_PER =
- GPIO_MUXSEL_HIPKD |
- GPIO_MUXSEL_LOPKD |
- GPIO_MUXSEL_LORAW |
- GPIO_MUXSEL_HIRAW;
-
- LOW(GPIO_MUXSEL_HIPKD);
- LOW(GPIO_MUXSEL_LOPKD);
- LOW(GPIO_MUXSEL_HIRAW);
- LOW(GPIO_MUXSEL_LORAW);
- HIGH(whichGpio);
-#else
- if ((whichGpio == GPIO_MUXSEL_LORAW) || (whichGpio == GPIO_MUXSEL_HIRAW))
- return;
- // FPC USART uses HIRAW/LOWRAW pins, so they are excluded here.
- AT91C_BASE_PIOA->PIO_OER = GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_LOPKD;
- AT91C_BASE_PIOA->PIO_PER = GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_LOPKD;
- LOW(GPIO_MUXSEL_HIPKD);
- LOW(GPIO_MUXSEL_LOPKD);
- HIGH(whichGpio);
-#endif
-
-}
-
-void Fpga_print_status(void) {
- DbpString(_BLUE_("Currently loaded FPGA image"));
- Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream - 1]);
-}
-
-int FpgaGetCurrent(void) {
- return downloaded_bitstream;
-}
-
-// Turns off the antenna,
-// log message
-// if HF, Disable SSC DMA
-// turn off trace and leds off.
-void switch_off(void) {
- if (DBGLEVEL > 3) Dbprintf("switch_off");
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- if (downloaded_bitstream == FPGA_BITSTREAM_HF)
- FpgaDisableSscDma();
- set_tracing(false);
- LEDsoff();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/fpgaloader.h b/pm3rdv4rrg/src/main/cpp/armsrc/fpgaloader.h
deleted file mode 100644
index 636c5b7b..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/fpgaloader.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, April 2006
-// iZsh , 2014
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to load the FPGA image, and then to configure the FPGA's major
-// mode once it is configured.
-//-----------------------------------------------------------------------------
-#ifndef __FPGALOADER_H
-#define __FPGALOADER_H
-
-#include "common.h"
-
-#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
-#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
-
-// definitions for multiple FPGA config files support
-#define FPGA_BITSTREAM_LF 1
-#define FPGA_BITSTREAM_HF 2
-
-/*
- Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand)
- Send 16 bit command / data pair to FPGA
- The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
- where
- C is 4bit command
- D is 12bit data
-
------+--------- frame layout --------------------
-bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
------+-------------------------------------------
-cmd | x x x x
-major| x x x
-opt | x x
-divi | x x x x x x x x
-thres| x x x x x x x x
------+-------------------------------------------
-*/
-
-// Definitions for the FPGA commands.
-// BOTH HF / LF
-#define FPGA_CMD_SET_CONFREG (1<<12) // C
-
-// LF
-#define FPGA_CMD_SET_DIVISOR (2<<12) // C
-#define FPGA_CMD_SET_USER_BYTE1 (3<<12) // C
-
-// HF
-#define FPGA_CMD_TRACE_ENABLE (2<<12) // C
-
-// Definitions for the FPGA configuration word.
-// LF
-#define FPGA_MAJOR_MODE_LF_READER (0<<5)
-#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
-#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
-#define FPGA_MAJOR_MODE_LF_ADC (3<<5)
-
-// HF
-#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) // D
-#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) // D
-#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) // D
-#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) // D
-#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) // D
-#define FPGA_MAJOR_MODE_HF_ISO18092 (5<<5) // D
-#define FPGA_MAJOR_MODE_HF_GET_TRACE (6<<5) // D
-
-// BOTH HF / LF
-#define FPGA_MAJOR_MODE_OFF (7<<5) // D
-
-// Options for LF_READER
-#define FPGA_LF_ADC_READER_FIELD 0x1
-
-// Options for LF_EDGE_DETECT
-#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
-#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1
-#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2
-
-// Options for the HF reader, tx to tag
-#define FPGA_HF_READER_TX_SHALLOW_MOD 0x1
-
-// Options for the HF reader, correlating against rx from tag
-#define FPGA_HF_READER_RX_XCORR_848_KHZ 0x1
-#define FPGA_HF_READER_RX_XCORR_SNOOP 0x2
-#define FPGA_HF_READER_RX_XCORR_QUARTER 0x4
-
-// Options for the HF simulated tag, how to modulate
-#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000
-#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001
-#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010
-#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100
-#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101
-// no 848K
-
-// Options for ISO14443A
-#define FPGA_HF_ISO14443A_SNIFFER 0x0
-#define FPGA_HF_ISO14443A_TAGSIM_LISTEN 0x1
-#define FPGA_HF_ISO14443A_TAGSIM_MOD 0x2
-#define FPGA_HF_ISO14443A_READER_LISTEN 0x3
-#define FPGA_HF_ISO14443A_READER_MOD 0x4
-
-//options for Felica.
-#define FPGA_HF_ISO18092_FLAG_NOMOD 0x1 // 0001 disable modulation module
-#define FPGA_HF_ISO18092_FLAG_424K 0x2 // 0010 should enable 414k mode (untested). No autodetect
-#define FPGA_HF_ISO18092_FLAG_READER 0x4 // 0100 enables antenna power, to act as a reader instead of tag
-
-void FpgaSendCommand(uint16_t cmd, uint16_t v);
-void FpgaWriteConfWord(uint16_t v);
-void FpgaEnableTracing(void);
-void FpgaDisableTracing(void);
-void FpgaDownloadAndGo(int bitstream_version);
-// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
-void FpgaSetupSsc(void);
-void SetupSpi(int mode);
-bool FpgaSetupSscDma(uint8_t *buf, int len);
-void Fpga_print_status(void);
-int FpgaGetCurrent(void);
-void SetAdcMuxFor(uint32_t whichGpio);
-
-// extern and generel turn off the antenna method
-void switch_off(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/frozen.c b/pm3rdv4rrg/src/main/cpp/armsrc/frozen.c
deleted file mode 100644
index 41f2179c..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/frozen.c
+++ /dev/null
@@ -1,1470 +0,0 @@
-/*
- * Copyright (c) 2004-2013 Sergey Lyubka
- * Copyright (c) 2018 Cesanta Software Limited
- * All rights reserved
- *
- * Licensed under the Apache License, Version 2.0 (the ""License"");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an ""AS IS"" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */
-
-#include "frozen.h"
-
-#include
-#include
-#include "nprintf.h"
-
-#include "BigBuf.h"
-#define malloc(X) BigBuf_malloc(X)
-#define free(X)
-
-#if !defined(WEAK)
-#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
-#define WEAK __attribute__((weak))
-#else
-#define WEAK
-#endif
-#endif
-
-#ifdef _WIN32
-#undef snprintf
-#undef vsnprintf
-#define snprintf cs_win_snprintf
-#define vsnprintf cs_win_vsnprintf
-int cs_win_snprintf(char *str, size_t size, const char *format, ...);
-int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap);
-#if _MSC_VER >= 1700
-#include "stdint.h"
-#else
-typedef _int64 int64_t;
-typedef unsigned _int64 uint64_t;
-#endif
-#define PRId64 "I64d"
-#define PRIu64 "I64u"
-#else /* _WIN32 */
-/* wants this for C++ */
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS
-#endif
-#include
-#endif /* _WIN32 */
-
-#ifndef INT64_FMT
-#define INT64_FMT PRId64
-#endif
-#ifndef UINT64_FMT
-#define UINT64_FMT PRIu64
-#endif
-
-#ifndef va_copy
-#define va_copy(x, y) x = y
-#endif
-
-#ifndef JSON_ENABLE_ARRAY
-#define JSON_ENABLE_ARRAY 1
-#endif
-
-struct frozen {
- const char *end;
- const char *cur;
-
- const char *cur_name;
- size_t cur_name_len;
-
- /* For callback API */
- char path[JSON_MAX_PATH_LEN];
- size_t path_len;
- void *callback_data;
- json_walk_callback_t callback;
-};
-
-struct fstate {
- const char *ptr;
- size_t path_len;
-};
-
-#define SET_STATE(fr, ptr, str, len) \
- struct fstate fstate = {(ptr), (fr)->path_len}; \
- json_append_to_path((fr), (str), (len));
-
-#define CALL_BACK(fr, tok, value, len) \
- do { \
- if ((fr)->callback && \
- ((fr)->path_len == 0 || (fr)->path[(fr)->path_len - 1] != '.')) { \
- struct json_token t = {(value), (int) (len), (tok)}; \
- \
- /* Call the callback with the given value and current name */ \
- (fr)->callback((fr)->callback_data, (fr)->cur_name, (fr)->cur_name_len, \
- (fr)->path, &t); \
- \
- /* Reset the name */ \
- (fr)->cur_name = NULL; \
- (fr)->cur_name_len = 0; \
- } \
- } while (0)
-
-static int json_append_to_path(struct frozen *f, const char *str, int size) {
- int n = f->path_len;
- int left = sizeof(f->path) - n - 1;
- if (size > left) size = left;
- memcpy(f->path + n, str, size);
- f->path[n + size] = '\0';
- f->path_len += size;
- return n;
-}
-
-static void json_truncate_path(struct frozen *f, size_t len) {
- f->path_len = len;
- f->path[len] = '\0';
-}
-
-static int json_parse_object(struct frozen *f);
-static int json_parse_value(struct frozen *f);
-
-#define EXPECT(cond, err_code) \
- do { \
- if (!(cond)) return (err_code); \
- } while (0)
-
-#define TRY(expr) \
- do { \
- int _n = expr; \
- if (_n < 0) return _n; \
- } while (0)
-
-#define END_OF_STRING (-1)
-
-static int json_left(const struct frozen *f) {
- return f->end - f->cur;
-}
-
-static int json_isspace(int ch) {
- return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
-}
-
-static void json_skip_whitespaces(struct frozen *f) {
- while (f->cur < f->end && json_isspace(*f->cur)) f->cur++;
-}
-
-static int json_cur(struct frozen *f) {
- json_skip_whitespaces(f);
- return f->cur >= f->end ? END_OF_STRING : *(unsigned char *) f->cur;
-}
-
-static int json_test_and_skip(struct frozen *f, int expected) {
- int ch = json_cur(f);
- if (ch == expected) {
- f->cur++;
- return 0;
- }
- return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
-}
-
-static int json_isalpha(int ch) {
- return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
-}
-
-static int json_isdigit(int ch) {
- return ch >= '0' && ch <= '9';
-}
-
-static int json_isxdigit(int ch) {
- return json_isdigit(ch) || (ch >= 'a' && ch <= 'f') ||
- (ch >= 'A' && ch <= 'F');
-}
-
-static int json_get_escape_len(const char *s, int len) {
- switch (*s) {
- case 'u':
- return len < 6 ? JSON_STRING_INCOMPLETE
- : json_isxdigit(s[1]) && json_isxdigit(s[2]) &&
- json_isxdigit(s[3]) && json_isxdigit(s[4])
- ? 5
- : JSON_STRING_INVALID;
- case '"':
- case '\\':
- case '/':
- case 'b':
- case 'f':
- case 'n':
- case 'r':
- case 't':
- return len < 2 ? JSON_STRING_INCOMPLETE : 1;
- default:
- return JSON_STRING_INVALID;
- }
-}
-
-/* identifier = letter { letter | digit | '_' } */
-static int json_parse_identifier(struct frozen *f) {
- EXPECT(json_isalpha(json_cur(f)), JSON_STRING_INVALID);
- {
- SET_STATE(f, f->cur, "", 0);
- while (f->cur < f->end &&
- (*f->cur == '_' || json_isalpha(*f->cur) || json_isdigit(*f->cur))) {
- f->cur++;
- }
- json_truncate_path(f, fstate.path_len);
- CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr);
- }
- return 0;
-}
-
-static int json_get_utf8_char_len(unsigned char ch) {
- if ((ch & 0x80) == 0) return 1;
- switch (ch & 0xf0) {
- case 0xf0:
- return 4;
- case 0xe0:
- return 3;
- default:
- return 2;
- }
-}
-
-/* string = '"' { quoted_printable_chars } '"' */
-static int json_parse_string(struct frozen *f) {
- int n, ch = 0, len = 0;
- TRY(json_test_and_skip(f, '"'));
- {
- SET_STATE(f, f->cur, "", 0);
- for (; f->cur < f->end; f->cur += len) {
- ch = *(unsigned char *) f->cur;
- len = json_get_utf8_char_len((unsigned char) ch);
- EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */
- EXPECT(len <= json_left(f), JSON_STRING_INCOMPLETE);
- if (ch == '\\') {
- EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n);
- len += n;
- } else if (ch == '"') {
- json_truncate_path(f, fstate.path_len);
- CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr);
- f->cur++;
- break;
- };
- }
- }
- return ch == '"' ? 0 : JSON_STRING_INCOMPLETE;
-}
-
-/* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
-static int json_parse_number(struct frozen *f) {
- int ch = json_cur(f);
- SET_STATE(f, f->cur, "", 0);
- if (ch == '-') f->cur++;
- EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
- if (f->cur + 1 < f->end && f->cur[0] == '0' && f->cur[1] == 'x') {
- f->cur += 2;
- EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
- EXPECT(json_isxdigit(f->cur[0]), JSON_STRING_INVALID);
- while (f->cur < f->end && json_isxdigit(f->cur[0])) f->cur++;
- } else {
- EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID);
- while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++;
- if (f->cur < f->end && f->cur[0] == '.') {
- f->cur++;
- EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
- EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID);
- while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++;
- }
- if (f->cur < f->end && (f->cur[0] == 'e' || f->cur[0] == 'E')) {
- f->cur++;
- EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
- if ((f->cur[0] == '+' || f->cur[0] == '-')) f->cur++;
- EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
- EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID);
- while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++;
- }
- }
- json_truncate_path(f, fstate.path_len);
- CALL_BACK(f, JSON_TYPE_NUMBER, fstate.ptr, f->cur - fstate.ptr);
- return 0;
-}
-
-#if JSON_ENABLE_ARRAY
-/* array = '[' [ value { ',' value } ] ']' */
-static int json_parse_array(struct frozen *f) {
- int i = 0, current_path_len;
- char buf[20];
- CALL_BACK(f, JSON_TYPE_ARRAY_START, NULL, 0);
- TRY(json_test_and_skip(f, '['));
- {
- {
- SET_STATE(f, f->cur - 1, "", 0);
- while (json_cur(f) != ']') {
- snprintf(buf, sizeof(buf), "[%d]", i);
- i++;
- current_path_len = json_append_to_path(f, buf, strlen(buf));
- f->cur_name =
- f->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/;
- f->cur_name_len = strlen(buf) - 2 /*braces*/;
- TRY(json_parse_value(f));
- json_truncate_path(f, current_path_len);
- if (json_cur(f) == ',') f->cur++;
- }
- TRY(json_test_and_skip(f, ']'));
- json_truncate_path(f, fstate.path_len);
- CALL_BACK(f, JSON_TYPE_ARRAY_END, fstate.ptr, f->cur - fstate.ptr);
- }
- }
- return 0;
-}
-#endif /* JSON_ENABLE_ARRAY */
-
-static int json_expect(struct frozen *f, const char *s, int len,
- enum json_token_type tok_type) {
- int i, n = json_left(f);
- SET_STATE(f, f->cur, "", 0);
- for (i = 0; i < len; i++) {
- if (i >= n) return JSON_STRING_INCOMPLETE;
- if (f->cur[i] != s[i]) return JSON_STRING_INVALID;
- }
- f->cur += len;
- json_truncate_path(f, fstate.path_len);
-
- CALL_BACK(f, tok_type, fstate.ptr, f->cur - fstate.ptr);
-
- return 0;
-}
-
-/* value = 'null' | 'true' | 'false' | number | string | array | object */
-static int json_parse_value(struct frozen *f) {
- int ch = json_cur(f);
-
- switch (ch) {
- case '"':
- TRY(json_parse_string(f));
- break;
- case '{':
- TRY(json_parse_object(f));
- break;
-#if JSON_ENABLE_ARRAY
- case '[':
- TRY(json_parse_array(f));
- break;
-#endif
- case 'n':
- TRY(json_expect(f, "null", 4, JSON_TYPE_NULL));
- break;
- case 't':
- TRY(json_expect(f, "true", 4, JSON_TYPE_TRUE));
- break;
- case 'f':
- TRY(json_expect(f, "false", 5, JSON_TYPE_FALSE));
- break;
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- TRY(json_parse_number(f));
- break;
- default:
- return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
- }
-
- return 0;
-}
-
-/* key = identifier | string */
-static int json_parse_key(struct frozen *f) {
- int ch = json_cur(f);
- if (json_isalpha(ch)) {
- TRY(json_parse_identifier(f));
- } else if (ch == '"') {
- TRY(json_parse_string(f));
- } else {
- return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
- }
- return 0;
-}
-
-/* pair = key ':' value */
-static int json_parse_pair(struct frozen *f) {
- int current_path_len;
- const char *tok;
- json_skip_whitespaces(f);
- tok = f->cur;
- TRY(json_parse_key(f));
- {
- f->cur_name = *tok == '"' ? tok + 1 : tok;
- f->cur_name_len = *tok == '"' ? f->cur - tok - 2 : f->cur - tok;
- current_path_len = json_append_to_path(f, f->cur_name, f->cur_name_len);
- }
- TRY(json_test_and_skip(f, ':'));
- TRY(json_parse_value(f));
- json_truncate_path(f, current_path_len);
- return 0;
-}
-
-/* object = '{' pair { ',' pair } '}' */
-static int json_parse_object(struct frozen *f) {
- CALL_BACK(f, JSON_TYPE_OBJECT_START, NULL, 0);
- TRY(json_test_and_skip(f, '{'));
- {
- SET_STATE(f, f->cur - 1, ".", 1);
- while (json_cur(f) != '}') {
- TRY(json_parse_pair(f));
- if (json_cur(f) == ',') f->cur++;
- }
- TRY(json_test_and_skip(f, '}'));
- json_truncate_path(f, fstate.path_len);
- CALL_BACK(f, JSON_TYPE_OBJECT_END, fstate.ptr, f->cur - fstate.ptr);
- }
- return 0;
-}
-
-static int json_doit(struct frozen *f) {
- if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID;
- if (f->end == f->cur) return JSON_STRING_INCOMPLETE;
- return json_parse_value(f);
-}
-
-int json_escape(struct json_out *out, const char *p, size_t len) WEAK;
-int json_escape(struct json_out *out, const char *str, size_t str_len) {
- size_t i, cl, n = 0;
- const char *hex_digits = "0123456789abcdef";
- const char *specials = "btnvfr";
-
- for (i = 0; i < str_len; i++) {
- unsigned char ch = ((unsigned char *) str)[i];
- if (ch == '"' || ch == '\\') {
- n += out->printer(out, "\\", 1);
- n += out->printer(out, str + i, 1);
- } else if (ch >= '\b' && ch <= '\r') {
- n += out->printer(out, "\\", 1);
- n += out->printer(out, &specials[ch - '\b'], 1);
- } else if (c_isprint(ch)) {
- n += out->printer(out, str + i, 1);
- } else if ((cl = json_get_utf8_char_len(ch)) == 1) {
- n += out->printer(out, "\\u00", 4);
- n += out->printer(out, &hex_digits[(ch >> 4) % 0xf], 1);
- n += out->printer(out, &hex_digits[ch % 0xf], 1);
- } else {
- n += out->printer(out, str + i, cl);
- i += cl - 1;
- }
- }
-
- return n;
-}
-
-int json_printer_buf(struct json_out *out, const char *buf, size_t len) WEAK;
-int json_printer_buf(struct json_out *out, const char *buf, size_t len) {
- size_t avail = out->u.buf.size - out->u.buf.len;
- size_t n = len < avail ? len : avail;
- memcpy(out->u.buf.buf + out->u.buf.len, buf, n);
- out->u.buf.len += n;
- if (out->u.buf.size > 0) {
- size_t idx = out->u.buf.len;
- if (idx >= out->u.buf.size) idx = out->u.buf.size - 1;
- out->u.buf.buf[idx] = '\0';
- }
- return len;
-}
-
-int json_printer_file(struct json_out *out, const char *buf, size_t len) WEAK;
-int json_printer_file(struct json_out *out, const char *buf, size_t len) {
- return fwrite(buf, 1, len, out->u.fp);
-}
-
-#if JSON_ENABLE_BASE64
-static int b64idx(int c) {
- if (c < 26) {
- return c + 'A';
- } else if (c < 52) {
- return c - 26 + 'a';
- } else if (c < 62) {
- return c - 52 + '0';
- } else {
- return c == 62 ? '+' : '/';
- }
-}
-
-static int b64rev(int c) {
- if (c >= 'A' && c <= 'Z') {
- return c - 'A';
- } else if (c >= 'a' && c <= 'z') {
- return c + 26 - 'a';
- } else if (c >= '0' && c <= '9') {
- return c + 52 - '0';
- } else if (c == '+') {
- return 62;
- } else if (c == '/') {
- return 63;
- } else {
- return 64;
- }
-}
-
-static int b64enc(struct json_out *out, const unsigned char *p, int n) {
- char buf[4];
- int i, len = 0;
- for (i = 0; i < n; i += 3) {
- int a = p[i], b = i + 1 < n ? p[i + 1] : 0, c = i + 2 < n ? p[i + 2] : 0;
- buf[0] = b64idx(a >> 2);
- buf[1] = b64idx((a & 3) << 4 | (b >> 4));
- buf[2] = b64idx((b & 15) << 2 | (c >> 6));
- buf[3] = b64idx(c & 63);
- if (i + 1 >= n) buf[2] = '=';
- if (i + 2 >= n) buf[3] = '=';
- len += out->printer(out, buf, sizeof(buf));
- }
- return len;
-}
-
-static int b64dec(const char *src, int n, char *dst) {
- const char *end = src + n;
- int len = 0;
- while (src + 3 < end) {
- int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]),
- d = b64rev(src[3]);
- dst[len++] = (a << 2) | (b >> 4);
- if (src[2] != '=') {
- dst[len++] = (b << 4) | (c >> 2);
- if (src[3] != '=') {
- dst[len++] = (c << 6) | d;
- }
- }
- src += 4;
- }
- return len;
-}
-#endif /* JSON_ENABLE_BASE64 */
-
-static unsigned char hexdec(const char *s) {
-#define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W')
- int a = c_tolower(*(const unsigned char *) s);
- int b = c_tolower(*(const unsigned char *)(s + 1));
- return (HEXTOI(a) << 4) | HEXTOI(b);
-}
-
-int json_vprintf(struct json_out *out, const char *fmt, va_list xap) WEAK;
-int json_vprintf(struct json_out *out, const char *fmt, va_list xap) {
- int len = 0;
- const char *quote = "\"", *null = "null";
- va_list ap;
- va_copy(ap, xap);
-
- while (*fmt != '\0') {
- if (strchr(":, \r\n\t[]{}\"", *fmt) != NULL) {
- len += out->printer(out, fmt, 1);
- fmt++;
- } else if (fmt[0] == '%') {
- char buf[21];
- size_t skip = 2;
-
- if (fmt[1] == 'l' && fmt[2] == 'l' && (fmt[3] == 'd' || fmt[3] == 'u')) {
- int64_t val = va_arg(ap, int64_t);
- const char *fmt2 = fmt[3] == 'u' ? "%" UINT64_FMT : "%" INT64_FMT;
- snprintf(buf, sizeof(buf), fmt2, val);
- len += out->printer(out, buf, strlen(buf));
- skip += 2;
- } else if (fmt[1] == 'z' && fmt[2] == 'u') {
- size_t val = va_arg(ap, size_t);
- snprintf(buf, sizeof(buf), "%lu", (unsigned long) val);
- len += out->printer(out, buf, strlen(buf));
- skip += 1;
- } else if (fmt[1] == 'M') {
- json_printf_callback_t f = va_arg(ap, json_printf_callback_t);
- len += f(out, &ap);
- } else if (fmt[1] == 'B') {
- int val = va_arg(ap, int);
- const char *str = val ? "true" : "false";
- len += out->printer(out, str, strlen(str));
- } else if (fmt[1] == 'H') {
-#if JSON_ENABLE_HEX
- const char *hex = "0123456789abcdef";
- int i, n = va_arg(ap, int);
- const unsigned char *p = va_arg(ap, const unsigned char *);
- len += out->printer(out, quote, 1);
- for (i = 0; i < n; i++) {
- len += out->printer(out, &hex[(p[i] >> 4) & 0xf], 1);
- len += out->printer(out, &hex[p[i] & 0xf], 1);
- }
- len += out->printer(out, quote, 1);
-#endif /* JSON_ENABLE_HEX */
- } else if (fmt[1] == 'V') {
-#if JSON_ENABLE_BASE64
- const unsigned char *p = va_arg(ap, const unsigned char *);
- int n = va_arg(ap, int);
- len += out->printer(out, quote, 1);
- len += b64enc(out, p, n);
- len += out->printer(out, quote, 1);
-#endif /* JSON_ENABLE_BASE64 */
- } else if (fmt[1] == 'Q' ||
- (fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 'Q')) {
- size_t l = 0;
- const char *p;
-
- if (fmt[1] == '.') {
- l = (size_t) va_arg(ap, int);
- skip += 2;
- }
- p = va_arg(ap, char *);
-
- if (p == NULL) {
- len += out->printer(out, null, 4);
- } else {
- if (fmt[1] == 'Q') {
- l = strlen(p);
- }
- len += out->printer(out, quote, 1);
- len += json_escape(out, p, l);
- len += out->printer(out, quote, 1);
- }
- } else {
- /*
- * we delegate printing to the system printf.
- * The goal here is to delegate all modifiers parsing to the system
- * printf, as you can see below we still have to parse the format
- * types.
- *
- * Currently, %s with strings longer than 20 chars will require
- * double-buffering (an auxiliary buffer will be allocated from heap).
- * TODO(dfrank): reimplement %s and %.*s in order to avoid that.
- */
-
- const char *end_of_format_specifier = "sdfFeEgGlhuIcx.*-0123456789";
- int n = strspn(fmt + 1, end_of_format_specifier);
- char *pbuf = buf;
- int need_len, size = sizeof(buf);
- char fmt2[20];
- va_list ap_copy;
- strncpy(fmt2, fmt,
- n + 1 > (int) sizeof(fmt2) ? sizeof(fmt2) : (size_t) n + 1);
- fmt2[n + 1] = '\0';
-
- va_copy(ap_copy, ap);
- need_len = vsnprintf(pbuf, size, fmt2, ap_copy);
- va_end(ap_copy);
-
- if (need_len < 0) {
- /*
- * Windows & eCos vsnprintf implementation return -1 on overflow
- * instead of needed size.
- */
- pbuf = NULL;
- while (need_len < 0) {
- free(pbuf);
- size *= 2;
- if ((pbuf = (char *) malloc(size)) == NULL) break;
- va_copy(ap_copy, ap);
- need_len = vsnprintf(pbuf, size, fmt2, ap_copy);
- va_end(ap_copy);
- }
- } else if (need_len >= (int) sizeof(buf)) {
- /*
- * resulting string doesn't fit into a stack-allocated buffer `buf`,
- * so we need to allocate a new buffer from heap and use it
- */
- if ((pbuf = (char *) malloc(need_len + 1)) != NULL) {
- va_copy(ap_copy, ap);
- vsnprintf(pbuf, need_len + 1, fmt2, ap_copy);
- va_end(ap_copy);
- }
- }
- if (pbuf == NULL) {
- buf[0] = '\0';
- pbuf = buf;
- }
-
- /*
- * however we need to parse the type ourselves in order to advance
- * the va_list by the correct amount; there is no portable way to
- * inherit the advancement made by vprintf.
- * 32-bit (linux or windows) passes va_list by value.
- */
- if ((n + 1 == strlen("%" PRId64) && strcmp(fmt2, "%" PRId64) == 0) ||
- (n + 1 == strlen("%" PRIu64) && strcmp(fmt2, "%" PRIu64) == 0)) {
- (void) va_arg(ap, int64_t);
- } else if (strcmp(fmt2, "%.*s") == 0) {
- (void) va_arg(ap, int);
- (void) va_arg(ap, char *);
- } else {
- switch (fmt2[n]) {
- case 'u':
- case 'd':
- (void) va_arg(ap, int);
- break;
- case 'g':
- case 'f':
- (void) va_arg(ap, double);
- break;
- case 'p':
- (void) va_arg(ap, void *);
- break;
- default:
- /* many types are promoted to int */
- (void) va_arg(ap, int);
- }
- }
-
- len += out->printer(out, pbuf, strlen(pbuf));
- skip = n + 1;
-
- /* If buffer was allocated from heap, free it */
- if (pbuf != buf) {
- free(pbuf);
- pbuf = NULL;
- }
- }
- fmt += skip;
- } else if (*fmt == '_' || json_isalpha(*fmt)) {
- len += out->printer(out, quote, 1);
- while (*fmt == '_' || json_isalpha(*fmt) || json_isdigit(*fmt)) {
- len += out->printer(out, fmt, 1);
- fmt++;
- }
- len += out->printer(out, quote, 1);
- } else {
- len += out->printer(out, fmt, 1);
- fmt++;
- }
- }
- va_end(ap);
-
- return len;
-}
-
-int json_printf(struct json_out *out, const char *fmt, ...) WEAK;
-int json_printf(struct json_out *out, const char *fmt, ...) {
- int n;
- va_list ap;
- va_start(ap, fmt);
- n = json_vprintf(out, fmt, ap);
- va_end(ap);
- return n;
-}
-
-int json_printf_array(struct json_out *out, va_list *ap) WEAK;
-int json_printf_array(struct json_out *out, va_list *ap) {
- int len = 0;
- char *arr = va_arg(*ap, char *);
- size_t i, arr_size = va_arg(*ap, size_t);
- size_t elem_size = va_arg(*ap, size_t);
- const char *fmt = va_arg(*ap, char *);
- len += json_printf(out, "[", 1);
- for (i = 0; arr != NULL && i < arr_size / elem_size; i++) {
- union {
- int64_t i;
- double d;
- } val;
- memcpy(&val, arr + i * elem_size,
- elem_size > sizeof(val) ? sizeof(val) : elem_size);
- if (i > 0) len += json_printf(out, ", ");
- if (strpbrk(fmt, "efg") != NULL) {
- len += json_printf(out, fmt, val.d);
- } else {
- len += json_printf(out, fmt, val.i);
- }
- }
- len += json_printf(out, "]", 1);
- return len;
-}
-
-#ifdef _WIN32
-int cs_win_vsnprintf(char *str, size_t size, const char *format,
- va_list ap) WEAK;
-int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
- int res = _vsnprintf(str, size, format, ap);
- va_end(ap);
- if (res >= size) {
- str[size - 1] = '\0';
- }
- return res;
-}
-
-int cs_win_snprintf(char *str, size_t size, const char *format, ...) WEAK;
-int cs_win_snprintf(char *str, size_t size, const char *format, ...) {
- int res;
- va_list ap;
- va_start(ap, format);
- res = vsnprintf(str, size, format, ap);
- va_end(ap);
- return res;
-}
-#endif /* _WIN32 */
-
-int json_walk(const char *json_string, int json_string_length,
- json_walk_callback_t callback, void *callback_data) WEAK;
-int json_walk(const char *json_string, int json_string_length,
- json_walk_callback_t callback, void *callback_data) {
- struct frozen frozen;
-
- memset(&frozen, 0, sizeof(frozen));
- frozen.end = json_string + json_string_length;
- frozen.cur = json_string;
- frozen.callback_data = callback_data;
- frozen.callback = callback;
-
- TRY(json_doit(&frozen));
-
- return frozen.cur - json_string;
-}
-
-struct scan_array_info {
- int found;
- char path[JSON_MAX_PATH_LEN];
- struct json_token *token;
-};
-
-static void json_scanf_array_elem_cb(void *callback_data, const char *name,
- size_t name_len, const char *path,
- const struct json_token *token) {
- struct scan_array_info *info = (struct scan_array_info *) callback_data;
-
- (void) name;
- (void) name_len;
-
- if (strcmp(path, info->path) == 0) {
- *info->token = *token;
- info->found = 1;
- }
-}
-
-int json_scanf_array_elem(const char *s, int len, const char *path, int idx,
- struct json_token *token) WEAK;
-int json_scanf_array_elem(const char *s, int len, const char *path, int idx,
- struct json_token *token) {
- struct scan_array_info info;
- info.token = token;
- info.found = 0;
- memset(token, 0, sizeof(*token));
- snprintf(info.path, sizeof(info.path), "%s[%d]", path, idx);
- json_walk(s, len, json_scanf_array_elem_cb, &info);
- return info.found ? token->len : -1;
-}
-
-struct json_scanf_info {
- int num_conversions;
- char *path;
- const char *fmt;
- void *target;
- void *user_data;
- int type;
-};
-
-int json_unescape(const char *src, int slen, char *dst, int dlen) WEAK;
-int json_unescape(const char *src, int slen, char *dst, int dlen) {
- char *send = (char *) src + slen, *dend = dst + dlen, *orig_dst = dst, *p;
- const char *esc1 = "\"\\/bfnrt", *esc2 = "\"\\/\b\f\n\r\t";
-
- while (src < send) {
- if (*src == '\\') {
- if (++src >= send) return JSON_STRING_INCOMPLETE;
- if (*src == 'u') {
- if (send - src < 5) return JSON_STRING_INCOMPLETE;
- /* Here we go: this is a \u.... escape. Process simple one-byte chars */
- if (src[1] == '0' && src[2] == '0') {
- /* This is \u00xx character from the ASCII range */
- if (dst < dend) *dst = hexdec(src + 3);
- src += 4;
- } else {
- /* Complex \uXXXX escapes drag utf8 lib... Do it at some stage */
- return JSON_STRING_INVALID;
- }
- } else if ((p = (char *) strchr(esc1, *src)) != NULL) {
- if (dst < dend) *dst = esc2[p - esc1];
- } else {
- return JSON_STRING_INVALID;
- }
- } else {
- if (dst < dend) *dst = *src;
- }
- dst++;
- src++;
- }
-
- return dst - orig_dst;
-}
-
-static void json_scanf_cb(void *callback_data, const char *name,
- size_t name_len, const char *path,
- const struct json_token *token) {
- struct json_scanf_info *info = (struct json_scanf_info *) callback_data;
- char buf[32]; /* Must be enough to hold numbers */
-
- (void) name;
- (void) name_len;
-
- if (token->ptr == NULL) {
- /*
- * We're not interested here in the events for which we have no value;
- * namely, JSON_TYPE_OBJECT_START and JSON_TYPE_ARRAY_START
- */
- return;
- }
-
- if (strcmp(path, info->path) != 0) {
- /* It's not the path we're looking for, so, just ignore this callback */
- return;
- }
-
- switch (info->type) {
- case 'B':
- info->num_conversions++;
- switch (sizeof(bool)) {
- case sizeof(char):
- *(char *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0);
- break;
- case sizeof(int):
- *(int *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0);
- break;
- default:
- /* should never be here */
- abort();
- }
- break;
- case 'M': {
- union {
- void *p;
- json_scanner_t f;
- } u = {info->target};
- info->num_conversions++;
- u.f(token->ptr, token->len, info->user_data);
- break;
- }
- case 'Q': {
- char **dst = (char **) info->target;
- if (token->type == JSON_TYPE_NULL) {
- *dst = NULL;
- } else {
- int unescaped_len = json_unescape(token->ptr, token->len, NULL, 0);
- if (unescaped_len >= 0 &&
- (*dst = (char *) malloc(unescaped_len + 1)) != NULL) {
- info->num_conversions++;
- if (json_unescape(token->ptr, token->len, *dst, unescaped_len) ==
- unescaped_len) {
- (*dst)[unescaped_len] = '\0';
- } else {
- free(*dst);
- *dst = NULL;
- }
- }
- }
- break;
- }
- case 'H': {
-#if JSON_ENABLE_HEX
- char **dst = (char **) info->user_data;
- int i, len = token->len / 2;
- *(int *) info->target = len;
- if ((*dst = (char *) malloc(len + 1)) != NULL) {
- for (i = 0; i < len; i++) {
- (*dst)[i] = hexdec(token->ptr + 2 * i);
- }
- (*dst)[len] = '\0';
- info->num_conversions++;
- }
-#endif /* JSON_ENABLE_HEX */
- break;
- }
- case 'V': {
-#if JSON_ENABLE_BASE64
- char **dst = (char **) info->target;
- int len = token->len * 4 / 3 + 2;
- if ((*dst = (char *) malloc(len + 1)) != NULL) {
- int n = b64dec(token->ptr, token->len, *dst);
- (*dst)[n] = '\0';
- *(int *) info->user_data = n;
- info->num_conversions++;
- }
-#endif /* JSON_ENABLE_BASE64 */
- break;
- }
- case 'T':
- info->num_conversions++;
- *(struct json_token *) info->target = *token;
- break;
- default:
- if (token->len >= (int) sizeof(buf)) break;
- /* Before converting, copy into tmp buffer in order to 0-terminate it */
- memcpy(buf, token->ptr, token->len);
- buf[token->len] = '\0';
- /* NB: Use of base 0 for %d, %ld, %u and %lu is intentional. */
- if (info->fmt[1] == 'd' || (info->fmt[1] == 'l' && info->fmt[2] == 'd') ||
- info->fmt[1] == 'i') {
- char *endptr = NULL;
- long r = strtol(buf, &endptr, 0 /* base */);
- if (*endptr == '\0') {
- if (info->fmt[1] == 'l') {
- *((long *) info->target) = r;
- } else {
- *((int *) info->target) = (int) r;
- }
- info->num_conversions++;
- }
- } else if (info->fmt[1] == 'u' ||
- (info->fmt[1] == 'l' && info->fmt[2] == 'u')) {
- char *endptr = NULL;
- unsigned long r = strtoul(buf, &endptr, 0 /* base */);
- if (*endptr == '\0') {
- if (info->fmt[1] == 'l') {
- *((unsigned long *) info->target) = r;
- } else {
- *((unsigned int *) info->target) = (unsigned int) r;
- }
- info->num_conversions++;
- }
- } else {
-#if !JSON_MINIMAL
- info->num_conversions += sscanf(buf, info->fmt, info->target);
-#endif
- }
- break;
- }
-}
-
-int json_vscanf(const char *str, int len, const char *fmt, va_list ap) WEAK;
-int json_vscanf(const char *str, int len, const char *fmt, va_list ap) {
- char path[JSON_MAX_PATH_LEN] = "", fmtbuf[20];
- int i = 0;
- char *p = NULL;
- struct json_scanf_info info = {0, path, fmtbuf, NULL, NULL, 0};
-
- while (fmt[i] != '\0') {
- if (fmt[i] == '{') {
- strcat(path, ".");
- i++;
- } else if (fmt[i] == '}') {
- if ((p = strrchr(path, '.')) != NULL) * p = '\0';
- i++;
- } else if (fmt[i] == '%') {
- info.target = va_arg(ap, void *);
- info.type = fmt[i + 1];
- switch (fmt[i + 1]) {
- case 'M':
- case 'V':
- case 'H':
- info.user_data = va_arg(ap, void *);
- /* FALLTHROUGH */
- case 'B':
- case 'Q':
- case 'T':
- i += 2;
- break;
- default: {
- const char *delims = ", \t\r\n]}";
- int conv_len = strcspn(fmt + i + 1, delims) + 1;
- memcpy(fmtbuf, fmt + i, conv_len);
- fmtbuf[conv_len] = '\0';
- i += conv_len;
- i += strspn(fmt + i, delims);
- break;
- }
- }
- json_walk(str, len, json_scanf_cb, &info);
- } else if (json_isalpha(fmt[i]) || json_get_utf8_char_len(fmt[i]) > 1) {
- char *pe;
- const char *delims = ": \r\n\t";
- int key_len = strcspn(&fmt[i], delims);
- if ((p = strrchr(path, '.')) != NULL) p[1] = '\0';
- pe = path + strlen(path);
- memcpy(pe, fmt + i, key_len);
- pe[key_len] = '\0';
- i += key_len + strspn(fmt + i + key_len, delims);
- } else {
- i++;
- }
- }
- return info.num_conversions;
-}
-
-int json_scanf(const char *str, int len, const char *fmt, ...) WEAK;
-int json_scanf(const char *str, int len, const char *fmt, ...) {
- int result;
- va_list ap;
- va_start(ap, fmt);
- result = json_vscanf(str, len, fmt, ap);
- va_end(ap);
- return result;
-}
-
-int json_vfprintf(const char *file_name, const char *fmt, va_list ap) WEAK;
-int json_vfprintf(const char *file_name, const char *fmt, va_list ap) {
- int res = -1;
- FILE *fp = fopen(file_name, "wb");
- if (fp != NULL) {
- struct json_out out = JSON_OUT_FILE(fp);
- res = json_vprintf(&out, fmt, ap);
- fputc('\n', fp);
- fclose(fp);
- }
- return res;
-}
-
-int json_fprintf(const char *file_name, const char *fmt, ...) WEAK;
-int json_fprintf(const char *file_name, const char *fmt, ...) {
- int result;
- va_list ap;
- va_start(ap, fmt);
- result = json_vfprintf(file_name, fmt, ap);
- va_end(ap);
- return result;
-}
-
-char *json_fread(const char *path) WEAK;
-char *json_fread(const char *path) {
- FILE *fp;
- char *data = NULL;
- if ((fp = fopen(path, "rb")) == NULL) {
- } else if (fseek(fp, 0, SEEK_END) != 0) {
- fclose(fp);
- } else {
- long size = ftell(fp);
- if (size > 0 && (data = (char *) malloc(size + 1)) != NULL) {
- fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */
- if (fread(data, 1, size, fp) != (size_t) size) {
- free(data);
- data = NULL;
- } else {
- data[size] = '\0';
- }
- }
- fclose(fp);
- }
- return data;
-}
-
-struct json_setf_data {
- const char *json_path;
- const char *base; /* Pointer to the source JSON string */
- int matched; /* Matched part of json_path */
- int pos; /* Offset of the mutated value begin */
- int end; /* Offset of the mutated value end */
- int prev; /* Offset of the previous token end */
-};
-
-static int get_matched_prefix_len(const char *s1, const char *s2) {
- int i = 0;
- while (s1[i] && s2[i] && s1[i] == s2[i]) i++;
- return i;
-}
-
-static void json_vsetf_cb(void *userdata, const char *name, size_t name_len,
- const char *path, const struct json_token *t) {
- struct json_setf_data *data = (struct json_setf_data *) userdata;
- int off, len = get_matched_prefix_len(path, data->json_path);
- if (t->ptr == NULL) return;
- off = t->ptr - data->base;
- if (len > data->matched) data->matched = len;
-
- /*
- * If there is no exact path match, set the mutation position to tbe end
- * of the object or array
- */
- if (len < data->matched && data->pos == 0 &&
- (t->type == JSON_TYPE_OBJECT_END || t->type == JSON_TYPE_ARRAY_END)) {
- data->pos = data->end = data->prev;
- }
-
- /* Exact path match. Set mutation position to the value of this token */
- if (strcmp(path, data->json_path) == 0 && t->type != JSON_TYPE_OBJECT_START &&
- t->type != JSON_TYPE_ARRAY_START) {
- data->pos = off;
- data->end = off + t->len;
- }
-
- /*
- * For deletion, we need to know where the previous value ends, because
- * we don't know where matched value key starts.
- * When the mutation position is not yet set, remember each value end.
- * When the mutation position is already set, but it is at the beginning
- * of the object/array, we catch the end of the object/array and see
- * whether the object/array start is closer then previously stored prev.
- */
- if (data->pos == 0) {
- data->prev = off + t->len; /* pos is not yet set */
- } else if ((t->ptr[0] == '[' || t->ptr[0] == '{') && off + 1 < data->pos &&
- off + 1 > data->prev) {
- data->prev = off + 1;
- }
- (void) name;
- (void) name_len;
-}
-
-int json_vsetf(const char *s, int len, struct json_out *out,
- const char *json_path, const char *json_fmt, va_list ap) WEAK;
-int json_vsetf(const char *s, int len, struct json_out *out,
- const char *json_path, const char *json_fmt, va_list ap) {
- struct json_setf_data data;
- memset(&data, 0, sizeof(data));
- data.json_path = json_path;
- data.base = s;
- data.end = len;
- json_walk(s, len, json_vsetf_cb, &data);
- if (json_fmt == NULL) {
- /* Deletion codepath */
- json_printf(out, "%.*s", data.prev, s);
- /* Trim comma after the value that begins at object/array start */
- if (s[data.prev - 1] == '{' || s[data.prev - 1] == '[') {
- int i = data.end;
- while (i < len && json_isspace(s[i])) i++;
- if (s[i] == ',') data.end = i + 1; /* Point after comma */
- }
- json_printf(out, "%.*s", len - data.end, s + data.end);
- } else {
- /* Modification codepath */
- int n, off = data.matched, depth = 0;
-
- /* Print the unchanged beginning */
- json_printf(out, "%.*s", data.pos, s);
-
- /* Add missing keys */
- while ((n = strcspn(&json_path[off], ".[")) > 0) {
- if (s[data.prev - 1] != '{' && s[data.prev - 1] != '[' && depth == 0) {
- json_printf(out, ",");
- }
- if (off > 0 && json_path[off - 1] != '.') break;
- json_printf(out, "%.*Q:", n, json_path + off);
- off += n;
- if (json_path[off] != '\0') {
- json_printf(out, "%c", json_path[off] == '.' ? '{' : '[');
- depth++;
- off++;
- }
- }
- /* Print the new value */
- json_vprintf(out, json_fmt, ap);
-
- /* Close brackets/braces of the added missing keys */
- for (; off > data.matched; off--) {
- int ch = json_path[off];
- const char *p = ch == '.' ? "}" : ch == '[' ? "]" : "";
- json_printf(out, "%s", p);
- }
-
- /* Print the rest of the unchanged string */
- json_printf(out, "%.*s", len - data.end, s + data.end);
- }
- return data.end > data.pos ? 1 : 0;
-}
-
-int json_setf(const char *s, int len, struct json_out *out,
- const char *json_path, const char *json_fmt, ...) WEAK;
-int json_setf(const char *s, int len, struct json_out *out,
- const char *json_path, const char *json_fmt, ...) {
- int result;
- va_list ap;
- va_start(ap, json_fmt);
- result = json_vsetf(s, len, out, json_path, json_fmt, ap);
- va_end(ap);
- return result;
-}
-
-struct prettify_data {
- struct json_out *out;
- int level;
- int last_token;
-};
-
-static void indent(struct json_out *out, int level) {
- while (level-- > 0) out->printer(out, " ", 2);
-}
-
-static void print_key(struct prettify_data *pd, const char *path,
- const char *name, int name_len) {
- if (pd->last_token != JSON_TYPE_INVALID &&
- pd->last_token != JSON_TYPE_ARRAY_START &&
- pd->last_token != JSON_TYPE_OBJECT_START) {
- pd->out->printer(pd->out, ",", 1);
- }
- if (path[0] != '\0') pd->out->printer(pd->out, "\n", 1);
- indent(pd->out, pd->level);
- if (path[0] != '\0' && path[strlen(path) - 1] != ']') {
- pd->out->printer(pd->out, "\"", 1);
- pd->out->printer(pd->out, name, (int) name_len);
- pd->out->printer(pd->out, "\"", 1);
- pd->out->printer(pd->out, ": ", 2);
- }
-}
-
-static void prettify_cb(void *userdata, const char *name, size_t name_len,
- const char *path, const struct json_token *t) {
- struct prettify_data *pd = (struct prettify_data *) userdata;
- switch (t->type) {
- case JSON_TYPE_OBJECT_START:
- case JSON_TYPE_ARRAY_START:
- print_key(pd, path, name, name_len);
- pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_START ? "[" : "{",
- 1);
- pd->level++;
- break;
- case JSON_TYPE_OBJECT_END:
- case JSON_TYPE_ARRAY_END:
- pd->level--;
- if (pd->last_token != JSON_TYPE_INVALID &&
- pd->last_token != JSON_TYPE_ARRAY_START &&
- pd->last_token != JSON_TYPE_OBJECT_START) {
- pd->out->printer(pd->out, "\n", 1);
- indent(pd->out, pd->level);
- }
- pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_END ? "]" : "}", 1);
- break;
- case JSON_TYPE_NUMBER:
- case JSON_TYPE_NULL:
- case JSON_TYPE_TRUE:
- case JSON_TYPE_FALSE:
- case JSON_TYPE_STRING:
- print_key(pd, path, name, name_len);
- if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1);
- pd->out->printer(pd->out, t->ptr, t->len);
- if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1);
- break;
- default:
- break;
- }
- pd->last_token = t->type;
-}
-
-int json_prettify(const char *s, int len, struct json_out *out) WEAK;
-int json_prettify(const char *s, int len, struct json_out *out) {
- struct prettify_data pd = {out, 0, JSON_TYPE_INVALID};
- return json_walk(s, len, prettify_cb, &pd);
-}
-
-int json_prettify_file(const char *file_name) WEAK;
-int json_prettify_file(const char *file_name) {
- int res = -1;
- char *s = json_fread(file_name);
- FILE *fp;
- if (s != NULL && (fp = fopen(file_name, "wb")) != NULL) {
- struct json_out out = JSON_OUT_FILE(fp);
- res = json_prettify(s, strlen(s), &out);
- if (res < 0) {
- /* On error, restore the old content */
- fclose(fp);
- fp = fopen(file_name, "wb");
- fseek(fp, 0, SEEK_SET);
- fwrite(s, 1, strlen(s), fp);
- } else {
- fputc('\n', fp);
- }
- fclose(fp);
- }
- free(s);
- return res;
-}
-
-struct next_data {
- void *handle; // Passed handle. Changed if a next entry is found
- const char *path; // Path to the iterated object/array
- int path_len; // Path length - optimisation
- int found; // Non-0 if found the next entry
- struct json_token *key; // Object's key
- struct json_token *val; // Object's value
- int *idx; // Array index
-};
-
-static void next_set_key(struct next_data *d, const char *name, int name_len,
- int is_array) {
- if (is_array) {
- /* Array. Set index and reset key */
- if (d->key != NULL) {
- d->key->len = 0;
- d->key->ptr = NULL;
- }
- if (d->idx != NULL) *d->idx = atoi(name);
- } else {
- /* Object. Set key and make index -1 */
- if (d->key != NULL) {
- d->key->ptr = name;
- d->key->len = name_len;
- }
- if (d->idx != NULL) *d->idx = -1;
- }
-}
-
-static void json_next_cb(void *userdata, const char *name, size_t name_len,
- const char *path, const struct json_token *t) {
- struct next_data *d = (struct next_data *) userdata;
- const char *p = path + d->path_len;
- if (d->found) return;
- if (d->path_len >= (int) strlen(path)) return;
- if (strncmp(d->path, path, d->path_len) != 0) return;
- if (strchr(p + 1, '.') != NULL) return; /* More nested objects - skip */
- if (strchr(p + 1, '[') != NULL) return; /* Ditto for arrays */
- // {OBJECT,ARRAY}_END types do not pass name, _START does. Save key.
- if (t->type == JSON_TYPE_OBJECT_START || t->type == JSON_TYPE_ARRAY_START) {
- next_set_key(d, name, name_len, p[0] == '[');
- } else if (d->handle == NULL || d->handle < (void *) t->ptr) {
- if (t->type != JSON_TYPE_OBJECT_END && t->type != JSON_TYPE_ARRAY_END) {
- next_set_key(d, name, name_len, p[0] == '[');
- }
- if (d->val != NULL) *d->val = *t;
- d->handle = (void *) t->ptr;
- d->found = 1;
- }
-}
-
-static void *json_next(const char *s, int len, void *handle, const char *path,
- struct json_token *key, struct json_token *val, int *i) {
- struct json_token tmpval, *v = val == NULL ? &tmpval : val;
- struct json_token tmpkey, *k = key == NULL ? &tmpkey : key;
- int tmpidx, *pidx = i == NULL ? &tmpidx : i;
- struct next_data data = {handle, path, (int) strlen(path), 0, k, v, pidx};
- json_walk(s, len, json_next_cb, &data);
- return data.found ? data.handle : NULL;
-}
-
-void *json_next_key(const char *s, int len, void *handle, const char *path,
- struct json_token *key, struct json_token *val) WEAK;
-void *json_next_key(const char *s, int len, void *handle, const char *path,
- struct json_token *key, struct json_token *val) {
- return json_next(s, len, handle, path, key, val, NULL);
-}
-
-void *json_next_elem(const char *s, int len, void *handle, const char *path,
- int *idx, struct json_token *val) WEAK;
-void *json_next_elem(const char *s, int len, void *handle, const char *path,
- int *idx, struct json_token *val) {
- return json_next(s, len, handle, path, NULL, val, idx);
-}
-
-static int json_sprinter(struct json_out *out, const char *str, size_t len) {
- size_t old_len = out->u.buf.buf == NULL ? 0 : strlen(out->u.buf.buf);
- size_t new_len = len + old_len;
- char *p = (char *) realloc(out->u.buf.buf, new_len + 1);
- if (p != NULL) {
- memcpy(p + old_len, str, len);
- p[new_len] = '\0';
- out->u.buf.buf = p;
- }
- return len;
-}
-
-char *json_vasprintf(const char *fmt, va_list ap) WEAK;
-char *json_vasprintf(const char *fmt, va_list ap) {
- struct json_out out;
- memset(&out, 0, sizeof(out));
- out.printer = json_sprinter;
- json_vprintf(&out, fmt, ap);
- return out.u.buf.buf;
-}
-
-char *json_asprintf(const char *fmt, ...) WEAK;
-char *json_asprintf(const char *fmt, ...) {
- char *result = NULL;
- va_list ap;
- va_start(ap, fmt);
- result = json_vasprintf(fmt, ap);
- va_end(ap);
- return result;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/frozen.h b/pm3rdv4rrg/src/main/cpp/armsrc/frozen.h
deleted file mode 100644
index fc6fd3b3..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/frozen.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (c) 2004-2013 Sergey Lyubka
- * Copyright (c) 2018 Cesanta Software Limited
- * All rights reserved
- *
- * Licensed under the Apache License, Version 2.0 (the ""License"");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an ""AS IS"" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CS_FROZEN_FROZEN_H_
-#define CS_FROZEN_FROZEN_H_
-
-#include
-#include
-
-/* JSON token type */
-enum json_token_type {
- JSON_TYPE_INVALID = 0, /* memsetting to 0 should create INVALID value */
- JSON_TYPE_STRING,
- JSON_TYPE_NUMBER,
- JSON_TYPE_TRUE,
- JSON_TYPE_FALSE,
- JSON_TYPE_NULL,
- JSON_TYPE_OBJECT_START,
- JSON_TYPE_OBJECT_END,
- JSON_TYPE_ARRAY_START,
- JSON_TYPE_ARRAY_END,
-
- JSON_TYPES_CNT
-};
-
-/*
- * Structure containing token type and value. Used in `json_walk()` and
- * `json_scanf()` with the format specifier `%T`.
- */
-struct json_token {
- const char *ptr; /* Points to the beginning of the value */
- int len; /* Value length */
- enum json_token_type type; /* Type of the token, possible values are above */
-};
-
-#define JSON_INVALID_TOKEN \
- { 0, 0, JSON_TYPE_INVALID }
-
-/* Error codes */
-#define JSON_STRING_INVALID -1
-#define JSON_STRING_INCOMPLETE -2
-
-/*
- * Callback-based SAX-like API.
- *
- * Property name and length is given only if it's available: i.e. if current
- * event is an object's property. In other cases, `name` is `NULL`. For
- * example, name is never given:
- * - For the first value in the JSON string;
- * - For events JSON_TYPE_OBJECT_END and JSON_TYPE_ARRAY_END
- *
- * E.g. for the input `{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`,
- * the sequence of callback invocations will be as follows:
- *
- * - type: JSON_TYPE_OBJECT_START, name: NULL, path: "", value: NULL
- * - type: JSON_TYPE_NUMBER, name: "foo", path: ".foo", value: "123"
- * - type: JSON_TYPE_ARRAY_START, name: "bar", path: ".bar", value: NULL
- * - type: JSON_TYPE_NUMBER, name: "0", path: ".bar[0]", value: "1"
- * - type: JSON_TYPE_NUMBER, name: "1", path: ".bar[1]", value: "2"
- * - type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL
- * - type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true"
- * - type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\":
- *true }"
- * - type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, {
- *\"baz\": true } ]"
- * - type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123,
- *\"bar\": [ 1, 2, { \"baz\": true } ] }"
- */
-typedef void (*json_walk_callback_t)(void *callback_data, const char *name,
- size_t name_len, const char *path,
- const struct json_token *token);
-
-/*
- * Parse `json_string`, invoking `callback` in a way similar to SAX parsers;
- * see `json_walk_callback_t`.
- * Return number of processed bytes, or a negative error code.
- */
-int json_walk(const char *json_string, int json_string_length,
- json_walk_callback_t callback, void *callback_data);
-
-/*
- * JSON generation API.
- * struct json_out abstracts output, allowing alternative printing plugins.
- */
-struct json_out {
- int (*printer)(struct json_out *, const char *str, size_t len);
- union {
- struct {
- char *buf;
- size_t size;
- size_t len;
- } buf;
- void *data;
- FILE *fp;
- } u;
-};
-
-extern int json_printer_buf(struct json_out *, const char *, size_t);
-extern int json_printer_file(struct json_out *, const char *, size_t);
-
-#define JSON_OUT_BUF(buf, len) \
- { \
- json_printer_buf, { \
- { buf, len, 0 } \
- } \
- }
-#define JSON_OUT_FILE(fp) \
- { \
- json_printer_file, { \
- { (char *) fp, 0, 0 } \
- } \
- }
-
-typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
-
-/*
- * Generate formatted output into a given sting buffer.
- * This is a superset of printf() function, with extra format specifiers:
- * - `%B` print json boolean, `true` or `false`. Accepts an `int`.
- * - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
- * - `%.*Q` same as `%Q`, but with length. Accepts `int`, `const char *`
- * - `%V` print quoted base64-encoded string. Accepts a `const char *`, `int`.
- * - `%H` print quoted hex-encoded string. Accepts a `int`, `const char *`.
- * - `%M` invokes a json_printf_callback_t function. That callback function
- * can consume more parameters.
- *
- * Return number of bytes printed. If the return value is bigger than the
- * supplied buffer, that is an indicator of overflow. In the overflow case,
- * overflown bytes are not printed.
- */
-int json_printf(struct json_out *, const char *fmt, ...);
-int json_vprintf(struct json_out *, const char *fmt, va_list xap);
-
-/*
- * Same as json_printf, but prints to a file.
- * File is created if does not exist. File is truncated if already exists.
- */
-int json_fprintf(const char *file_name, const char *fmt, ...);
-int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
-
-/*
- * Print JSON into an allocated 0-terminated string.
- * Return allocated string, or NULL on error.
- * Example:
- *
- * ```c
- * char *str = json_asprintf("{a:%H}", 3, "abc");
- * printf("%s\n", str); // Prints "616263"
- * free(str);
- * ```
- */
-char *json_asprintf(const char *fmt, ...);
-char *json_vasprintf(const char *fmt, va_list ap);
-
-/*
- * Helper %M callback that prints contiguous C arrays.
- * Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt
- * Return number of bytes printed.
- */
-int json_printf_array(struct json_out *, va_list *ap);
-
-/*
- * Scan JSON string `str`, performing scanf-like conversions according to `fmt`.
- * This is a `scanf()` - like function, with following differences:
- *
- * 1. Object keys in the format string may be not quoted, e.g. "{key: %d}"
- * 2. Order of keys in an object is irrelevant.
- * 3. Several extra format specifiers are supported:
- * - %B: consumes `int *` (or `char *`, if `sizeof(bool) == sizeof(char)`),
- * expects boolean `true` or `false`.
- * - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
- * string is malloc-ed, caller must free() the string.
- * - %V: consumes `char **`, `int *`. Expects base64-encoded string.
- * Result string is base64-decoded, malloced and NUL-terminated.
- * The length of result string is stored in `int *` placeholder.
- * Caller must free() the result.
- * - %H: consumes `int *`, `char **`.
- * Expects a hex-encoded string, e.g. "fa014f".
- * Result string is hex-decoded, malloced and NUL-terminated.
- * The length of the result string is stored in `int *` placeholder.
- * Caller must free() the result.
- * - %M: consumes custom scanning function pointer and
- * `void *user_data` parameter - see json_scanner_t definition.
- * - %T: consumes `struct json_token *`, fills it out with matched token.
- *
- * Return number of elements successfully scanned & converted.
- * Negative number means scan error.
- */
-int json_scanf(const char *str, int len, const char *fmt, ...);
-int json_vscanf(const char *str, int len, const char *fmt, va_list ap);
-
-/* json_scanf's %M handler */
-typedef void (*json_scanner_t)(const char *str, int len, void *user_data);
-
-/*
- * Helper function to scan array item with given path and index.
- * Fills `token` with the matched JSON token.
- * Return -1 if no array element found, otherwise non-negative token length.
- */
-int json_scanf_array_elem(const char *s, int len, const char *path, int idx, struct json_token *token);
-
-/*
- * Unescape JSON-encoded string src,slen into dst, dlen.
- * src and dst may overlap.
- * If destination buffer is too small (or zero-length), result string is not
- * written but the length is counted nevertheless (similar to snprintf).
- * Return the length of unescaped string in bytes.
- */
-int json_unescape(const char *src, int slen, char *dst, int dlen);
-
-/*
- * Escape a string `str`, `str_len` into the printer `out`.
- * Return the number of bytes printed.
- */
-int json_escape(struct json_out *out, const char *str, size_t str_len);
-
-/*
- * Read the whole file in memory.
- * Return malloc-ed file content, or NULL on error. The caller must free().
- */
-char *json_fread(const char *path);
-
-/*
- * Update given JSON string `s,len` by changing the value at given `json_path`.
- * The result is saved to `out`. If `json_fmt` == NULL, that deletes the key.
- * If path is not present, missing keys are added. Array path without an
- * index pushes a value to the end of an array.
- * Return 1 if the string was changed, 0 otherwise.
- *
- * Example: s is a JSON string { "a": 1, "b": [ 2 ] }
- * json_setf(s, len, out, ".a", "7"); // { "a": 7, "b": [ 2 ] }
- * json_setf(s, len, out, ".b", "7"); // { "a": 1, "b": 7 }
- * json_setf(s, len, out, ".b[]", "7"); // { "a": 1, "b": [ 2,7 ] }
- * json_setf(s, len, out, ".b", NULL); // { "a": 1 }
- */
-int json_setf(const char *s, int len, struct json_out *out,
- const char *json_path, const char *json_fmt, ...);
-
-int json_vsetf(const char *s, int len, struct json_out *out,
- const char *json_path, const char *json_fmt, va_list ap);
-
-/*
- * Pretty-print JSON string `s,len` into `out`.
- * Return number of processed bytes in `s`.
- */
-int json_prettify(const char *s, int len, struct json_out *out);
-
-/*
- * Prettify JSON file `file_name`.
- * Return number of processed bytes, or negative number of error.
- * On error, file content is not modified.
- */
-int json_prettify_file(const char *file_name);
-
-/*
- * Iterate over an object at given JSON `path`.
- * On each iteration, fill the `key` and `val` tokens. It is OK to pass NULL
- * for `key`, or `val`, in which case they won't be populated.
- * Return an opaque value suitable for the next iteration, or NULL when done.
- *
- * Example:
- *
- * ```c
- * void *h = NULL;
- * struct json_token key, val;
- * while ((h = json_next_key(s, len, h, ".foo", &key, &val)) != NULL) {
- * printf("[%.*s] -> [%.*s]\n", key.len, key.ptr, val.len, val.ptr);
- * }
- * ```
- */
-void *json_next_key(const char *s, int len, void *handle, const char *path,
- struct json_token *key, struct json_token *val);
-
-/*
- * Iterate over an array at given JSON `path`.
- * Similar to `json_next_key`, but fills array index `idx` instead of `key`.
- */
-void *json_next_elem(const char *s, int len, void *handle, const char *path,
- int *idx, struct json_token *val);
-
-#ifndef JSON_MAX_PATH_LEN
-#define JSON_MAX_PATH_LEN 256
-#endif
-
-#ifndef JSON_MINIMAL
-#define JSON_MINIMAL 1
-#endif
-
-#ifndef JSON_ENABLE_BASE64
-#define JSON_ENABLE_BASE64 !JSON_MINIMAL
-#endif
-
-#ifndef JSON_ENABLE_HEX
-#define JSON_ENABLE_HEX !JSON_MINIMAL
-#endif
-
-#endif /* CS_FROZEN_FROZEN_H_ */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hfsnoop.c b/pm3rdv4rrg/src/main/cpp/armsrc/hfsnoop.c
deleted file mode 100644
index 770280b9..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hfsnoop.c
+++ /dev/null
@@ -1,130 +0,0 @@
-//-----------------------------------------------------------------------------
-// piwi, 2019
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to get sample data from FPGA.
-//-----------------------------------------------------------------------------
-#include "hfsnoop.h"
-#include "proxmark3_arm.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "fpga.h"
-#include "appmain.h"
-#include "cmd.h"
-
-static void RAMFUNC optimizedSniff(void) {
- int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
-
- uint16_t *dest = (uint16_t *)BigBuf_get_addr();
- uint16_t *destend = dest + n - 1;
-
- // Reading data loop
- while (dest <= destend) {
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
- dest++;
- }
- }
- //setting tracelen - important! it was set by buffer overflow before
- set_tracelen(BigBuf_max_traceLen());
-}
-
-void HfSniff(int samplesToSkip, int triggersToSkip) {
- BigBuf_free();
- BigBuf_Clear();
-
- Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
- int trigger_cnt = 0;
-
- LED_D_ON();
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Set up the synchronous serial port
- FpgaSetupSsc();
-
- // Setting Frame Mode For better performance on high speed data transfer.
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
- SpinDelay(100);
-
- uint16_t r = 0;
- while (!BUTTON_PRESS() && !data_available()) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- r = (uint16_t)AT91C_BASE_SSC->SSC_RHR;
- r = MAX(r & 0xff, r >> 8);
- if (r >= 180) { // 0xB4 ??
- if (++trigger_cnt > triggersToSkip)
- break;
- }
- }
- }
-
- if (!BUTTON_PRESS()) {
- int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0
- while (waitcount != 0) {
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
- waitcount--;
- }
- optimizedSniff();
- Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
- }
-
- //Resetting Frame mode (First set in fpgaloader.c)
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
-
- DbpString("HF Sniffing end");
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
-}
-
-void HfPlotDownload(void) {
- uint8_t *buf = ToSend;
- uint8_t *this_buf = buf;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- FpgaSetupSsc();
-
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
- AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address
- AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples
- buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM
-
- LED_B_ON();
- for (size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) {
- // prepare next DMA transfer:
- uint8_t *next_buf = buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE));
-
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE;
-
- size_t len = MIN(FPGA_TRACE_SIZE - i, PM3_CMD_DATA_SIZE);
-
- while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) {}; // wait for DMA transfer to complete
-
- reply_old(CMD_FPGAMEM_DOWNLOADED, i, len, FPGA_TRACE_SIZE, this_buf, len);
- this_buf = next_buf;
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- // Trigger a finish downloading signal with an ACK frame
- reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0);
- LED_B_OFF();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hfsnoop.h b/pm3rdv4rrg/src/main/cpp/armsrc/hfsnoop.h
deleted file mode 100644
index 04953694..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hfsnoop.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-// Piwi, Feb 2019
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __HFSNOOP_H
-#define __HFSNOOP_H
-
-void HfSniff(int, int);
-void HfPlotDownload(void);
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2.c b/pm3rdv4rrg/src/main/cpp/armsrc/hitag2.c
deleted file mode 100644
index aa0eb820..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2.c
+++ /dev/null
@@ -1,1938 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Hitag2 emulation
-//
-// (c) 2009 Henryk Plötz
-//-----------------------------------------------------------------------------
-// Hitag2 complete rewrite of the code
-// - Fixed modulation/encoding issues
-// - Rewrote code for transponder emulation
-// - Added sniffing of transponder communication
-// - Added reader functionality
-//
-// (c) 2012 Roel Verdult
-//-----------------------------------------------------------------------------
-// Piwi, 2019
-// Iceman, 2019
-// Anon, 2019
-// Doegox, 2020
-
-#include "hitag2.h"
-#include "hitag2_crypto.h"
-#include "string.h"
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "lfadc.h"
-#include "lfsampling.h"
-#include "lfdemod.h"
-#include "commonutil.h"
-
-
-#define test_bit(data, i) (*(data + (i/8)) >> (7-(i % 8))) & 1
-#define set_bit(data, i) *(data + (i/8)) |= (1 << (7-(i % 8)))
-#define clear_bit(data, i) *(data + (i/8)) &= ~(1 << (7-(i % 8)))
-#define flip_bit(data, i) *(data + (i/8)) ^= (1 << (7-(i % 8)))
-
-// Successful crypto auth
-static bool bCrypto;
-// Is in auth stage
-static bool bAuthenticating;
-// Successful password auth
-bool bSelecting;
-bool bCollision;
-static bool bPwd;
-static bool bSuccessful;
-
-static struct hitag2_tag tag = {
- .state = TAG_STATE_RESET,
- .sectors = { // Password mode: | Crypto mode:
- [0] = { 0x02, 0x4e, 0x02, 0x20}, // UID | UID
- [1] = { 0x4d, 0x49, 0x4b, 0x52}, // Password RWD | 32 bit LSB key
- [2] = { 0x20, 0xf0, 0x4f, 0x4e}, // Reserved | 16 bit MSB key, 16 bit reserved
- [3] = { 0x0e, 0xaa, 0x48, 0x54}, // Configuration, password TAG | Configuration, password TAG
- [4] = { 0x46, 0x5f, 0x4f, 0x4b}, // Data: F_OK
- [5] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU
- [6] = { 0xaa, 0xaa, 0xaa, 0xaa}, // Data: ....
- [7] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU
- [8] = { 0x00, 0x00, 0x00, 0x00}, // RSK Low
- [9] = { 0x00, 0x00, 0x00, 0x00}, // RSK High
- [10] = { 0x00, 0x00, 0x00, 0x00}, // RCF
- [11] = { 0x00, 0x00, 0x00, 0x00}, // SYNC
- // up to index 15 reserved for HITAG1/HITAGS public data
- },
-};
-
-static enum {
- WRITE_STATE_START = 0x0,
- WRITE_STATE_PAGENUM_WRITTEN,
- WRITE_STATE_PROG
-} writestate;
-
-// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
-// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
-#define AUTH_TABLE_LENGTH 2744
-static uint8_t *auth_table;
-static size_t auth_table_pos = 0;
-static size_t auth_table_len = AUTH_TABLE_LENGTH;
-
-static uint8_t password[4];
-static uint8_t NrAr[8];
-static uint8_t key[8];
-static uint8_t writedata[4];
-uint8_t logdata_0[4], logdata_1[4];
-uint8_t nonce[4];
-bool key_no;
-static uint64_t cipher_state;
-
-size_t blocknr;
-size_t flipped_bit = 0;
-uint32_t byte_value = 0;
-
-static int hitag2_reset(void) {
- tag.state = TAG_STATE_RESET;
- tag.crypto_active = 0;
- return 0;
-}
-
-static int hitag2_init(void) {
- hitag2_reset();
- return 0;
-}
-
-// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
-// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
-// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
-// T0 = TIMER_CLOCK1 / 125000 = 192
-#ifndef HITAG_T0
-#define HITAG_T0 192
-#endif
-
-#define HITAG_FRAME_LEN 20
-#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
-#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
-#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
-#define HITAG_T_0 20 /* T[0] should be 18..22 */
-#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
-#define HITAG_T_1 30 /* T[1] should be 26..30 */
-//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
-#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
-#define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */
-#define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */
-#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
-#define HITAG_T_PROG 614
-
-#define HITAG_T_TAG_ONE_HALF_PERIOD 10
-#define HITAG_T_TAG_TWO_HALF_PERIOD 25
-#define HITAG_T_TAG_THREE_HALF_PERIOD 41
-#define HITAG_T_TAG_FOUR_HALF_PERIOD 57
-
-#define HITAG_T_TAG_HALF_PERIOD 16
-#define HITAG_T_TAG_FULL_PERIOD 32
-
-#define HITAG_T_TAG_CAPTURE_ONE_HALF 13
-#define HITAG_T_TAG_CAPTURE_TWO_HALF 25
-#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
-#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
-
-/*
-// sim
-static void hitag_send_bit(int bit) {
- LED_A_ON();
-
- // Reset clock for the next bit
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- // Fixed modulation, earlier proxmark version used inverted signal
- // check datasheet if reader uses BiPhase?
- if (bit == 0) {
- // Manchester: Unloaded, then loaded |__--|
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_HALF_PERIOD);
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_FULL_PERIOD);
- } else {
- // Manchester: Loaded, then unloaded |--__|
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_HALF_PERIOD);
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_FULL_PERIOD);
- }
- LED_A_OFF();
-}
-
-// sim
-static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
- // SOF - write start of frame
- hitag_send_bit(1);
- hitag_send_bit(1);
- hitag_send_bit(1);
- hitag_send_bit(1);
- hitag_send_bit(1);
-
- // Send the content of the frame
- for (size_t i = 0; i < frame_len; i++) {
- hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
- }
-
- // Drop the modulation
- LOW(GPIO_SSC_DOUT);
-}
-*/
-
-// sim
-static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
- uint8_t rx_air[HITAG_FRAME_LEN];
-
- // Copy the (original) received frame how it is write over the air
- memcpy(rx_air, rx, nbytes(rxlen));
-
- if (tag.crypto_active) {
- hitag2_cipher_transcrypt(&(tag.cs), rx, rxlen / 8, rxlen % 8);
- }
-
- // Reset the transmission frame length
- *txlen = 0;
-
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- // Received 11000 from the reader, request for UID, write UID
- case 05: {
- // Always write over the air in the clear plaintext mode
- if (rx_air[0] != 0xC0) {
- // Unknown frame ?
- return;
- }
- *txlen = 32;
- memcpy(tx, tag.sectors[0], 4);
- tag.crypto_active = 0;
- }
- break;
-
- // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number
- case 10: {
- uint16_t sector = (~(((rx[0] << 2) & 0x04) | ((rx[1] >> 6) & 0x03)) & 0x07);
-
- // Verify complement of sector index
- if (sector != ((rx[0] >> 3) & 0x07)) {
- DbpString("Transmission error (read/write)");
- return;
- }
-
- switch (rx[0] & 0xC6) {
- // Read command: 11xx x00y
- case 0xC0: {
- memcpy(tx, tag.sectors[sector], 4);
- *txlen = 32;
- break;
- }
- // Inverted Read command: 01xx x10y
- case 0x44: {
- for (size_t i = 0; i < 4; i++) {
- tx[i] = tag.sectors[sector][i] ^ 0xff;
- }
- *txlen = 32;
- break;
- }
- // Write command: 10xx x01y
- case 0x82: {
- // Prepare write, acknowledge by repeating command
- memcpy(tx, rx, nbytes(rxlen));
- *txlen = rxlen;
- tag.active_sector = sector;
- tag.state = TAG_STATE_WRITING;
- break;
- }
- // Unknown command
- default: {
- Dbprintf("Unknown command: %02x %02x", rx[0], rx[1]);
- return;
- }
- }
- }
- break;
-
- // Writing data or Reader password
- case 32: {
- if (tag.state == TAG_STATE_WRITING) {
- // These are the sector contents to be written. We don't have to do anything else.
- memcpy(tag.sectors[tag.active_sector], rx, nbytes(rxlen));
- tag.state = TAG_STATE_RESET;
- return;
- } else {
- // Received RWD password, respond with configuration and our password
- if (memcmp(rx, tag.sectors[1], 4) != 0) {
- DbpString("Reader password is wrong");
- return;
- }
- *txlen = 32;
- memcpy(tx, tag.sectors[3], 4);
- }
- }
- break;
-
- // Received RWD authentication challenge and respnse
- case 64: {
- // Store the authentication attempt
- if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) {
- memcpy(auth_table + auth_table_len, rx, 8);
- auth_table_len += 8;
- }
-
- // Reset the cipher state
- hitag2_cipher_reset(&tag, rx);
-
- // Check if the authentication was correct
- if (!hitag2_cipher_authenticate(&(tag.cs), rx + 4)) {
- // The reader failed to authenticate, do nothing
- Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
- return;
- }
- // Activate encryption algorithm for all further communication
- tag.crypto_active = 1;
-
- // Use the tag password as response
- memcpy(tx, tag.sectors[3], 4);
- *txlen = 32;
- }
- break;
- }
-
- if (tag.crypto_active) {
- hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
- }
-}
-
-// reader/writer
-// returns how long it took
-static uint32_t hitag_reader_send_bit(int bit) {
- uint32_t wait = 0;
- LED_A_ON();
- // Binary pulse length modulation (BPLM) is used to encode the data stream
- // This means that a transmission of a one takes longer than that of a zero
-
- // Enable modulation, which means, drop the field
- lf_modulation(true);
-
- // Wait for 4-10 times the carrier period
- lf_wait_periods(8); // wait for 4-10 times the carrier period
- wait += 8;
-
- // Disable modulation, just activates the field again
- lf_modulation(false);
-
- if (bit == 0) {
- // Zero bit: |_-|
- lf_wait_periods(HITAG_T_0 - HITAG_T_LOW); // wait for 18-22 times the carrier period
- wait += HITAG_T_0 - HITAG_T_LOW;
- } else {
- // One bit: |_--|
- lf_wait_periods(HITAG_T_1 - HITAG_T_LOW); // wait for 26-32 times the carrier period
- wait += HITAG_T_1 - HITAG_T_LOW;
- }
- /*lf_wait_periods(10);*/
- LED_A_OFF();
- return wait;
-}
-
-// reader/writer
-static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
-
- uint32_t wait = 0;
- // Send the content of the frame
- for (size_t i = 0; i < frame_len; i++) {
- wait += hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
- }
-
- // Enable modulation, which means, drop the field
- lf_modulation(true);
-
- // Wait for 4-10 times the carrier period
- lf_wait_periods(HITAG_T_LOW);
- wait += HITAG_T_LOW;
-
- // Disable modulation, just activates the field again
- lf_modulation(false);
-
- // t_stop, high field for stop condition (> 36)
- lf_wait_periods(HITAG_T_STOP);
- wait += HITAG_T_STOP;
-
- return wait;
-}
-
-uint8_t hitag_crc(uint8_t *data, size_t length) {
- uint8_t crc = 0xff;
- unsigned int byte, bit;
- for (byte = 0; byte < ((length + 7) / 8); byte++) {
- crc ^= *(data + byte);
- bit = length < (8 * (byte + 1)) ? (length % 8) : 8;
- while (bit--) {
- if (crc & 0x80) {
- crc <<= 1;
- crc ^= 0x1d;
- } else {
- crc <<= 1;
- }
- }
- }
- return crc;
-}
-
-/*
-void fix_ac_decoding(uint8_t *input, size_t len) {
- // Reader routine tries to decode AC data after Manchester decoding
- // AC has double the bitrate, extract data from bit-pairs
- uint8_t temp[len / 16];
- memset(temp, 0, sizeof(temp));
-
- for (size_t i = 1; i < len; i += 2) {
- if (test_bit(input, i) && test_bit(input, (i + 1))) {
- set_bit(temp, (i / 2));
- }
- }
- memcpy(input, temp, sizeof(temp));
-}
-*/
-
-
-// looks at number of received bits.
-// 0 = collision?
-// 32 = good response
-bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) {
- uint8_t crc;
- *txlen = 0;
- switch (rxlen) {
- case 0: {
- // retry waking up card
- /*tx[0] = 0xb0; // Rev 3.0*/
- tx[0] = 0x30; // Rev 2.0
- *txlen = 5;
- if (!bCollision) blocknr--;
- if (blocknr < 0) {
- blocknr = 0;
- }
- if (!hitag_s) {
- if (blocknr > 1 && blocknr < 31) {
- blocknr = 31;
- }
- }
- bCollision = true;
- return true;
- }
- case 32: {
- if (bCollision) {
- // Select card by serial from response
- tx[0] = 0x00 | rx[0] >> 5;
- tx[1] = rx[0] << 3 | rx[1] >> 5;
- tx[2] = rx[1] << 3 | rx[2] >> 5;
- tx[3] = rx[2] << 3 | rx[3] >> 5;
- tx[4] = rx[3] << 3;
- crc = hitag_crc(tx, 37);
- tx[4] |= crc >> 5;
- tx[5] = crc << 3;
- *txlen = 45;
- bCollision = false;
- } else {
- memcpy(tag.sectors[blocknr], rx, 4);
- blocknr++;
- if (!hitag_s) {
- if (blocknr > 1 && blocknr < 31) {
- blocknr = 31;
- }
- }
- if (blocknr > 63) {
- DbpString("Read succesful!");
- *txlen = 0;
- bSuccessful = true;
- return false;
- }
- // read next page of card until done
- Dbprintf("Reading page %02u", blocknr);
- tx[0] = 0xc0 | blocknr >> 4; // RDPPAGE
- tx[1] = blocknr << 4;
- crc = hitag_crc(tx, 12);
- tx[1] |= crc >> 4;
- tx[2] = crc << 4;
- *txlen = 20;
- }
- }
- break;
- default: {
- Dbprintf("Uknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
- return true;
-}
-
-
-bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
- uint8_t crc;
- *txlen = 0;
- switch (rxlen) {
- case 0: {
- // retry waking up card
- /*tx[0] = 0xb0; // Rev 3.0*/
- tx[0] = 0x30; // Rev 2.0
- *txlen = 5;
- if (bCrypto && byte_value <= 0xff) {
- // to retry
- bCrypto = false;
- }
- if (!bCollision) blocknr--;
- if (blocknr < 0) {
- blocknr = 0;
- }
- bCollision = true;
- // will receive 32-bit UID
- }
- break;
- case 2: {
- if (bAuthenticating) {
- // received Auth init ACK, send nonce
- // TODO Roel, bit-manipulation goes here
- /*nonce[0] = 0x2d;*/
- /*nonce[1] = 0x74;*/
- /*nonce[2] = 0x80;*/
- /*nonce[3] = 0xa5;*/
- nonce[0] = byte_value;
- byte_value++;
- /*set_bit(nonce,flipped_bit);*/
- memcpy(tx, nonce, 4);
- *txlen = 32;
- // will receive 32 bit encrypted Logdata
- } else if (bCrypto) {
- // authed, start reading
- tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
- tx[1] = blocknr << 4;
- crc = hitag_crc(tx, 12);
- tx[1] |= crc >> 4;
- tx[2] = crc << 4;
- *txlen = 20;
- // will receive 32-bit encrypted page
- }
- }
- break;
- case 32: {
- if (bCollision) {
- // Select card by serial from response
- tx[0] = 0x00 | rx[0] >> 5;
- tx[1] = rx[0] << 3 | rx[1] >> 5;
- tx[2] = rx[1] << 3 | rx[2] >> 5;
- tx[3] = rx[2] << 3 | rx[3] >> 5;
- tx[4] = rx[3] << 3;
- crc = hitag_crc(tx, 37);
- tx[4] |= crc >> 5;
- tx[5] = crc << 3;
- *txlen = 45;
- bCollision = false;
- bSelecting = true;
- // will receive 32-bit configuration page
- } else if (bSelecting) {
- // Initiate auth
- tx[0] = 0xa0 | key_no >> 4; // WRCPAGE
- tx[1] = blocknr << 4;
- crc = hitag_crc(tx, 12);
- tx[1] |= crc >> 4;
- tx[2] = crc << 4;
- *txlen = 20;
- bSelecting = false;
- bAuthenticating = true;
- // will receive 2-bit ACK
- } else if (bAuthenticating) {
- // received 32-bit logdata 0
- // TODO decrypt logdata 0, verify against logdata_0
- memcpy(tag.sectors[0], rx, 4);
- memcpy(tag.sectors[1], tx, 4);
- Dbprintf("%02x%02x%02x%02x %02x%02x%02x%02x", rx[0], rx[1], rx[2], rx[3], tx[0], tx[1], tx[2], tx[3]);
- // TODO replace with secret data stream
- // TODO encrypt logdata_1
- memcpy(tx, logdata_1, 4);
- *txlen = 32;
- bAuthenticating = false;
- bCrypto = true;
- // will receive 2-bit ACK
- } else if (bCrypto) {
- // received 32-bit encrypted page
- // TODO decrypt rx
- memcpy(tag.sectors[blocknr], rx, 4);
- blocknr++;
- if (blocknr > 63) {
- DbpString("Read succesful!");
- bSuccessful = true;
- return false;
- }
-
- // TEST
- Dbprintf("Succesfully authenticated with logdata:");
- Dbhexdump(4, logdata_1, false);
- bSuccessful = true;
- return false;
-
- // read next page of card until done
- tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
- tx[1] = blocknr << 4;
- crc = hitag_crc(tx, 12);
- tx[1] |= crc >> 4;
- tx[2] = crc << 4;
- *txlen = 20;
- }
- }
- break;
- default: {
- Dbprintf("Uknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Hitag2 operations
-//-----------------------------------------------------------------------------
-
-static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
- switch (writestate) {
- case WRITE_STATE_START:
- *txlen = 10;
- tx[0] = 0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
- tx[1] = ((blocknr ^ 7) << 6);
- writestate = WRITE_STATE_PAGENUM_WRITTEN;
- break;
- case WRITE_STATE_PAGENUM_WRITTEN:
- // Check if page number was received correctly
- if ((rxlen == 10)
- && (rx[0] == (0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2)))
- && (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
-
- *txlen = 32;
- memset(tx, 0, HITAG_FRAME_LEN);
- memcpy(tx, writedata, 4);
- writestate = WRITE_STATE_PROG;
- } else {
- Dbprintf("hitag2_write_page: Page number was not received correctly: rxlen=%d rx=%02x%02x%02x%02x",
- rxlen, rx[0], rx[1], rx[2], rx[3]);
- bSuccessful = false;
- return false;
- }
- break;
- case WRITE_STATE_PROG:
- if (rxlen == 0) {
- bSuccessful = true;
- } else {
- bSuccessful = false;
- Dbprintf("hitag2_write_page: unexpected rx data (%d) after page write", rxlen);
- }
- return false;
- default:
- DbpString("hitag2_write_page: Unknown state %d");
- bSuccessful = false;
- return false;
- }
-
- return true;
-}
-
-static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) {
- // Reset the transmission frame length
- *txlen = 0;
-
- if (bPwd && !bAuthenticating && write) {
- if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
- return false;
- }
- } else {
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- // No answer, try to resurrect
- case 0: {
- // Stop if there is no answer (after sending password)
- if (bPwd) {
- DbpString("Password failed!");
- return false;
- }
- *txlen = 5;
- memcpy(tx, "\xC0", nbytes(*txlen));
- }
- break;
-
- // Received UID, tag password
- case 32: {
- // stage 1, got UID
- if (!bPwd) {
- bPwd = true;
- bAuthenticating = true;
- memcpy(tx, password, 4);
- *txlen = 32;
- } else {
- // stage 2, got config byte+password TAG, discard as will read later
- if (bAuthenticating) {
- bAuthenticating = false;
- if (write) {
- if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
- return false;
- }
- break;
- }
- }
- // stage 2+, got data block
- else {
- memcpy(tag.sectors[blocknr], rx, 4);
- blocknr++;
- }
-
- if (blocknr > 7) {
- bSuccessful = true;
- return false;
- }
-
- *txlen = 10;
- tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
- tx[1] = ((blocknr ^ 7) << 6);
- }
- }
- break;
-
- // Unexpected response
- default: {
- Dbprintf("Unknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
- }
-
- return true;
-}
-
-static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) {
- // Reset the transmission frame length
- *txlen = 0;
-
- if (bCrypto) {
- hitag2_cipher_transcrypt(&cipher_state, rx, rxlen / 8, rxlen % 8);
- }
-
- if (bCrypto && !bAuthenticating && write) {
- if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
- return false;
- }
- } else {
-
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- // No answer, try to resurrect
- case 0: {
- // Stop if there is no answer while we are in crypto mode (after sending NrAr)
- if (bCrypto) {
- // Failed during authentication
- if (bAuthenticating) {
- DbpString("Authentication failed!");
- return false;
- } else {
- // Failed reading a block, could be (read/write) locked, skip block and re-authenticate
- if (blocknr == 1) {
- // Write the low part of the key in memory
- memcpy(tag.sectors[1], key + 2, 4);
- } else if (blocknr == 2) {
- // Write the high part of the key in memory
- tag.sectors[2][0] = 0x00;
- tag.sectors[2][1] = 0x00;
- tag.sectors[2][2] = key[0];
- tag.sectors[2][3] = key[1];
- } else {
- // Just put zero's in the memory (of the unreadable block)
- memset(tag.sectors[blocknr], 0x00, 4);
- }
- blocknr++;
- bCrypto = false;
- }
- } else {
- *txlen = 5;
- memcpy(tx, "\xc0", nbytes(*txlen));
- }
- break;
- }
- // Received UID, crypto tag answer
- case 32: {
- // stage 1, got UID
- if (!bCrypto) {
- uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
- uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
- Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid));
- cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
- // PRN
- memset(tx, 0x00, 4);
- // Secret data
- memset(tx + 4, 0xff, 4);
- hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
- *txlen = 64;
- bCrypto = true;
- bAuthenticating = true;
- } else {
- // stage 2, got config byte+password TAG, discard as will read later
- if (bAuthenticating) {
- bAuthenticating = false;
- if (write) {
- if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
- return false;
- }
- break;
- }
- }
- // stage 2+, got data block
- else {
- // Store the received block
- memcpy(tag.sectors[blocknr], rx, 4);
- blocknr++;
- }
- if (blocknr > 7) {
- DbpString("Read successful!");
- bSuccessful = true;
- return false;
- } else {
- *txlen = 10;
- tx[0] = 0xc0 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
- tx[1] = ((blocknr ^ 7) << 6);
- }
- }
- }
- break;
-
- // Unexpected response
- default: {
- Dbprintf("Unknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
- }
-
- if (bCrypto) {
- // We have to return now to avoid double encryption
- if (!bAuthenticating) {
- hitag2_cipher_transcrypt(&cipher_state, tx, *txlen / 8, *txlen % 8);
- }
- }
-
- return true;
-}
-
-static bool hitag2_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
- // Reset the transmission frame length
- *txlen = 0;
-
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- // No answer, try to resurrect
- case 0: {
- // Stop if there is no answer while we are in crypto mode (after sending NrAr)
- if (bCrypto) {
- DbpString("Authentication failed!");
- return false;
- }
- *txlen = 5;
- memcpy(tx, "\xC0", nbytes(*txlen));
- }
- break;
-
- // Received UID, crypto tag answer
- case 32: {
- if (!bCrypto) {
- *txlen = 64;
- memcpy(tx, NrAr, 8);
- bCrypto = true;
- } else {
- DbpString("Authentication successful!");
- return true;
- }
- }
- break;
-
- // Unexpected response
- default: {
- Dbprintf("Unknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
-
- return true;
-}
-
-static bool hitag2_test_auth_attempts(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
-
- // Reset the transmission frame length
- *txlen = 0;
-
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- // No answer, try to resurrect
- case 0: {
- // Stop if there is no answer while we are in crypto mode (after sending NrAr)
- if (bCrypto) {
- Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]);
-
- // Removing failed entry from authentiations table
- memcpy(auth_table + auth_table_pos, auth_table + auth_table_pos + 8, 8);
- auth_table_len -= 8;
-
- // Return if we reached the end of the authentications table
- bCrypto = false;
- if (auth_table_pos == auth_table_len) {
- return false;
- }
-
- // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
- memcpy(NrAr, auth_table + auth_table_pos, 8);
- }
- *txlen = 5;
- memcpy(tx, "\xc0", nbytes(*txlen));
- }
- break;
-
- // Received UID, crypto tag answer, or read block response
- case 32: {
- if (!bCrypto) {
- *txlen = 64;
- memcpy(tx, NrAr, 8);
- bCrypto = true;
- } else {
- Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]);
- bCrypto = false;
- if ((auth_table_pos + 8) == auth_table_len) {
- return false;
- }
- auth_table_pos += 8;
- memcpy(NrAr, auth_table + auth_table_pos, 8);
- }
- }
- break;
-
- default: {
- Dbprintf("Unknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
-
- return true;
-}
-
-static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
- // Reset the transmission frame length
- *txlen = 0;
-
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- // No answer, try to resurrect
- case 0: {
- // Just starting or if there is no answer
- *txlen = 5;
- memcpy(tx, "\xC0", nbytes(*txlen));
- }
- break;
- // Received UID
- case 32: {
- // Check if we received answer tag (at)
- if (bAuthenticating) {
- bAuthenticating = false;
- } else {
- // Store the received block
- memcpy(tag.sectors[blocknr], rx, 4);
- blocknr++;
-
- Dbhexdump(4, rx, false);
- }
- if (blocknr > 0) {
- bSuccessful = true;
- return false;
- }
- }
- break;
- // Unexpected response
- default: {
- Dbprintf("Unknown frame length: %d", rxlen);
- return false;
- }
- break;
- }
- return true;
-}
-
-// Hitag2 Sniffing
-void SniffHitag2(void) {
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- auth_table_len = 0;
- auth_table_pos = 0;
-
- auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
- memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
-
- DbpString("Starting Hitag2 sniffing");
- LED_D_ON();
-
- lf_init(false, false);
-
- logging = false;
-
- size_t periods = 0;
- uint8_t periods_bytes[4];
-
- int16_t checked = 0;
-
- /*bool waiting_for_first_edge = true;*/
- LED_C_ON();
-
- while (!BUTTON_PRESS()) {
-
- WDT_HIT();
-
- // only every 1000th times, in order to save time when collecting samples.
- if (checked == 1000) {
- if (data_available()) {
- checked = -1;
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
-
- // Receive frame, watch for at most T0*EOF periods
- lf_reset_counter();
-
- // Wait "infinite" for reader modulation
- periods = lf_detect_gap(20000);
-
- // Test if we detected the first reader modulation edge
- if (periods != 0) {
- if (logging == false) {
- logging = true;
- LED_D_ON();
- }
- }
-
- /*lf_count_edge_periods(10000);*/
- while ((periods = lf_detect_gap(64)) != 0) {
- num_to_bytes(periods, 4, periods_bytes);
- LogTrace(periods_bytes, 4, 0, 0, NULL, true);
- }
-
- }
-
- lf_finalize();
-
- DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations");
-}
-
-// Hitag2 simulation
-void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // empties bigbuff etc
- lf_init(false, true);
-
- int response = 0;
- uint8_t rx[HITAG_FRAME_LEN];
- size_t rxlen = 0;
- uint8_t tx[HITAG_FRAME_LEN];
- size_t txlen = 0;
-
- auth_table_len = 0;
- auth_table_pos = 0;
-// auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH);
-// memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
-
- // Reset the received frame, frame count and timing info
-// memset(rx, 0x00, sizeof(rx));
-// memset(tx, 0x00, sizeof(tx));
-
- DbpString("Starting Hitag2 simulation");
-
- LED_D_ON();
-
- // hitag2 state machine?
- hitag2_init();
-
- // copy user supplied emulation data
- if (tag_mem_supplied) {
- DbpString("Loading hitag2 memory...");
- memcpy((uint8_t *)tag.sectors, data, 48);
- }
-
- // printing
- uint32_t block = 0;
- for (size_t i = 0; i < 12; i++) {
-
- // num2bytes?
- for (size_t j = 0; j < 4; j++) {
- block <<= 8;
- block |= tag.sectors[i][j];
- }
- Dbprintf("| %d | %08x |", i, block);
- }
-
- uint8_t tag_modulation;
- size_t max_nrzs = 8 * HITAG_FRAME_LEN + 5;
- uint8_t nrz_samples[max_nrzs];
- size_t nrzs = 0, periods = 0;
-
-// uint32_t command_start = 0, command_duration = 0;
-
- int16_t checked = 0;
-
- while (!BUTTON_PRESS()) {
-
-loop1:
- LED_A_OFF();
- WDT_HIT();
-
- // only every 1000th times, in order to save time when collecting samples.
- if (checked == 100) {
- if (data_available()) {
- checked = -1;
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
- rxlen = 0;
-
- // Keep administration of the first edge detection
- bool waiting_for_first_edge = true;
-
- // Did we detected any modulaiton at all
- bool detected_tag_modulation = false;
-
- // Use the current modulation state as starting point
- tag_modulation = lf_get_tag_modulation();
-
- // Receive frame, watch for at most max_nrzs periods
- // Reset the number of NRZ samples and use edge detection to detect them
- nrzs = 0;
- while (nrzs < max_nrzs) {
- // Get the timing of the next edge in number of wave periods
- periods = lf_count_edge_periods(128);
-
- // Just break out of loop after an initial time-out (tag is probably not available)
- // The function lf_count_edge_periods() returns 0 when a time-out occurs
- if (periods == 0) {
- goto loop1; //break;
- }
-
- LED_A_ON();
-
- // Are we dealing with the first incoming edge
- if (waiting_for_first_edge) {
-
- // Register the number of periods that have passed
- response = periods;
-
- // Indicate that we have dealt with the first edge
- waiting_for_first_edge = false;
-
- // The first edge is always a single NRZ bit, force periods on 16
- periods = 16;
-
- // We have received more than 0 periods, so we have detected a tag response
- detected_tag_modulation = true;
- }
-
- // Evaluate the number of periods before the next edge
- if (periods > 24 && periods <= 64) {
- // Detected two sequential equal bits and a modulation switch
- // NRZ modulation: (11 => --|) or (11 __|)
- nrz_samples[nrzs++] = tag_modulation;
- nrz_samples[nrzs++] = tag_modulation;
- // Invert tag modulation state
- tag_modulation ^= 1;
- } else if (periods > 0 && periods <= 24) {
- // Detected one bit and a modulation switch
- // NRZ modulation: (1 => -|) or (0 _|)
- nrz_samples[nrzs++] = tag_modulation;
- tag_modulation ^= 1;
- } else {
- tag_modulation ^= 1;
- // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods
- Dbprintf("Detected unexpected period count: %d", periods);
- break;
- }
- }
-
- // If there is no response, just repeat the loop
- if (!detected_tag_modulation) continue;
-
- // Make sure we always have an even number of samples. This fixes the problem
- // of ending the manchester decoding with a zero. See the example below where
- // the '|' character is end of modulation
- // One at the end: ..._-|_____...
- // Zero at the end: ...-_|_____...
- // The last modulation change of a zero is not detected, but we should take
- // the half period in account, otherwise the demodulator will fail.
- if ((nrzs % 2) != 0) {
- nrz_samples[nrzs++] = tag_modulation;
- }
-
- LED_B_ON();
-
- // decode bitstream
- manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0);
-
- // Verify if the header consists of five consecutive ones
- if (nrzs < 5) {
- Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
- continue;
- } else {
- for (size_t i = 0; i < 5; i++){
- if (nrz_samples[i] != 1) {
- Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i);
- }
- }
- }
-
- // Pack the response into a byte array
- for (size_t i = 5; i < 37; i++){
- uint8_t bit = nrz_samples[i];
- rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
- rxlen++;
- }
-
- // Check if frame was captured
- if (rxlen > 4) {
-
- LogTrace(rx, nbytes(rxlen), response, 0, NULL, true);
-
- // Process the incoming frame (rx) and prepare the outgoing frame (tx)
- hitag2_handle_reader_command(rx, rxlen, tx, &txlen);
-
- // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit,
- // not that since the clock counts since the rising edge, but T_Wait1 is
- // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
- // periods. The gap time T_Low varies (4..10). All timer values are in
- // terms of T0 units
- lf_wait_periods(200);
-
- // Send and store the tag answer (if there is any)
- if (txlen) {
- // Transmit the tag frame
- //hitag_send_frame(tx, txlen);
- lf_manchester_send_bytes(tx, txlen);
-
- // Store the frame in the trace
- LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
- }
-
- // Reset the received frame and response timing info
- memset(rx, 0x00, sizeof(rx));
- response = 0;
-
- LED_B_OFF();
- }
- }
-
- lf_finalize();
-
- // release allocated memory from BigBuff.
- BigBuf_free();
-
- DbpString("Sim stopped");
-
-// reply_ng(CMD_LF_HITAG_SIMULATE, (checked == -1) ? PM3_EOPABORTED : PM3_SUCCESS, (uint8_t *)tag.sectors, tag_size);
-}
-
-void ReaderHitag(hitag_function htf, hitag_data *htd) {
-
- uint32_t command_start = 0;
- uint32_t command_duration = 0;
- uint32_t response_start = 0;
- uint32_t response_duration = 0;
- uint8_t rx[HITAG_FRAME_LEN];
- size_t rxlen = 0;
- uint8_t txbuf[HITAG_FRAME_LEN];
- uint8_t *tx = txbuf;
- size_t txlen = 0;
- int t_wait_1;
- int t_wait_1_guard = 8;
- int t_wait_2;
- size_t tag_size;
- bool bStop = false;
-
- // Raw demodulation/decoding by sampling edge periods
- size_t periods = 0;
-
- // Reset the return status
- bSuccessful = false;
- bCrypto = false;
-
- // Clean up trace and prepare it for storing frames
- set_tracing(true);
- clear_trace();
-
- DbpString("Starting Hitag reader family");
-
- // Check configuration
- switch (htf) {
- case RHT1F_PLAIN: {
- Dbprintf("Read public blocks in plain mode");
- // this part will be unreadable
- memset(tag.sectors + 2, 0x0, 30);
- blocknr = 0;
- break;
- }
- case RHT1F_AUTHENTICATE: {
- Dbprintf("Read all blocks in authed mode");
- memcpy(nonce, htd->ht1auth.nonce, 4);
- memcpy(key, htd->ht1auth.key, 4);
- memcpy(logdata_0, htd->ht1auth.logdata_0, 4);
- memcpy(logdata_1, htd->ht1auth.logdata_1, 4);
- // TEST
- memset(nonce, 0x0, 4);
- memset(logdata_1, 0x00, 4);
- byte_value = 0;
- key_no = htd->ht1auth.key_no;
- Dbprintf("Authenticating using key #%d:", key_no);
- Dbhexdump(4, key, false);
- DbpString("Nonce:");
- Dbhexdump(4, nonce, false);
- DbpString("Logdata_0:");
- Dbhexdump(4, logdata_0, false);
- DbpString("Logdata_1:");
- Dbhexdump(4, logdata_1, false);
- blocknr = 0;
- break;
- }
- case RHT2F_PASSWORD: {
- Dbprintf("List identifier in password mode");
- if (memcmp(htd->pwd.password, "\x00\x00\x00\x00", 4) == 0)
- memcpy(password, tag.sectors[1], sizeof(password));
- else
- memcpy(password, htd->pwd.password, sizeof(password));
-
- blocknr = 0;
- bPwd = false;
- bAuthenticating = false;
- break;
- }
- case RHT2F_AUTHENTICATE: {
- DbpString("Authenticating using nr,ar pair:");
- memcpy(NrAr, htd->auth.NrAr, 8);
- Dbhexdump(8, NrAr, false);
- bCrypto = false;
- bAuthenticating = false;
- break;
- }
- case RHT2F_CRYPTO: {
- DbpString("Authenticating using key:");
- memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
- Dbhexdump(6, key, false);
- DbpString("Nonce:");
- Dbhexdump(4, nonce, false);
- memcpy(nonce, htd->crypto.data, 4);
- blocknr = 0;
- bCrypto = false;
- bAuthenticating = false;
- break;
- }
- case RHT2F_TEST_AUTH_ATTEMPTS: {
- Dbprintf("Testing %d authentication attempts", (auth_table_len / 8));
- auth_table_pos = 0;
- memcpy(NrAr, auth_table, 8);
- bCrypto = false;
- break;
- }
- case RHT2F_UID_ONLY: {
- blocknr = 0;
- bCrypto = false;
- bAuthenticating = false;
- break;
- }
- default: {
- Dbprintf("Error, unknown function: %d", htf);
- set_tracing(false);
- return;
- }
- }
-
- LED_D_ON();
-
- // hitag2 state machine?
- hitag2_init();
-
- // init as reader
- lf_init(true, false);
-
- uint8_t attempt_count = 0;
-
- // Tag specific configuration settings (sof, timings, etc.)
- if (htf < 10) {
- // hitagS settings
- t_wait_1 = 204;
- t_wait_2 = 128;
- /*tag_size = 256;*/
- flipped_bit = 0;
- tag_size = 8;
- DbpString("Configured for hitagS reader");
- } else if (htf < 20) {
- // hitag1 settings
- t_wait_1 = 204;
- t_wait_2 = 128;
- tag_size = 256;
- flipped_bit = 0;
- DbpString("Configured for hitag1 reader");
- } else if (htf < 30) {
- // hitag2 settings
- t_wait_1 = HITAG_T_WAIT_1_MIN;
- t_wait_2 = HITAG_T_WAIT_2_MIN;
- tag_size = 48;
- DbpString("Configured for hitag2 reader");
- } else {
- Dbprintf("Error, unknown hitag reader type: %d", htf);
- return;
- }
-
- uint8_t tag_modulation;
- size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit
- uint8_t nrz_samples[max_nrzs];
- size_t nrzs = 0;
- int16_t checked = 0;
-
- while (!bStop) {
-
- WDT_HIT();
-
- // only every 1000th times, in order to save time when collecting samples.
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) {
- checked = -1;
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
- // By default reset the transmission buffer
- tx = txbuf;
- switch (htf) {
- case RHT1F_PLAIN: {
- bStop = !hitag_plain(rx, rxlen, tx, &txlen, false);
- break;
- }
- case RHT1F_AUTHENTICATE: {
- bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen);
- break;
- }
- case RHT2F_PASSWORD: {
- bStop = !hitag2_password(rx, rxlen, tx, &txlen, false);
- break;
- }
- case RHT2F_AUTHENTICATE: {
- bStop = !hitag2_authenticate(rx, rxlen, tx, &txlen);
- break;
- }
- case RHT2F_CRYPTO: {
- bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, false);
- break;
- }
- case RHT2F_TEST_AUTH_ATTEMPTS: {
- bStop = !hitag2_test_auth_attempts(rx, rxlen, tx, &txlen);
- break;
- }
- case RHT2F_UID_ONLY: {
- bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
- attempt_count++; //attempt 3 times to get uid then quit
- if (!bStop && attempt_count == 3)
- bStop = true;
-
- break;
- }
- default: {
- Dbprintf("Error, unknown function: %d", htf);
- goto out;
- }
- }
-
- // Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
- lf_wait_periods(t_wait_2);
- command_start += t_wait_2;
-
- // Transmit the reader frame
- command_duration = hitag_reader_send_frame(tx, txlen);
- response_start = command_start + command_duration;
-
- // Let the antenna and ADC values settle
- // And find the position where edge sampling should start
- lf_wait_periods(t_wait_1 - t_wait_1_guard);
- response_start += t_wait_1 - t_wait_1_guard;
-
- // Keep administration of the first edge detection
- bool waiting_for_first_edge = true;
-
- // Did we detected any modulaiton at all
- bool detected_tag_modulation = false;
-
- // Use the current modulation state as starting point
- tag_modulation = lf_get_tag_modulation();
-
- // Reset the number of NRZ samples and use edge detection to detect them
- nrzs = 0;
- while (nrzs < max_nrzs) {
- // Get the timing of the next edge in number of wave periods
- periods = lf_count_edge_periods(128);
-
- // Are we dealing with the first incoming edge
- if (waiting_for_first_edge) {
- // Just break out of loop after an initial time-out (tag is probably not available)
- if (periods == 0) break;
- if (tag_modulation == 0) {
- // hitag replies always start with 11111 == 1010101010, if we see 0
- // it means we missed the first period, e.g. if the signal never crossed 0 since reader signal
- // so let's add it:
- nrz_samples[nrzs++] = tag_modulation ^ 1;
- // Register the number of periods that have passed
- // we missed the begin of response but we know it happened one period of 16 earlier
- response_start += periods - 16;
- response_duration = response_start;
- } else {
- // Register the number of periods that have passed
- response_start += periods;
- response_duration = response_start;
- }
- // Indicate that we have dealt with the first edge
- waiting_for_first_edge = false;
- // The first edge is always a single NRZ bit, force periods on 16
- periods = 16;
- // We have received more than 0 periods, so we have detected a tag response
- detected_tag_modulation = true;
- } else {
- // The function lf_count_edge_periods() returns 0 when a time-out occurs
- if (periods == 0) {
- //Dbprintf("Detected timeout after [%d] nrz samples", nrzs);
- break;
- }
- }
- // Evaluate the number of periods before the next edge
- if (periods > 24 && periods <= 64) {
- // Detected two sequential equal bits and a modulation switch
- // NRZ modulation: (11 => --|) or (11 __|)
- nrz_samples[nrzs++] = tag_modulation;
- nrz_samples[nrzs++] = tag_modulation;
- response_duration += periods;
- // Invert tag modulation state
- tag_modulation ^= 1;
- } else if (periods > 0 && periods <= 24) {
- // Detected one bit and a modulation switch
- // NRZ modulation: (1 => -|) or (0 _|)
- nrz_samples[nrzs++] = tag_modulation;
- response_duration += periods;
- tag_modulation ^= 1;
- } else {
- // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods
- //Dbprintf("Detected unexpected period count: %d", periods);
- break;
- }
- }
-
- // Store the TX frame, we do this now at this point, to avoid delay in processing
- // and to be able to overwrite the first samples with the trace (since they currently
- // still use the same memory space)
- if (txlen > 0) {
- LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true);
- }
-
- // Reset values for receiving frames
- memset(rx, 0x00, sizeof(rx));
- rxlen = 0;
-
- // If there is no response, just repeat the loop
- if (!detected_tag_modulation) continue;
-
- // Make sure we always have an even number of samples. This fixes the problem
- // of ending the manchester decoding with a zero. See the example below where
- // the '|' character is end of modulation
- // One at the end: ..._-|_____...
- // Zero at the end: ...-_|_____...
- // The last modulation change of a zero is not detected, but we should take
- // the half period in account, otherwise the demodulator will fail.
- if ((nrzs % 2) != 0) {
- nrz_samples[nrzs++] = tag_modulation;
- }
-
- LED_B_ON();
-
- // decode bitstream
- manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0);
-
- // decode frame
-
- // Verify if the header consists of five consecutive ones
- if (nrzs < 5) {
- Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
- break;
- } else {
- size_t i;
- for (i = 0; i < 5; i++) {
- if (nrz_samples[i] != 1) {
- Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i);
- break;
- }
- }
- if (i < 5) break;
- }
-
- // Pack the response into a byte array
- for (size_t i = 5; i < nrzs; i++) {
- uint8_t bit = nrz_samples[i];
- if (bit > 1) { // When Manchester detects impossible symbol it writes "7"
- Dbprintf("Error in Manchester decoding, abort");
- break;
- }
- rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
- rxlen++;
- }
-
- if (rxlen % 8 == 1) // skip spurious bit
- rxlen--;
-
- // Check if frame was captured and store it
- if (rxlen > 0) {
-
- LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
-
-// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52
-// Use delta time?
-// command_start = response_start + response_duration;
- command_start = 0;
- nrzs = 0;
- }
- }
-
-out:
- lf_finalize();
-
- // release allocated memory from BigBuff.
- BigBuf_free();
-
- if (bSuccessful)
- reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size);
- else
- reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0);
-}
-
-void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
-
- uint32_t command_start = 0;
- uint32_t command_duration = 0;
- uint32_t response_start = 0;
- uint32_t response_duration = 0;
- uint8_t rx[HITAG_FRAME_LEN];
- size_t rxlen = 0;
- uint8_t txbuf[HITAG_FRAME_LEN];
- uint8_t *tx = txbuf;
- size_t txlen = 0;
- int t_wait_1;
- int t_wait_1_guard = 8;
- int t_wait_2;
- size_t tag_size;
- bool bStop = false;
-
- // Raw demodulation/decoding by sampling edge periods
- size_t periods = 0;
-
- // Reset the return status
- bSuccessful = false;
- bCrypto = false;
-
- // Clean up trace and prepare it for storing frames
- set_tracing(true);
- clear_trace();
-
- DbpString("Starting Hitag writer family");
-
- // Check configuration
- switch (htf) {
- case WHT2F_CRYPTO: {
- DbpString("Authenticating using key:");
- memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
- memcpy(writedata, htd->crypto.data, 4);
- Dbhexdump(6, key, false);
- blocknr = page;
- bCrypto = false;
- bAuthenticating = false;
- writestate = WRITE_STATE_START;
- }
- break;
- case WHT2F_PASSWORD: {
- DbpString("Authenticating using password:");
- memcpy(password, htd->pwd.password, 4);
- memcpy(writedata, htd->crypto.data, 4);
- Dbhexdump(4, password, false);
- blocknr = page;
- bPwd = false;
- bAuthenticating = false;
- writestate = WRITE_STATE_START;
- }
- break;
- default: {
- Dbprintf("Error, unknown function: %d", htf);
- return;
- }
- break;
- }
-
- LED_D_ON();
-
- hitag2_init();
-
- // init as reader
- lf_init(true, false);
-
- // Tag specific configuration settings (sof, timings, etc.)
- if (htf < 10) {
- // hitagS settings
- t_wait_1 = 204;
- t_wait_2 = 128;
- /*tag_size = 256;*/
- flipped_bit = 0;
- tag_size = 8;
- DbpString("Configured for hitagS writer");
- } else if (htf < 20) {
- // hitag1 settings
- t_wait_1 = 204;
- t_wait_2 = 128;
- tag_size = 256;
- flipped_bit = 0;
- DbpString("Configured for hitag1 writer");
- } else if (htf < 30) {
- // hitag2 settings
- t_wait_1 = HITAG_T_WAIT_1_MIN;
- t_wait_2 = HITAG_T_WAIT_2_MIN;
- tag_size = 48;
- DbpString("Configured for hitag2 writer");
- } else {
- Dbprintf("Error, unknown hitag writer type: %d", htf);
- return;
- }
-
- uint8_t tag_modulation;
- size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit
- uint8_t nrz_samples[max_nrzs];
- size_t nrzs = 0;
-
- int16_t checked = 0;
- while (!bStop) {
-
- // only every 1000th times, in order to save time when collecting samples.
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) {
- checked = -1;
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
- WDT_HIT();
-
- // By default reset the transmission buffer
- tx = txbuf;
- switch (htf) {
- case WHT2F_CRYPTO: {
- bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true);
- break;
- }
- case WHT2F_PASSWORD: {
- bStop = !hitag2_password(rx, rxlen, tx, &txlen, true);
- break;
- }
- default: {
- Dbprintf("Error, unknown function: %d", htf);
- goto out;
- }
- }
-
- // Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
- lf_wait_periods(t_wait_2);
- command_start += t_wait_2;
-
- // Transmit the reader frame
- command_duration = hitag_reader_send_frame(tx, txlen);
-
- response_start = command_start + command_duration;
-
- // Let the antenna and ADC values settle
- // And find the position where edge sampling should start
- lf_wait_periods(t_wait_1 - t_wait_1_guard);
- response_start += t_wait_1 - t_wait_1_guard;
-
- // Keep administration of the first edge detection
- bool waiting_for_first_edge = true;
-
- // Did we detected any modulaiton at all
- bool detected_tag_modulation = false;
-
- // Use the current modulation state as starting point
- tag_modulation = lf_get_tag_modulation();
-
- // Reset the number of NRZ samples and use edge detection to detect them
- nrzs = 0;
- while (nrzs < max_nrzs) {
- // Get the timing of the next edge in number of wave periods
- periods = lf_count_edge_periods(128);
-
- // Are we dealing with the first incoming edge
- if (waiting_for_first_edge) {
- // Just break out of loop after an initial time-out (tag is probably not available)
- if (periods == 0) break;
- if (tag_modulation == 0) {
- // hitag replies always start with 11111 == 1010101010, if we see 0
- // it means we missed the first period, e.g. if the signal never crossed 0 since reader signal
- // so let's add it:
- nrz_samples[nrzs++] = tag_modulation ^ 1;
- // Register the number of periods that have passed
- // we missed the begin of response but we know it happened one period of 16 earlier
- response_start += periods - 16;
- response_duration = response_start;
- } else {
- // Register the number of periods that have passed
- response_start += periods;
- response_duration = response_start;
- }
- // Indicate that we have dealt with the first edge
- waiting_for_first_edge = false;
- // The first edge is always a single NRZ bit, force periods on 16
- periods = 16;
- // We have received more than 0 periods, so we have detected a tag response
- detected_tag_modulation = true;
- } else {
- // The function lf_count_edge_periods() returns 0 when a time-out occurs
- if (periods == 0) {
- //Dbprintf("Detected timeout after [%d] nrz samples", nrzs);
- break;
- }
- }
- // Evaluate the number of periods before the next edge
- if (periods > 24 && periods <= 64) {
- // Detected two sequential equal bits and a modulation switch
- // NRZ modulation: (11 => --|) or (11 __|)
- nrz_samples[nrzs++] = tag_modulation;
- nrz_samples[nrzs++] = tag_modulation;
- response_duration += periods;
- // Invert tag modulation state
- tag_modulation ^= 1;
- } else if (periods > 0 && periods <= 24) {
- // Detected one bit and a modulation switch
- // NRZ modulation: (1 => -|) or (0 _|)
- nrz_samples[nrzs++] = tag_modulation;
- response_duration += periods;
- tag_modulation ^= 1;
- } else {
- // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods
- //Dbprintf("Detected unexpected period count: %d", periods);
- break;
- }
- }
-
- // Wait some extra time for flash to be programmed
- //
-
- // Store the TX frame, we do this now at this point, to avoid delay in processing
- // and to be able to overwrite the first samples with the trace (since they currently
- // still use the same memory space)
- if (txlen > 0) {
- LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true);
- }
-
- // Reset values for receiving frames
- memset(rx, 0x00, sizeof(rx));
- rxlen = 0;
-
- // If there is no response, just repeat the loop
- if (!detected_tag_modulation) continue;
-
- // Make sure we always have an even number of samples. This fixes the problem
- // of ending the manchester decoding with a zero. See the example below where
- // the '|' character is end of modulation
- // One at the end: ..._-|_____...
- // Zero at the end: ...-_|_____...
- // The last modulation change of a zero is not detected, but we should take
- // the half period in account, otherwise the demodulator will fail.
- if ((nrzs % 2) != 0) {
- nrz_samples[nrzs++] = tag_modulation;
- }
-
- LED_B_ON();
-
- // decode bitstream
- manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0);
-
- // decode frame
-
- // Verify if the header consists of five consecutive ones
- if (nrzs < 5) {
- break;
- } else {
- size_t i;
- for (i = 0; i < 5; i++) {
- if (nrz_samples[i] != 1) {
- Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i);
- break;
- }
- }
- if (i < 5) break;
- }
-
- // Pack the response into a byte array
- for (size_t i = 5; i < nrzs; i++) {
- uint8_t bit = nrz_samples[i];
- if (bit > 1) { // When Manchester detects impossible symbol it writes "7"
- break;
- }
- rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
- rxlen++;
- }
-
- if (rxlen % 8 == 1) // skip spurious bit
- rxlen--;
-
- // Check if frame was captured and store it
- if (rxlen > 0) {
- LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
- command_start = 0;
- }
- }
-
-
-out:
- lf_finalize();
-
- // release allocated memory from BigBuff.
- BigBuf_free();
-
- reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2.h b/pm3rdv4rrg/src/main/cpp/armsrc/hitag2.h
deleted file mode 100644
index ec3d0d7f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//-----------------------------------------------------------------------------
-// (c) 2012 Roel Verdult
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Hitag2 type prototyping
-//-----------------------------------------------------------------------------
-
-#ifndef _HITAG2_H_
-#define _HITAG2_H_
-
-#include "common.h"
-#include "hitag.h"
-
-void SniffHitag2(void);
-void SimulateHitag2(bool tag_mem_supplied, uint8_t *data);
-void ReaderHitag(hitag_function htf, hitag_data *htd);
-void WriterHitag(hitag_function htf, hitag_data *htd, int page);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2_crypto.c b/pm3rdv4rrg/src/main/cpp/armsrc/hitag2_crypto.c
deleted file mode 100644
index 91c04ef4..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2_crypto.c
+++ /dev/null
@@ -1,119 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Hitag2 Crypto
-//
-// (c) 2009 Henryk Plötz
-// (c) 2012 Roel Verdult
-// (c) 2019 Iceman
-//-----------------------------------------------------------------------------
-#include "hitag2_crypto.h"
-
-#include "util.h"
-#include "string.h"
-
-/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
-// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
-// For educational purposes only.
-// No warranties or guarantees of any kind.
-// This code is released into the public domain by its author.
-
-// Single bit Hitag2 functions:
-#ifndef i4
-#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
-#endif
-
-static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
-static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
-static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
-
-uint32_t _f20(const uint64_t x) {
- uint32_t i5;
-
- i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
- + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
- + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4
- + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8
- + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16;
-
- return (ht2_f5c >> i5) & 1;
-}
-
-uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
- uint32_t i;
- uint64_t x = ((key & 0xFFFF) << 32) + serial;
-
- for (i = 0; i < 32; i++) {
- x >>= 1;
- x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
- }
- return x;
-}
-
-uint64_t _hitag2_round(uint64_t *state) {
- uint64_t x = *state;
-
- x = (x >> 1) +
- ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
- ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22)
- ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41)
- ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
-
- *state = x;
- return _f20(x);
-}
-
-// "MIKRON" = O N M I K R
-// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
-// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
-// Random = 65 6E 45 72 - Random IV, transmitted in clear
-//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
-
-// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
-// The inverse of the first 4 bytes is sent to the tag to authenticate.
-// The rest is encrypted by XORing it with the subsequent keystream.
-
-uint32_t _hitag2_byte(uint64_t *x) {
- uint32_t i, c;
- for (i = 0, c = 0; i < 8; i++) {
- c += (uint32_t) _hitag2_round(x) << (i ^ 7);
- }
- return c;
-}
-
-void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
- uint64_t key = ((uint64_t)tag->sectors[2][2]) |
- ((uint64_t)tag->sectors[2][3] << 8) |
- ((uint64_t)tag->sectors[1][0] << 16) |
- ((uint64_t)tag->sectors[1][1] << 24) |
- ((uint64_t)tag->sectors[1][2] << 32) |
- ((uint64_t)tag->sectors[1][3] << 40);
- uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
- ((uint32_t)tag->sectors[0][1] << 8) |
- ((uint32_t)tag->sectors[0][2] << 16) |
- ((uint32_t)tag->sectors[0][3] << 24);
- uint32_t iv_ = (((uint32_t)(iv[0]))) |
- (((uint32_t)(iv[1])) << 8) |
- (((uint32_t)(iv[2])) << 16) |
- (((uint32_t)(iv[3])) << 24);
- tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_));
-}
-
-int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
- uint8_t authenticator_should[4];
- authenticator_should[0] = ~_hitag2_byte(cs);
- authenticator_should[1] = ~_hitag2_byte(cs);
- authenticator_should[2] = ~_hitag2_byte(cs);
- authenticator_should[3] = ~_hitag2_byte(cs);
- return (memcmp(authenticator_should, authenticator_is, 4) == 0);
-}
-
-int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) {
- int i;
- for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs);
- for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i);
- return 0;
-}
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2_crypto.h b/pm3rdv4rrg/src/main/cpp/armsrc/hitag2_crypto.h
deleted file mode 100644
index 8544c7e1..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2_crypto.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __HITAG2_CRYPTO_H
-#define __HITAG2_CRYPTO_H
-
-#include "common.h"
-
-struct hitag2_tag {
- uint32_t uid;
- enum {
- TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
- TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password
- TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
- TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
- } state;
- uint16_t active_sector;
- uint8_t crypto_active;
- uint64_t cs;
- uint8_t sectors[12][4];
-};
-
-uint32_t _f20(const uint64_t x);
-uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV);
-uint64_t _hitag2_round(uint64_t *state);
-uint32_t _hitag2_byte(uint64_t *x);
-void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
-int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
-int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2crack.c b/pm3rdv4rrg/src/main/cpp/armsrc/hitag2crack.c
deleted file mode 100644
index c6b61b01..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitag2crack.c
+++ /dev/null
@@ -1,923 +0,0 @@
-//-----------------------------------------------------------------------------
-// Kevin Sheldrake , Aug 2018
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//
-// iceman, Jan, 2020
-// doegox, Jan, 2020
-//-----------------------------------------------------------------------------
-// hitag2 attack functions
-//-----------------------------------------------------------------------------
-
-#include "hitagcrypto.h"
-#include "hitag2crack.h"
-
-#define READP0CMD "1100000111"
-#define ERROR_RESPONSE "F402889C"
-
-extern const uint8_t Hitag2Sync[5];
-extern bool CryptoActive;
-extern Hitag_State Hitag_Crypto_State;
-
-// hitag2_crack implements the first crack algorithm described in the paper,
-// Gone In 360 Seconds by Verdult, Garcia and Balasch.
-// response is a multi-line text response containing the 8 pages of the
-// cracked tag;
-// nrarhex is a string containing hex representations of the 32 bit nR and aR
-// values (separated by a space) snooped using SNIFF-PWM.
-bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
- uint8_t uidhex[9];
- uint8_t uid[32];
- uint8_t nrar[64];
- uint8_t e_firstcmd[10];
- uint8_t e_page0cmd[10];
- uint8_t keybits[42];
- uint8_t pagehex[9];
- uint8_t temp[20];
- int i;
- uint8_t *spaceptr = NULL;
-
- // get uid as hexstring
- if(!hitag2_get_uid(uidhex))
- {
- UserMessage("Cannot get UID\r\n");
- return false;
- }
-
- // convert uid hexstring to binarray
- hextobinarray(uid, uidhex);
-
- // convert nR and aR hexstrings to binarray
- spaceptr = strchr(nrarhex, ' ');
- if (!spaceptr)
- {
- UserMessage("Please supply a valid nR aR pair\r\n");
- return false;
- }
- *spaceptr = 0x00;
-
- if (hextobinarray(nrar, nrarhex) != 32)
- {
- UserMessage("nR is not 32 bits long\r\n");
- return false;
- }
-
- if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
- {
- UserMessage("aR is not 32 bits long\r\n");
- return false;
- }
-
- // find a valid encrypted command
- if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
- {
- UserMessage("Cannot find a valid encrypted command\r\n");
- return false;
- }
-
- // find the 'read page 0' command and recover key stream
- if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
- {
- UserMessage("Cannot find encrypted 'read page0' command\r\n");
- return false;
- }
-
- // empty the response string
- response[0] = 0x00;
-
- // read all pages using key stream
- for (i=0; i<8; i++)
- {
- if (hitag2crack_read_page(pagehex, i, nrar, keybits))
- {
- sprintf(temp, "%1d: %s\r\n", i, pagehex);
- }
- else
- {
- sprintf(temp, "%1d:\r\n", i);
- }
- // add page string to response
- strcat(response, temp);
- }
-
- return true;
-}
-
-// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
-// with a different sequential encrypted command value in order to find one
-// that returns a valid response.
-// e_cmd is the returned binarray of the valid encrypted command;
-// nrar is the binarray of the 64 bit nR aR pair.
-bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
- uint8_t guess[10];
- uint8_t responsestr[9];
-
-// UserMessage("Finding valid encrypted command:");
- // we're going to hold bits 5, 7, 8 and 9 and brute force the rest
- // e.g. x x x x x 0 x 0 0 0
- for (uint8_t a=0; a<2; a++) {
- for (uint8_t b=0; b<2; b++) {
- for (uint8_t c=0; c<2; c++) {
- for (uint8_t d=0; d<2; d++) {
- for (uint8_t e=0; e<2; e++) {
- for (uint8_t g=0; g<2; g++) {
- // build binarray
- guess[0] = a;
- guess[1] = b;
- guess[2] = c;
- guess[3] = d;
- guess[4] = e;
- guess[5] = 0;
- guess[6] = g;
- guess[7] = 0;
- guess[8] = 0;
- guess[9] = 0;
-
- // send guess
- if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
- // check if it was valid
- if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
- // return the guess as the encrypted command
- memcpy(e_cmd, guess, 10);
- return true;
- }
- } else {
-#ifdef RFIDLER_DEBUG
- UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
-#endif
- }
- UserMessage(".");
- }
- }
- }
- }
- }
- }
-// UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n");
- return false;
-}
-
-// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
-// valid encrypted command and tests the results by attempting an extended
-// command version of the command to see if that produces a valid response.
-// keybits is the returned binarray of the recovered key stream;
-// e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
-// e_firstcmd is the binarray of the first valid encrypted command found;
-// nrar is the binarray of the 64 bit nR aR pair;
-// uid is the binarray of the 32 bit UID.
-bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) {
- uint8_t a, b, c, d;
- uint8_t guess[10];
- uint8_t responsestr[9];
- uint8_t e_uid[32];
-
- UserMessage("Finding 'read page 0' command:");
- // we're going to brute the missing 4 bits of the valid encrypted command
- for (a=0; a<2; a++)
- {
- for (b=0; b<2; b++)
- {
- for (c=0; c<2; c++)
- {
- for (d=0; d<2; d++)
- {
- // create our guess by bit flipping the pattern of bits
- // representing the inverted bit and the 3 page bits
- // in both the non-inverted and inverted parts of the
- // encrypted command.
- memcpy(guess, e_firstcmd, 10);
- if (a)
- {
- guess[5] = !guess[5];
- guess[0] = !guess[0];
- }
- if (b)
- {
- guess[7] = !guess[7];
- guess[2] = !guess[2];
- }
- if (c)
- {
- guess[8] = !guess[8];
- guess[3] = !guess[3];
- }
- if (d)
- {
- guess[9] = !guess[9];
- guess[4] = !guess[4];
- }
-
- // try the guess
- if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10))
- {
- // check if it was valid
- if (strcmp(responsestr, ERROR_RESPONSE) != 0)
- {
- // convert response to binarray
- hextobinarray(e_uid, responsestr);
- // test if the guess was 'read page 0' command
- if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid))
- {
-
- return true;
- }
- }
- else
- {
-#ifdef RFIDLER_DEBUG
- UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
-#endif
- }
- }
- else
- {
- #ifdef RFIDLER_DEBUG
- UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
-#endif
- }
- UserMessage(".");
- }
- }
- }
- }
- UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n");
- return false;
-}
-
-// hitag2crack_test_e_p0cmd XORs the message (command + response) with the
-// encrypted version to retrieve the key stream. It then uses this key stream
-// to encrypt an extended version of the READP0CMD and tests if the response
-// is valid.
-// keybits is the returned binarray of the key stream;
-// nrar is the 64 bit binarray of nR aR pair;
-// e_cmd is the binarray of the encrypted command;
-// uid is the binarray of the card UID;
-// e_uid is the binarray of the encrypted version of the UID.
-bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) {
- uint8_t cipherbits[42];
- uint8_t plainbits[42];
- uint8_t ext_cmd[40];
- uint8_t e_ext_cmd[40];
- uint8_t responsestr[9];
- int i;
-
- // copy encrypted cmd to cipherbits
- memcpy(cipherbits, e_cmd, 10);
-
- // copy encrypted uid to cipherbits
- memcpy(cipherbits + 10, e_uid, 32);
-
- // copy cmd to plainbits
- binstringtobinarray(plainbits, READP0CMD);
-
- // copy uid to plainbits
- memcpy(plainbits + 10, uid, 32);
-
- // xor the plainbits with the cipherbits to get keybits
- hitag2crack_xor(keybits, plainbits, cipherbits, 42);
-
- // create extended cmd -> 4 * READP0CMD = 40 bits
- for (i=0; i<4; i++)
- {
- binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
- }
-
- // xor extended cmd with keybits
- hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
-
- // send extended encrypted cmd
- if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40))
- {
- // test if it was valid
- if (strcmp(responsestr, ERROR_RESPONSE) != 0)
- {
- return true;
- }
- }
- else
- {
-#ifdef RFIDLER_DEBUG
- UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
-#endif
- }
-
- return false;
-
-}
-
-// hitag2crack_xor XORs the source with the pad to produce the target.
-// source, target and pad are binarrays of length len.
-void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
-
- for (int i=0; i 7))
- {
- UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
- return false;
- }
-
- // create cmd
- binstringtobinarray(cmd, READP0CMD);
- if (pagenum & 0x1)
- {
- cmd[9] = !cmd[9];
- cmd[4] = !cmd[4];
- }
- if (pagenum & 0x2)
- {
- cmd[8] = !cmd[8];
- cmd[3] = !cmd[3];
- }
- if (pagenum & 0x4)
- {
- cmd[7] = !cmd[7];
- cmd[2] = !cmd[2];
- }
-
- // encrypt command
- hitag2crack_xor(e_cmd, cmd, keybits, 10);
-
- // send encrypted command
- if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10))
- {
- // check if it is valid
- if (strcmp(e_responsestr, ERROR_RESPONSE) != 0)
- {
- // convert to binarray
- hextobinarray(e_response, e_responsestr);
- // decrypt response
- hitag2crack_xor(response, e_response, keybits + 10, 32);
- // convert to hexstring
- binarraytohex(responsestr, response, 32);
- return true;
- }
- else
- {
- UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
- }
- }
- else
- {
- UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
- }
-
- return false;
-}
-
-// hitag2crack_send_e_cmd replays the auth and sends the given encrypted
-// command.
-// responsestr is the hexstring of the response to the command;
-// nrar is the 64 bit binarray of the nR aR pair;
-// cmd is the binarray of the encrypted command to send;
-// len is the length of the encrypted command.
-bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) {
- uint8_t tmp[37];
- uint8_t uid[9];
- uint8_t e_page3str[9];
- int ret = 0;
-
- // get the UID
- if(!hitag2_get_uid(uid))
- {
- UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
- return false;
- }
-
- // START_AUTH kills active crypto session
- CryptoActive = false;
-
- // get the UID again
- if(!hitag2_get_uid(uid))
- {
- UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
- return false;
- }
-
- // send nrar and receive (useless) encrypted page 3 value
- if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
- {
- UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
- return false;
- }
-
- // send encrypted command
- if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false))
- {
-#ifdef RFIDLER_DEBUG
- UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
-#endif
- return false;
- }
-
- return true;
-}
-
-// hitag2crack_tx_rx transmits a message and receives a response.
-// responsestr is the hexstring of the response;
-// msg is the binarray of the message to send;
-// state is the RWD state;
-// reset indicates whether to reset RWD state after.
-bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) {
- uint8_t tmp[37];
- int ret = 0;
-
- // START_AUTH kills active crypto session
- CryptoActive= false;
-
- if(!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX))
- {
- UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
- return false;
- }
-
- // skip 1/2 bit to synchronise manchester
- HW_Skip_Bits = 1;
- ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY);
-
- // check if response was a valid length (5 sync bits + 32 bits response)
- if (ret == 37)
- {
- // check sync bits
- if (memcmp(tmp, Hitag2Sync, 5) != 0)
- {
- UserMessage("hitag2crack_tx_rx: no sync\r\n");
- return false;
- }
-
- // convert response to hexstring
- binarraytohex(responsestr, tmp + 5, 32);
- return true;
- }
- else
- {
-#ifdef RFIDLER_DEBUG
- UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
-#endif
- return false;
- }
- return false;
-}
-
-
-bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
- uint64_t sharedkey;
- uint32_t serialnum;
- uint32_t initvector;
- uint8_t *spaceptr;
- uint8_t *dataptr;
-
- // extract vals from input
- dataptr = input;
- spaceptr = strchr(dataptr, ' ');
- if (!spaceptr)
- {
- UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
- return false;
- }
-
- *spaceptr = 0x00;
-
- if (strlen(dataptr) != 12)
- {
- UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
- return false;
- }
-
- sharedkey = rev64(hexreversetoulonglong(dataptr));
-
- dataptr = spaceptr+1;
- spaceptr = strchr(dataptr, ' ');
- if (!spaceptr)
- {
- UserMessage("/r/nno UID\r\n");
- return false;
- }
-
- *spaceptr = 0x00;
- if (strlen(dataptr) != 8)
- {
- UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
- return false;
- }
-
- serialnum = rev32(hexreversetoulong(dataptr));
-
- dataptr = spaceptr+1;
-
- if (strlen(dataptr) != 8)
- {
- UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
- return false;
- }
-
- initvector = rev32(hexreversetoulong(dataptr));
-
- // start up crypto engine
- hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
-
- strcpy(response, "Success\r\n");
-
- return true;
-}
-
-bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
- uint8_t bin[32];
- uint8_t binhex[9];
- uint8_t binstr[33];
- uint32_t binulong;
-
- if (strlen(hex) != 8)
- {
- UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
- return false;
- }
-
- binulong = hextoulong(hex);
-
- ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
- binarraytobinstring(binstr, bin, 32);
- binarraytohex(binhex, bin, 32);
-// UserMessage("ar = %s\r\n", binstr);
-// UserMessage("arhex = %s\r\n", binhex);
-
- strcpy(response, binhex);
- return true;
-}
-
-bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
- uint8_t bin[32];
- uint8_t e_bin[32];
- uint8_t binstr[33];
- uint32_t binulong;
- int len;
-
- len = strlen(e_binstr);
- if (len > 32)
- {
- UserMessage("\r\nbinary string must be <= 32 bits\r\n");
- return false;
- }
-
- binstringtobinarray(e_bin, e_binstr);
- binulong = binarraytoulong(e_bin, len);
-
- ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
- binarraytobinstring(binstr, bin, len);
- strcpy(response, binstr);
- return true;
-}
-
-bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
- // XOR pad so encrypt == decrypt :)
- return hitag2crack_decrypt_hex(response, hex);
-}
-
-bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
- return hitag2crack_decrypt_bin(response, e_binstr);
-}
-
-// hitag2_keystream uses the first crack algorithm described in the paper,
-// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
-// of keystream.
-// response is a multi-line text response containing the hex of the keystream;
-// nrarhex is a string containing hex representations of the 32 bit nR and aR
-// values (separated by a space) snooped using SNIFF-PWM.
-bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
- uint8_t uidhex[9];
- uint8_t uid[32];
- uint8_t nrar[64];
- uint8_t e_firstcmd[10];
- uint8_t e_page0cmd[10];
-// uint8_t keybits[2080];
- uint8_t *keybits = DataBuff;
- uint8_t keybitshex[67];
- int kslen;
- int ksoffset;
- uint8_t pagehex[9];
- uint8_t temp[20];
- int i;
- uint8_t *spaceptr = NULL;
-
-/*
- keybits = malloc(2080);
- if (!keybits) {
- UserMessage("cannot malloc keybits\r\n");
- return false;
- }
-*/
-
- // get uid as hexstring
- if(!hitag2_get_uid(uidhex))
- {
- UserMessage("Cannot get UID\r\n");
- return false;
- }
-
- // convert uid hexstring to binarray
- hextobinarray(uid, uidhex);
-
- // convert nR and aR hexstrings to binarray
- spaceptr = strchr(nrarhex, ' ');
- if (!spaceptr)
- {
- UserMessage("Please supply a valid nR aR pair\r\n");
- return false;
- }
- *spaceptr = 0x00;
-
- if (hextobinarray(nrar, nrarhex) != 32)
- {
- UserMessage("nR is not 32 bits long\r\n");
- return false;
- }
-
- if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
- {
- UserMessage("aR is not 32 bits long\r\n");
- return false;
- }
-
- // find a valid encrypted command
- if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
- {
- UserMessage("Cannot find a valid encrypted command\r\n");
- return false;
- }
-
- // find the 'read page 0' command and recover key stream
- if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
- {
- UserMessage("Cannot find encrypted 'read page0' command\r\n");
- return false;
- }
-
- // using the 40 bits of keystream in keybits, sending commands with ever
- // increasing lengths to acquire 2048 bits of key stream.
- kslen = 40;
-
- while (kslen < 2048)
- {
- ksoffset = 0;
- if (!hitag2crack_send_auth(nrar))
- {
- UserMessage("hitag2crack_send_auth failed\r\n");
- return false;
- }
- // while we have at least 52 bits of keystream, consume it with
- // extended read page 0 commands. 52 = 10 (min command len) +
- // 32 (response) + 10 (min command len we'll send)
- while ((kslen - ksoffset) >= 52)
- {
- // consume the keystream, updating ksoffset as we go
- if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar))
- {
- UserMessage("hitag2crack_consume_keystream failed\r\n");
- return false;
- }
- }
- // send an extended command to retrieve more keystream, updating kslen
- // as we go
- if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid))
- {
- UserMessage("hitag2crack_extend_keystream failed\r\n");
- return false;
- }
- UserMessage("Recovered %d bits of keystream\r\n", kslen);
-
- }
-
- for (i=0; i<2048; i+=256)
- {
- binarraytohex(keybitshex, keybits + i, 256);
- UserMessage("%s\r\n", keybitshex);
- }
-
- response[0] = 0x00;
-
- return true;
-}
-
-// hitag2crack_send_auth replays the auth and returns.
-// nrar is the 64 bit binarray of the nR aR pair;
-bool hitag2crack_send_auth(uint8_t *nrar) {
- uint8_t uid[9];
- uint8_t e_page3str[9];
-
- // get the UID
- if(!hitag2_get_uid(uid))
- {
- UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
- return false;
- }
-
- // START_AUTH kills active crypto session
- CryptoActive = false;
-
- // get the UID again
- if(!hitag2_get_uid(uid))
- {
- UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
- return false;
- }
-
- // send nrar and receive (useless) encrypted page 3 value
- if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
- {
- UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
- return false;
- }
- return true;
-}
-
-// hitag2crack_consume_keystream sends an extended command (up to 510 bits in
-// length) to consume keystream.
-// keybits is the binarray of keystream bits;
-// kslen is the length of keystream;
-// ksoffset is a pointer to the current keystream offset (updated by this fn);
-// nrar is the 64 bit binarray of the nR aR pair.
-bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) {
- int conlen;
- int numcmds;
- int i;
- uint8_t ext_cmd[510];
- uint8_t e_ext_cmd[510];
- uint8_t responsestr[9];
-
- // calculate the length of keybits to consume with the extended command.
- // 42 = 32 bit response + 10 bit command reserved for next command. conlen
- // cannot be longer than 510 bits to fit into the small RWD buffer.
- conlen = kslen - *ksoffset - 42;
- if (conlen < 10)
- {
- UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
- return false;
- }
-
- // sanitise conlen
- if (conlen > 510)
- {
- conlen = 510;
- }
-
- // calculate how many repeated commands to send in this extended command.
- numcmds = conlen / 10;
-
- // build extended command
- for (i=0; i, Aug 2018
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions hitag2 attack functions
-//-----------------------------------------------------------------------------
-
-bool hitag2_crack(uint8_t *response, uint8_t *nrarhex);
-bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]);
-bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]);
-bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid);
-void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len);
-bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits);
-bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len);
-bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset);
-
-bool hitag2crack_rng_init(uint8_t *response, uint8_t *input);
-bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex);
-bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *hex);
-bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex);
-bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *hex);
-
-bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex);
-bool hitag2crack_send_auth(uint8_t *nrar);
-bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar);
-bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid);
-
-bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive);
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitagS.c b/pm3rdv4rrg/src/main/cpp/armsrc/hitagS.c
deleted file mode 100644
index a0a2a771..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitagS.c
+++ /dev/null
@@ -1,2061 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// HitagS emulation (preliminary test version)
-//
-// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
-//
-//-----------------------------------------------------------------------------
-// Some code was copied from Hitag2.c
-//-----------------------------------------------------------------------------
-
-#include "hitagS.h"
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "string.h"
-#include "commonutil.h"
-#include "hitag2_crypto.h"
-
-#define CRC_PRESET 0xFF
-#define CRC_POLYNOM 0x1D
-
-static bool bQuiet;
-static bool bSuccessful;
-static struct hitagS_tag tag;
-static uint8_t page_to_be_written = 0;
-static int block_data_left = 0;
-
-typedef enum modulation {
- AC2K = 0,
- AC4K,
- MC4K,
- MC8K
-} MOD;
-
-static MOD m = AC2K; // used modulation
-static uint32_t temp_uid;
-static int temp2 = 0;
-static int sof_bits; // number of start-of-frame bits
-static uint8_t pwdh0, pwdl0, pwdl1; // password bytes
-static uint32_t rnd = 0x74124485; // randomnumber
-size_t blocknr;
-bool end = false;
-//#define SENDBIT_TEST
-
-#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b))
-#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b)))
-#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
-
-// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
-// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
-// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
-// T0 = TIMER_CLOCK1 / 125000 = 192
-#ifndef T0
-#define T0 192
-#endif
-
-#define HITAG_FRAME_LEN 20
-#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
-#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
-#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
-#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
-//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
-#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
-#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */
-#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */
-#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
-
-#define HITAG_T_TAG_ONE_HALF_PERIOD 10
-#define HITAG_T_TAG_TWO_HALF_PERIOD 25
-#define HITAG_T_TAG_THREE_HALF_PERIOD 41
-#define HITAG_T_TAG_FOUR_HALF_PERIOD 57
-
-#define HITAG_T_TAG_HALF_PERIOD 16
-#define HITAG_T_TAG_FULL_PERIOD 32
-
-#define HITAG_T_TAG_CAPTURE_ONE_HALF 13
-#define HITAG_T_TAG_CAPTURE_TWO_HALF 25
-#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
-#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
-
-#define DEBUG 0
-
-/*
- * Implementation of the crc8 calculation from Hitag S
- * from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf
- */
-void calc_crc(unsigned char *crc, unsigned char data, unsigned char Bitcount) {
- *crc ^= data; // crc = crc (exor) data
- do {
- if (*crc & 0x80) { // if (MSB-CRC == 1)
- *crc <<= 1; // CRC = CRC Bit-shift left
- *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM
- } else {
- *crc <<= 1; // CRC = CRC Bit-shift left
- }
- } while (--Bitcount);
-}
-
-static void hitag_send_bit(int bit) {
- LED_A_ON();
- // Reset clock for the next bit
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- switch (m) {
- case AC2K:
- if (bit == 0) {
- // AC Coding --__
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 32) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 64) {};
-
- } else {
- // AC coding -_-_
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 16) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 32) {};
-
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 48) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 64) {};
-
- }
- LED_A_OFF();
- break;
- case AC4K:
- if (bit == 0) {
- // AC Coding --__
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD) {};
-
- } else {
- // AC coding -_-_
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 8) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 16) {};
-
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 24) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 32) {};
- }
- LED_A_OFF();
- break;
- case MC4K:
- if (bit == 0) {
- // Manchester: Unloaded, then loaded |__--|
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 16) {};
-
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 32) {};
-
- } else {
- // Manchester: Loaded, then unloaded |--__|
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 16) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 32) {};
-
- }
- LED_A_OFF();
- break;
- case MC8K:
- if (bit == 0) {
- // Manchester: Unloaded, then loaded |__--|
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 8) {};
-
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 16) {};
-
- } else {
- // Manchester: Loaded, then unloaded |--__|
- HIGH(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 8) {};
-
- LOW(GPIO_SSC_DOUT);
- while (AT91C_BASE_TC0->TC_CV < T0 * 16) {};
-
- }
- LED_A_OFF();
- break;
- default:
- break;
- }
-}
-
-static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
- // SOF - write start of frame
- for (size_t i = 0; i < sof_bits; i++) {
- hitag_send_bit(1);
- }
-
- // Send the content of the frame
- for (size_t i = 0; i < frame_len; i++) {
- hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
- }
-
- LOW(GPIO_SSC_DOUT);
-}
-
-static void hitag_reader_send_bit(int bit) {
-
- LED_A_ON();
- // Reset clock for the next bit
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- // Binary puls length modulation (BPLM) is used to encode the data stream
- // This means that a transmission of a one takes longer than that of a zero
-
- HIGH(GPIO_SSC_DOUT);
-
-#ifdef SENDBIT_TEST
- // Wait for 4-10 times the carrier period
- while (AT91C_BASE_TC0->TC_CV < T0 * 6) {};
-
- LOW(GPIO_SSC_DOUT);
-
- if (bit == 0) {
- // Zero bit: |_-|
- while (AT91C_BASE_TC0->TC_CV < T0 * 11) {};
- } else {
- // One bit: |_--|
- while (AT91C_BASE_TC0->TC_CV < T0 * 14) {};
- }
-#else
- // Wait for 4-10 times the carrier period
- while (AT91C_BASE_TC0->TC_CV < T0 * 6) {};
-
- LOW(GPIO_SSC_DOUT);
-
- if (bit == 0) {
- // Zero bit: |_-|
- while (AT91C_BASE_TC0->TC_CV < T0 * 22) {};
- } else {
- // One bit: |_--|
- while (AT91C_BASE_TC0->TC_CV < T0 * 28) {};
- }
-#endif
-
- LED_A_OFF();
-}
-
-static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
- // Send the content of the frame
- for (size_t i = 0; i < frame_len; i++) {
-// if (frame[0] == 0xf8) {
- //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1);
-// }
- hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
- }
- // write EOF
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- HIGH(GPIO_SSC_DOUT);
-
- // Wait for 4-10 times the carrier period
- while (AT91C_BASE_TC0->TC_CV < T0 * 6) {};
-
- LOW(GPIO_SSC_DOUT);
-}
-
-/*
- * to check if the right uid was selected
- */
-static int check_select(uint8_t *rx, uint32_t uid) {
- unsigned char resp[48];
- uint32_t ans = 0x0;
- for (int i = 0; i < 48; i++)
- resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1;
- for (int i = 0; i < 32; i++)
- ans += resp[5 + i] << (31 - i);
-
- temp_uid = ans;
- if (ans == tag.uid)
- return 1;
-
- return 0;
-}
-
-/*
- * handles all commands from a reader
- */
-static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
- uint8_t *tx, size_t *txlen) {
- uint8_t rx_air[HITAG_FRAME_LEN];
- uint64_t state;
- unsigned char crc;
-
- // Copy the (original) received frame how it is write over the air
- memcpy(rx_air, rx, nbytes(rxlen));
-
- // Reset the transmission frame length
- *txlen = 0;
-
- // Try to find out which command was write by selecting on length (in bits)
- switch (rxlen) {
- case 5: {
- //UID request with a selected response protocol mode
- tag.pstate = HT_READY;
- tag.tstate = HT_NO_OP;
- if ((rx[0] & 0xf0) == 0x30) {
- tag.mode = HT_STANDARD;
- sof_bits = 1;
- m = AC2K;
- }
- if ((rx[0] & 0xf0) == 0xc0) {
- tag.mode = HT_ADVANCED;
- sof_bits = 3;
- m = AC2K;
- }
-
- if ((rx[0] & 0xf0) == 0xd0) {
- tag.mode = HT_FAST_ADVANCED;
- sof_bits = 3;
- m = AC4K;
- }
- //write uid as a response
- *txlen = 32;
- for (int i = 0; i < 4; i++)
- tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff;
- }
- break;
- case 45: {
- //select command from reader received
- if (check_select(rx, tag.uid) == 1) {
- //if the right tag was selected
- *txlen = 32;
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
-
- //write configuration
- for (int i = 0; i < 4; i++)
- tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff;
- tx[3] = 0xff;
- if (tag.mode != HT_STANDARD) {
- *txlen = 40;
- crc = CRC_PRESET;
- for (int i = 0; i < 4; i++)
- calc_crc(&crc, tx[i], 8);
- tx[4] = crc;
- }
- }
- }
- break;
- case 64: {
- //challenge message received
- Dbprintf("Challenge for UID: %X", temp_uid);
- temp2++;
- *txlen = 32;
- state = _hitag2_init(REV64(tag.key),
- REV32(tag.pages[0][0]),
- REV32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))
- );
- Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
- rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
-
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
-
- for (int i = 0; i < 4; i++)
- _hitag2_byte(&state);
-
- //write con2, pwdh0, pwdl0, pwdl1 encrypted as a response
- tx[0] = _hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff);
- tx[1] = _hitag2_byte(&state) ^ tag.pwdh0;
- tx[2] = _hitag2_byte(&state) ^ tag.pwdl0;
- tx[3] = _hitag2_byte(&state) ^ tag.pwdl1;
- if (tag.mode != HT_STANDARD) {
- //add crc8
- *txlen = 40;
- crc = CRC_PRESET;
- calc_crc(&crc, ((tag.pages[0][1] >> 16) & 0xff), 8);
- calc_crc(&crc, tag.pwdh0, 8);
- calc_crc(&crc, tag.pwdl0, 8);
- calc_crc(&crc, tag.pwdl1, 8);
- tx[4] = (crc ^ _hitag2_byte(&state));
- }
- /*
- * some readers do not allow to authenticate multiple times in a row with the same tag.
- * use this to change the uid between authentications.
-
- if (temp2 % 2 == 0) {
- tag.uid = 0x11223344;
- tag.pages[0][0] = 0x44332211;
- } else {
- tag.uid = 0x55667788;
- tag.pages[0][0] = 0x88776655;
- }
- */
- }
- case 40:
- //data received to be written
- if (tag.tstate == HT_WRITING_PAGE_DATA) {
- tag.tstate = HT_NO_OP;
- tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
- << 0) + (rx[1] << 8) + (rx[2] << 16) + (rx[3] << 24);
- //write ack
- *txlen = 2;
- tx[0] = 0x40;
- page_to_be_written = 0;
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
- } else if (tag.tstate == HT_WRITING_BLOCK_DATA) {
- tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
- << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3];
- //write ack
- *txlen = 2;
- tx[0] = 0x40;
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
- page_to_be_written++;
- block_data_left--;
- if (block_data_left == 0) {
- tag.tstate = HT_NO_OP;
- page_to_be_written = 0;
- }
- }
- break;
- case 20: {
- //write page, write block, read page or read block command received
- if ((rx[0] & 0xf0) == 0xc0) { //read page
- //write page data
- uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
- *txlen = 32;
- tx[0] = (tag.pages[page / 4][page % 4]) & 0xff;
- tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
- tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
- tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
- if (tag.LKP && page == 1)
- tx[3] = 0xff;
-
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
-
- if (tag.mode != HT_STANDARD) {
- //add crc8
- *txlen = 40;
- crc = CRC_PRESET;
- for (int i = 0; i < 4; i++)
- calc_crc(&crc, tx[i], 8);
- tx[4] = crc;
- }
-
- if (tag.LKP && (page == 2 || page == 3)) {
- //if reader asks for key or password and the LKP-mark is set do not respond
- sof_bits = 0;
- *txlen = 0;
- }
- } else if ((rx[0] & 0xf0) == 0xd0) { //read block
- uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
- *txlen = 32 * 4;
- //write page,...,page+3 data
- for (int i = 0; i < 4; i++) {
- tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff;
- tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
- tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
- tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
- page++;
- }
-
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
-
- if (tag.mode != HT_STANDARD) {
- //add crc8
- *txlen = 32 * 4 + 8;
- crc = CRC_PRESET;
- for (int i = 0; i < 16; i++)
- calc_crc(&crc, tx[i], 8);
- tx[16] = crc;
- }
-
- if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) {
- sof_bits = 0;
- *txlen = 0;
- }
- } else if ((rx[0] & 0xf0) == 0x80) { //write page
- uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
-
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
- if ((tag.LCON && page == 1)
- || (tag.LKP && (page == 2 || page == 3))) {
- //deny
- *txlen = 0;
- } else {
- //allow
- *txlen = 2;
- tx[0] = 0x40;
- page_to_be_written = page;
- tag.tstate = HT_WRITING_PAGE_DATA;
- }
-
- } else if ((rx[0] & 0xf0) == 0x90) { //write block
- uint8_t page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16);
- switch (tag.mode) {
- case HT_STANDARD:
- sof_bits = 1;
- m = MC4K;
- break;
- case HT_ADVANCED:
- sof_bits = 6;
- m = MC4K;
- break;
- case HT_FAST_ADVANCED:
- sof_bits = 6;
- m = MC8K;
- break;
- default:
- break;
- }
- if (page % 4 != 0 || page == 0) {
- //deny
- *txlen = 0;
- } else {
- //allow
- *txlen = 2;
- tx[0] = 0x40;
- page_to_be_written = page;
- block_data_left = 4;
- tag.tstate = HT_WRITING_BLOCK_DATA;
- }
- }
- }
- break;
- default:
-
- break;
- }
-}
-
-/*
- * to autenticate to a tag with the given key or challenge
- */
-static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
- uint8_t rx_air[HITAG_FRAME_LEN];
- int response_bit[200];
- unsigned char mask = 1;
- unsigned char uid[32];
- unsigned char crc;
- uint64_t state;
- uint8_t auth_ks[4];
- uint8_t conf_pages[3];
- memcpy(rx_air, rx, nbytes(rxlen));
- *txlen = 0;
-
- if (tag.pstate == HT_READY && rxlen >= 67) {
- //received uid
- if (end == true) {
- Dbprintf("authentication failed!");
- return -1;
- }
- int z = 0;
- for (int i = 0; i < 10; i++) {
- for (int j = 0; j < 8; j++) {
- response_bit[z] = 0;
- if ((rx[i] & ((mask << 7) >> j)) != 0)
- response_bit[z] = 1;
- z++;
- }
- }
- uint16_t k = 0;
- for (int i = 5; i < z; i += 2) {
- uid[k] = response_bit[i];
- k++;
- if (k > 31)
- break;
- }
- uint8_t uid1 = (uid[0] << 7)
- | (uid[1] << 6)
- | (uid[2] << 5)
- | (uid[3] << 4)
- | (uid[4] << 3)
- | (uid[5] << 2)
- | (uid[6] << 1)
- | uid[7];
-
- uint8_t uid2 = (uid[8] << 7)
- | (uid[9] << 6)
- | (uid[10] << 5)
- | (uid[11] << 4)
- | (uid[12] << 3)
- | (uid[13] << 2)
- | (uid[14] << 1)
- | uid[15];
-
- uint8_t uid3 = (uid[16] << 7)
- | (uid[17] << 6)
- | (uid[18] << 5)
- | (uid[19] << 4)
- | (uid[20] << 3)
- | (uid[21] << 2)
- | (uid[22] << 1)
- | uid[23];
-
- uint8_t uid4 = (uid[24] << 7)
- | (uid[25] << 6)
- | (uid[26] << 5)
- | (uid[27] << 4)
- | (uid[28] << 3)
- | (uid[29] << 2)
- | (uid[30] << 1)
- | uid[31];
-
- if (DEBUG)
- Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4);
-
- tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1);
-
- //select uid
- *txlen = 45;
- crc = CRC_PRESET;
- calc_crc(&crc, 0x00, 5);
- calc_crc(&crc, uid1, 8);
- calc_crc(&crc, uid2, 8);
- calc_crc(&crc, uid3, 8);
- calc_crc(&crc, uid4, 8);
-
- for (int i = 0; i < 100; i++) {
- response_bit[i] = 0;
- }
-
- for (int i = 0; i < 5; i++) {
- response_bit[i] = 0;
- }
- {
- int i = 5;
- for (; i < 37; i++) {
- response_bit[i] = uid[i - 5];
- }
-
- for (int j = 0; j < 8; j++) {
- response_bit[i] = 0;
- if ((crc & ((mask << 7) >> j)) != 0)
- response_bit[i] = 1;
- i++;
- }
- }
- k = 0;
- for (int i = 0; i < 6; i++) {
- tx[i] = (response_bit[k] << 7)
- | (response_bit[k + 1] << 6)
- | (response_bit[k + 2] << 5)
- | (response_bit[k + 3] << 4)
- | (response_bit[k + 4] << 3)
- | (response_bit[k + 5] << 2)
- | (response_bit[k + 6] << 1)
- | response_bit[k + 7];
-
- k += 8;
- }
-
- tag.pstate = HT_INIT;
- } else if (tag.pstate == HT_INIT && rxlen == 44) {
- // received configuration after select command
- int z = 0;
- for (int i = 0; i < 6; i++) {
- for (int j = 0; j < 8; j++) {
- response_bit[z] = 0;
- if ((rx[i] & ((mask << 7) >> j)) != 0)
- response_bit[z] = 1;
- z++;
- }
- }
- conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6)
- | (response_bit[6] << 5) | (response_bit[7] << 4)
- | (response_bit[8] << 3) | (response_bit[9] << 2)
- | (response_bit[10] << 1) | response_bit[11]);
- //check wich memorysize this tag has
- if (response_bit[10] == 0 && response_bit[11] == 0)
- tag.max_page = 32 / 32;
- if (response_bit[10] == 0 && response_bit[11] == 1)
- tag.max_page = 256 / 32;
- if (response_bit[10] == 1 && response_bit[11] == 0)
- tag.max_page = 2048 / 32;
- conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6)
- | (response_bit[14] << 5) | (response_bit[15] << 4)
- | (response_bit[16] << 3) | (response_bit[17] << 2)
- | (response_bit[18] << 1) | response_bit[19]);
- tag.auth = response_bit[12];
- tag.TTFC = response_bit[13];
- //tag.TTFDR in response_bit[14] and response_bit[15]
- //tag.TTFM in response_bit[16] and response_bit[17]
- tag.LCON = response_bit[18];
- tag.LKP = response_bit[19];
- conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6)
- | (response_bit[22] << 5) | (response_bit[23] << 4)
- | (response_bit[24] << 3) | (response_bit[25] << 2)
- | (response_bit[26] << 1) | response_bit[27]);
- tag.LCK7 = response_bit[20];
- tag.LCK6 = response_bit[21];
- tag.LCK5 = response_bit[22];
- tag.LCK4 = response_bit[23];
- tag.LCK3 = response_bit[24];
- tag.LCK2 = response_bit[25];
- tag.LCK1 = response_bit[26];
- tag.LCK0 = response_bit[27];
-
- if (DEBUG)
- Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]);
-
- if (tag.auth == 1) {
- //if the tag is in authentication mode try the key or challenge
- *txlen = 64;
- if (end != true) {
- if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY
- state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
-
- for (int i = 0; i < 4; i++) {
- auth_ks[i] = _hitag2_byte(&state) ^ 0xff;
- }
- *txlen = 64;
- tx[0] = rnd & 0xff;
- tx[1] = (rnd >> 8) & 0xff;
- tx[2] = (rnd >> 16) & 0xff;
- tx[3] = (rnd >> 24) & 0xff;
-
- tx[4] = auth_ks[0];
- tx[5] = auth_ks[1];
- tx[6] = auth_ks[2];
- tx[7] = auth_ks[3];
- if (DEBUG)
- Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0],
- tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]);
- } else if (htf == 01 || htf == 03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
- for (int i = 0; i < 8; i++)
- tx[i] = ((NrAr >> (56 - (i * 8))) & 0xff);
- }
- end = true;
- tag.pstate = HT_AUTHENTICATE;
- } else {
- Dbprintf("authentication failed!");
- return -1;
- }
- } else if (tag.auth == 0) {
- tag.pstate = HT_SELECTED;
- }
-
- } else if (tag.pstate == HT_AUTHENTICATE && rxlen == 44) {
- //encrypted con2,password received.
- crc = CRC_PRESET;
- calc_crc(&crc, 0x80, 1);
- calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8);
- calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8);
- calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8);
- calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8);
- if (DEBUG) {
- Dbprintf("UID:::%X", tag.uid);
- Dbprintf("RND:::%X", rnd);
- }
-
- //decrypt password
- pwdh0 = 0;
- pwdl0 = 0;
- pwdl1 = 0;
- if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY
- {
- state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
- for (int i = 0; i < 5; i++)
- _hitag2_byte(&state);
-
- pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) ^ _hitag2_byte(&state);
- pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) ^ _hitag2_byte(&state);
- pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state);
- }
-
- if (DEBUG)
- Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1);
-
- //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16));
- //rnd += 1;
- }
- tag.pstate = HT_SELECTED; //tag is now ready for read/write commands
- }
- return 0;
-
-}
-
-/*
- * Emulates a Hitag S Tag with the given data from the .hts file
- */
-void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
-
- StopTicks();
-
-// int frame_count = 0;
- int response = 0, overflow = 0;
- int i, j;
- uint8_t rx[HITAG_FRAME_LEN];
- size_t rxlen = 0;
- bQuiet = false;
- uint8_t txbuf[HITAG_FRAME_LEN];
- uint8_t *tx = txbuf;
- size_t txlen = 0;
-
- // Reset the received frame, frame count and timing info
- memset(rx, 0x00, sizeof(rx));
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
- BigBuf_Clear_ext(false);
-
- // Clean up trace and prepare it for storing frames
- set_tracing(true);
- clear_trace();
-
- DbpString("Starting HitagS simulation");
- LED_D_ON();
-
- tag.pstate = HT_READY;
- tag.tstate = HT_NO_OP;
-
- for (i = 0; i < 16; i++)
- for (j = 0; j < 4; j++)
- tag.pages[i][j] = 0x0;
-
- // read tag data into memory
- if (tag_mem_supplied) {
- DbpString("Loading hitagS memory...");
- memcpy((uint8_t *)tag.pages, data, 4 * 64);
- }
-
- tag.uid = (uint32_t)tag.pages[0];
- tag.key = (intptr_t)tag.pages[3];
- tag.key <<= 16;
- tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1];
- tag.pwdl0 = tag.pages[2][3];
- tag.pwdl1 = tag.pages[2][2];
- tag.pwdh0 = tag.pages[1][0];
- //con0
- tag.max_page = 64;
- if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 1)
- tag.max_page = 8;
- if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0)
- tag.max_page = 0;
- if (DBGLEVEL >= DBG_EXTENDED)
- for (i = 0; i < tag.max_page; i++)
- Dbprintf("Page[%2d]: %02X %02X %02X %02X", i,
- (tag.pages[i][3]) & 0xff,
- (tag.pages[i][2]) & 0xff,
- (tag.pages[i][1]) & 0xff,
- tag.pages[i][0] & 0xff);
- //con1
- tag.auth = 0;
- if ((tag.pages[1][2] & 0x80) == 0x80)
- tag.auth = 1;
- tag.LCON = 0;
- if ((tag.pages[1][2] & 0x2) == 0x02)
- tag.LCON = 1;
- tag.LKP = 0;
- if ((tag.pages[1][2] & 0x1) == 0x01)
- tag.LKP = 1;
- //con2
- //0=read write 1=read only
- tag.LCK7 = 0;
- if ((tag.pages[1][1] & 0x80) == 0x80)
- tag.LCK7 = 1;
- tag.LCK6 = 0;
- if ((tag.pages[1][1] & 0x40) == 0x040)
- tag.LCK6 = 1;
- tag.LCK5 = 0;
- if ((tag.pages[1][1] & 0x20) == 0x20)
- tag.LCK5 = 1;
- tag.LCK4 = 0;
- if ((tag.pages[1][1] & 0x10) == 0x10)
- tag.LCK4 = 1;
- tag.LCK3 = 0;
- if ((tag.pages[1][1] & 0x8) == 0x08)
- tag.LCK3 = 1;
- tag.LCK2 = 0;
- if ((tag.pages[1][1] & 0x4) == 0x04)
- tag.LCK2 = 1;
- tag.LCK1 = 0;
- if ((tag.pages[1][1] & 0x2) == 0x02)
- tag.LCK1 = 1;
- tag.LCK0 = 0;
- if ((tag.pages[1][1] & 0x1) == 0x01)
- tag.LCK0 = 1;
-
- // Set up simulator mode, frequency divisor which will drive the FPGA
- // and analog mux selection.
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-
- // Configure output pin that is connected to the FPGA (for modulating)
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
-
- // Disable modulation at default, which means release resistance
- LOW(GPIO_SSC_DOUT);
-
- // Enable Peripheral Clock for
- // TIMER_CLOCK0, used to measure exact timing before answering
- // TIMER_CLOCK1, used to capture edges of the tag frames
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
-
- AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
-
- // Disable timer during configuration
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
-
- // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
- // external trigger rising edge, load RA on rising edge of TIOA.
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
- | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
-
- // Enable and reset counter
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- // synchronized startup procedure
- while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
-
- while (!BUTTON_PRESS() && !data_available()) {
-
- WDT_HIT();
-
- // Receive frame, watch for at most T0*EOF periods
- while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) {
- // Check if rising edge in modulation is detected
- if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
- // Retrieve the new timing values
- int ra = (AT91C_BASE_TC1->TC_RA / T0) + overflow;
- overflow = 0;
-
- // Reset timer every frame, we have to capture the last edge for timing
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- LED_B_ON();
-
- // Capture reader frame
- if (ra >= HITAG_T_STOP) {
- if (rxlen != 0) {
- //DbpString("wierd0?");
- }
- // Capture the T0 periods that have passed since last communication or field drop (reset)
- response = (ra - HITAG_T_LOW);
- } else if (ra >= HITAG_T_1_MIN) {
- // '1' bit
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- } else if (ra >= HITAG_T_0_MIN) {
- // '0' bit
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- } else {
- // Ignore wierd value, is to small to mean anything
- }
- }
- }
-
- // Check if frame was captured
- if (rxlen > 0) {
-// frame_count++;
- LogTrace(rx, nbytes(rxlen), response, 0, NULL, true);
-
- // Disable timer 1 with external trigger to avoid triggers during our own modulation
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // Process the incoming frame (rx) and prepare the outgoing frame (tx)
- hitagS_handle_reader_command(rx, rxlen, tx, &txlen);
-
- // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit,
- // not that since the clock counts since the rising edge, but T_Wait1 is
- // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
- // periods. The gap time T_Low varies (4..10). All timer values are in
- // terms of T0 units
- while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) {};
-
- // Send and store the tag answer (if there is any)
- if (txlen > 0) {
- // Transmit the tag frame
- hitag_send_frame(tx, txlen);
- LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
- }
-
- // Reset the received frame and response timing info
- memset(rx, 0x00, sizeof(rx));
- response = 0;
-
- // Enable and reset external trigger in timer for capturing future frames
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- LED_B_OFF();
- }
- // Reset the frame length
- rxlen = 0;
- // Save the timer overflow, will be 0 when frame was received
- overflow += (AT91C_BASE_TC1->TC_CV / T0);
- // Reset the timer to restart while-loop that receives frames
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
- }
-
- LEDsoff();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- set_tracing(false);
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
-
- // release allocated memory from BigBuff.
- BigBuf_free();
-
- StartTicks();
-
- DbpString("Sim Stopped");
-}
-
-/*
- * Authenticates to the Tag with the given key or challenge.
- * If the key was given the password will be decrypted.
- * Reads every page of a hitag S transpoder.
- */
-void ReadHitagS(hitag_function htf, hitag_data *htd) {
-
- StopTicks();
-
- int i, j, z, k;
-// int frame_count = 0;
- int response = 0;
- int response_bit[200];
- uint8_t rx[HITAG_FRAME_LEN];
- size_t rxlen = 0;
- uint8_t txbuf[HITAG_FRAME_LEN];
- uint8_t *tx = txbuf;
- size_t txlen = 0;
- int lastbit = 1;
- int reset_sof = 1;
- int t_wait = HITAG_T_WAIT_MAX;
- bool bStop = false;
- int pageNum = 0;
- unsigned char mask = 1;
- unsigned char crc;
- unsigned char pageData[32];
- page_to_be_written = 0;
-
- //read given key/challenge
- uint8_t NrAr_[8];
- uint64_t key = 0;
- uint64_t NrAr = 0;
- uint8_t key_[6];
-
- switch (htf) {
- case RHTSF_CHALLENGE: {
- DbpString("Authenticating using nr,ar pair:");
- memcpy(NrAr_, htd->auth.NrAr, 8);
- Dbhexdump(8, NrAr_, false);
- NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
- ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
- break;
- }
- case RHTSF_KEY: {
- DbpString("Authenticating using key:");
- memcpy(key_, htd->crypto.key, 6);
- Dbhexdump(6, key_, false);
- key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
- break;
- }
- default: {
- Dbprintf("Error , unknown function: %d", htf);
- return;
- }
- }
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- // Reset the return status
- bSuccessful = false;
-
- // Clean up trace and prepare it for storing frames
- set_tracing(true);
- clear_trace();
-
- bQuiet = false;
-
- LED_D_ON();
-
- // Set fpga in edge detect with reader field, we can modulate as reader now
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-
- // Configure output and enable pin that is connected to the FPGA (for modulating)
- AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
-
- // Disable modulation at default, which means enable the field
- LOW(GPIO_SSC_DOUT);
-
- // Enable Peripheral Clock for
- // TIMER_CLOCK0, used to measure exact timing before answering
- // TIMER_CLOCK1, used to capture edges of the tag frames
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
-
- AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
-
- // Disable timer during configuration
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
-
- // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
- // external trigger rising edge, load RA on falling edge of TIOA.
- AT91C_BASE_TC1->TC_CMR =
- AT91C_TC_CLKS_TIMER_DIV1_CLOCK |
- AT91C_TC_ETRGEDG_FALLING |
- AT91C_TC_ABETRG |
- AT91C_TC_LDRA_FALLING;
-
- // Enable and reset counters
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- // synchronized startup procedure
- while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
-
- // Reset the received frame, frame count and timing info
- t_wait = 200;
-
- while (!bStop && !BUTTON_PRESS() && !data_available()) {
-
- WDT_HIT();
-
- // Check if frame was captured and store it
- if (rxlen > 0) {
-// frame_count++;
- LogTrace(rx, nbytes(rxlen), response, 0, NULL, false);
- }
-
- // By default reset the transmission buffer
- tx = txbuf;
- txlen = 0;
-
- if (rxlen == 0) {
- //start authentication
- txlen = 5;
- memcpy(tx, "\xC0", nbytes(txlen));
- tag.pstate = HT_READY;
- tag.tstate = HT_NO_OP;
- } else if (tag.pstate != HT_SELECTED) {
- if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1)
- bStop = !false;
- }
-
- if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) {
- //write read request
- tag.tstate = HT_READING_PAGE;
- txlen = 20;
- crc = CRC_PRESET;
- tx[0] = 0xc0 + (pageNum / 16);
- calc_crc(&crc, tx[0], 8);
- calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4);
- tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16);
- tx[2] = 0x00 + (crc % 16) * 16;
- } else if (tag.pstate == HT_SELECTED
- && tag.tstate == HT_READING_PAGE
- && rxlen > 0) {
- //save received data - 40 bits
- z = 0;
- for (i = 0; i < 5; i++) {
- for (j = 0; j < 8; j++) {
- response_bit[z] = 0;
- if ((rx[i] & ((mask << 7) >> j)) != 0)
- response_bit[z] = 1;
- z++;
- }
- }
- k = 0;
- for (i = 4; i < 36; i++) { // ignore first 4 bits: SOF (actualy 1 or 6 depending on response protocol)
- pageData[k] = response_bit[i];
- k++;
- }
- for (i = 0; i < 4; i++) // set page bytes to 0
- tag.pages[pageNum][i] = 0x0;
- for (i = 0; i < 4; i++) { // set page bytes from recieved bits
- tag.pages[pageNum][i] += ((pageData[i * 8] << 7)
- | (pageData[1 + (i * 8)] << 6)
- | (pageData[2 + (i * 8)] << 5)
- | (pageData[3 + (i * 8)] << 4)
- | (pageData[4 + (i * 8)] << 3)
- | (pageData[5 + (i * 8)] << 2)
- | (pageData[6 + (i * 8)] << 1)
- | pageData[7 + (i * 8)]);
- }
- if (tag.auth && tag.LKP && pageNum == 1) {
- Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0,
- (tag.pages[pageNum][2]) & 0xff,
- (tag.pages[pageNum][1]) & 0xff,
- tag.pages[pageNum][0] & 0xff);
- } else {
- Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum,
- (tag.pages[pageNum][3]) & 0xff,
- (tag.pages[pageNum][2]) & 0xff,
- (tag.pages[pageNum][1]) & 0xff,
- tag.pages[pageNum][0] & 0xff);
- }
-
- pageNum++;
- //display key and password if possible
- if (pageNum == 2 && tag.auth == 1 && tag.LKP) {
- if (htf == RHTSF_KEY) {
- Dbprintf("Page[ 2]: %02X %02X %02X %02X",
- (uint8_t)(key >> 8) & 0xff,
- (uint8_t) key & 0xff,
- pwdl1,
- pwdl0
- );
- Dbprintf("Page[ 3]: %02X %02X %02X %02X",
- (uint8_t)(key >> 40) & 0xff,
- (uint8_t)(key >> 32) & 0xff,
- (uint8_t)(key >> 24) & 0xff,
- (uint8_t)(key >> 16) & 0xff
- );
- } else {
- //if the authentication is done with a challenge the key and password are unknown
- Dbprintf("Page[ 2]: __ __ __ __");
- Dbprintf("Page[ 3]: __ __ __ __");
- }
- }
-
- txlen = 20;
- crc = CRC_PRESET;
- tx[0] = 0xc0 + (pageNum / 16);
- calc_crc(&crc, tx[0], 8);
- calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4);
- tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16);
- tx[2] = 0x00 + (crc % 16) * 16;
- if (pageNum >= tag.max_page) {
- bStop = !false;
- }
- }
-
- // Send and store the reader command
- // Disable timer 1 with external trigger to avoid triggers during our own modulation
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
- // Since the clock counts since the last falling edge, a 'one' means that the
- // falling edge occurred halfway the period. with respect to this falling edge,
- // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
- // All timer values are in terms of T0 units
-
- while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {};
-
- // Transmit the reader frame
- hitag_reader_send_frame(tx, txlen);
-
- // Enable and reset external trigger in timer for capturing future frames
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- // Add transmitted frame to total count
- if (txlen > 0) {
-// frame_count++;
- LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
- }
-
- // Reset values for receiving frames
- memset(rx, 0x00, sizeof(rx));
- rxlen = 0;
- lastbit = 1;
- bool bSkip = true;
- int tag_sof = reset_sof;
- response = 0;
-
- // Receive frame, watch for at most T0*EOF periods
- while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
- // Check if falling edge in tag modulation is detected
- if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
- // Retrieve the new timing values
- int ra = (AT91C_BASE_TC1->TC_RA / T0);
-
- // Reset timer every frame, we have to capture the last edge for timing
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- LED_B_ON();
-
- // Capture tag frame (manchester decoding using only falling edges)
- if (ra >= HITAG_T_EOF) {
- if (rxlen != 0) {
- //DbpString("wierd1?");
- }
- // Capture the T0 periods that have passed since last communication or field drop (reset)
- // We always recieve a 'one' first, which has the falling edge after a half period |-_|
- response = ra - HITAG_T_TAG_HALF_PERIOD;
- } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
- // Manchester coding example |-_|_-|-_| (101)
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
- // Manchester coding example |_-|...|_-|-_| (0...01)
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- // We have to skip this half period at start and add the 'one' the second time
- if (!bSkip) {
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- }
- lastbit = !lastbit;
- bSkip = !bSkip;
- } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
- // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
- if (tag_sof) {
- // Ignore bits that are transmitted during SOF
- tag_sof--;
- } else {
- // bit is same as last bit
- rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
- rxlen++;
- }
- } else {
- // Ignore wierd value, is to small to mean anything
- }
- }
-
- // We can break this loop if we received the last bit from a frame
- if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
- if (rxlen > 0)
- break;
- }
- }
- }
- end = false;
-
- LEDsoff();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- set_tracing(false);
-
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- StartTicks();
-
- reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
-}
-
-/*
- * Authenticates to the Tag with the given Key or Challenge.
- * Writes the given 32Bit data into page_
- */
-void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
-
- StopTicks();
-
-// int frame_count = 0;
- int response = 0;
- uint8_t rx[HITAG_FRAME_LEN];
- size_t rxlen = 0;
- uint8_t txbuf[HITAG_FRAME_LEN];
- uint8_t *tx = txbuf;
- size_t txlen = 0;
- int lastbit;
- int reset_sof;
- int t_wait = HITAG_T_WAIT_MAX;
- bool bStop;
- unsigned char crc;
- uint8_t data[4] = {0, 0, 0, 0};
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- bSuccessful = false;
-
- // Clean up trace and prepare it for storing frames
- set_tracing(true);
- clear_trace();
-
- //read given key/challenge, the page and the data
- uint8_t NrAr_[8];
- uint64_t key = 0;
- uint64_t NrAr = 0;
- uint8_t key_[6];
- switch (htf) {
- case WHTSF_CHALLENGE: {
- memcpy(data, htd->auth.data, 4);
- DbpString("Authenticating using nr,ar pair:");
- memcpy(NrAr_, htd->auth.NrAr, 8);
- Dbhexdump(8, NrAr_, false);
- NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
- ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
- break;
- }
-
- case WHTSF_KEY: {
- memcpy(data, htd->crypto.data, 4);
- DbpString("Authenticating using key:");
- memcpy(key_, htd->crypto.key, 6);
- Dbhexdump(6, key_, false);
- key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
- break;
- }
- default: {
- Dbprintf("Error , unknown function: %d", htf);
- return;
- }
- }
-
- Dbprintf("Page: %d", page);
- Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]);
-
- tag.pstate = HT_READY;
- tag.tstate = HT_NO_OP;
-
- LED_D_ON();
-
- // Configure output and enable pin that is connected to the FPGA (for modulating)
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
-
- // Set fpga in edge detect with reader field, we can modulate as reader now
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-
- // Disable modulation at default, which means enable the field
- LOW(GPIO_SSC_DOUT);
-
- // Enable Peripheral Clock for
- // TIMER_CLOCK0, used to measure exact timing before answering
- // TIMER_CLOCK1, used to capture edges of the tag frames
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
-
- AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
-
- // Disable timer during configuration
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
- // external trigger rising edge, load RA on falling edge of TIOA.
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
- | AT91C_TC_ETRGEDG_FALLING
- | AT91C_TC_ABETRG
- | AT91C_TC_LDRA_FALLING;
-
- // Enable and reset counters
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- while (AT91C_BASE_TC0->TC_CV > 0);
-
- // Reset the received frame, frame count and timing info
- lastbit = 1;
- bStop = false;
- reset_sof = 1;
- t_wait = 200;
-
- while (!bStop && !BUTTON_PRESS() && !data_available()) {
-
- WDT_HIT();
-
- // Check if frame was captured and store it
- if (rxlen > 0) {
-// frame_count++;
- LogTrace(rx, nbytes(rxlen), response, 0, NULL, false);
- }
-
- //check for valid input
- if (page == 0) {
- Dbprintf(
- "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]");
- bStop = !false;
- }
-
- // By default reset the transmission buffer
- tx = txbuf;
- txlen = 0;
-
- if (rxlen == 0 && tag.tstate == HT_WRITING_PAGE_ACK) {
- //no write access on this page
- Dbprintf("no write access on page %d", page);
- bStop = !false;
- } else if (rxlen == 0 && tag.tstate != HT_WRITING_PAGE_DATA) {
- //start the authetication
- txlen = 5;
- memcpy(tx, "\xc0", nbytes(txlen));
- tag.pstate = HT_READY;
- tag.tstate = HT_NO_OP;
- } else if (tag.pstate != HT_SELECTED) {
- //try to authenticate with the given key or challenge
- if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1)
- bStop = !false;
- }
- if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) {
- //check if the given page exists
- if (page > tag.max_page) {
- Dbprintf("page number too big");
- bStop = !false;
- }
- //ask Tag for write permission
- tag.tstate = HT_WRITING_PAGE_ACK;
- txlen = 20;
- crc = CRC_PRESET;
- tx[0] = 0x90 + (page / 16);
- calc_crc(&crc, tx[0], 8);
- calc_crc(&crc, 0x00 + ((page % 16) * 16), 4);
- tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16);
- tx[2] = 0x00 + (crc % 16) * 16;
- } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_ACK
- && rxlen == 6 && rx[0] == 0xf4) {
- //ACK recieved to write the page. write data
- tag.tstate = HT_WRITING_PAGE_DATA;
- txlen = 40;
- crc = CRC_PRESET;
- calc_crc(&crc, data[3], 8);
- calc_crc(&crc, data[2], 8);
- calc_crc(&crc, data[1], 8);
- calc_crc(&crc, data[0], 8);
- tx[0] = data[3];
- tx[1] = data[2];
- tx[2] = data[1];
- tx[3] = data[0];
- tx[4] = crc;
- } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_DATA
- && rxlen == 6 && rx[0] == 0xf4) {
- //received ACK
- Dbprintf("Successful!");
- bStop = !false;
- }
-
- // Send and store the reader command
- // Disable timer 1 with external trigger to avoid triggers during our own modulation
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
- // Since the clock counts since the last falling edge, a 'one' means that the
- // falling edge occurred halfway the period. with respect to this falling edge,
- // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
- // All timer values are in terms of T0 units
-
- while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {};
-
- // Transmit the reader frame
- hitag_reader_send_frame(tx, txlen);
-
- // Enable and reset external trigger in timer for capturing future frames
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- // Add transmitted frame to total count
- if (txlen > 0) {
-// frame_count++;
- LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
- }
-
- // Reset values for receiving frames
- memset(rx, 0x00, sizeof(rx));
- rxlen = 0;
- lastbit = 1;
- bool bSkip = true;
- int tag_sof = reset_sof;
- response = 0;
- uint32_t errorCount = 0;
-
- // Receive frame, watch for at most T0*EOF periods
- while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
- // Check if falling edge in tag modulation is detected
- if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
- // Retrieve the new timing values
- int ra = (AT91C_BASE_TC1->TC_RA / T0);
-
- // Reset timer every frame, we have to capture the last edge for timing
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- LED_B_ON();
-
- // Capture tag frame (manchester decoding using only falling edges)
- if (ra >= HITAG_T_EOF) {
- if (rxlen != 0) {
- //DbpString("wierd1?");
- }
- // Capture the T0 periods that have passed since last communication or field drop (reset)
- // We always recieve a 'one' first, which has the falling edge after a half period |-_|
- response = ra - HITAG_T_TAG_HALF_PERIOD;
- } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
- // Manchester coding example |-_|_-|-_| (101)
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
- // Manchester coding example |_-|...|_-|-_| (0...01)
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- // We have to skip this half period at start and add the 'one' the second time
- if (!bSkip) {
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- }
- lastbit = !lastbit;
- bSkip = !bSkip;
- } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
- // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
- if (tag_sof) {
- // Ignore bits that are transmitted during SOF
- tag_sof--;
- } else {
- // bit is same as last bit
- rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
- rxlen++;
- }
- } else {
- // Ignore wierd value, is to small to mean anything
- errorCount++;
- }
- }
-
- // if we saw over 100 wierd values break it probably isn't hitag...
- if (errorCount > 100) break;
-
- // We can break this loop if we received the last bit from a frame
- if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
- if (rxlen > 0)
- break;
- }
- }
- }
- end = false;
- LEDsoff();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- set_tracing(false);
-
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
-
- StartTicks();
-
- reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
-}
-
-/*
- * Tries to authenticate to a Hitag S Transponder with the given challenges from a .cc file.
- * Displays all Challenges that failed.
- * When collecting Challenges to break the key it is possible that some data
- * is not received correctly due to Antenna problems. This function
- * detects these challenges.
- */
-void check_challenges(bool file_given, uint8_t *data) {
- int i, j, z, k;
-// int frame_count = 0;
- int response = 0;
- uint8_t uid_byte[4];
- uint8_t rx[HITAG_FRAME_LEN];
- uint8_t unlocker[60][8];
- int u1 = 0;
- size_t rxlen = 0;
- uint8_t txbuf[HITAG_FRAME_LEN];
- int t_wait = HITAG_T_WAIT_MAX;
- int lastbit, reset_sof, STATE = 0;;
- bool bStop;
- int response_bit[200];
- unsigned char mask = 1;
- unsigned char uid[32];
- unsigned char crc;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- // Reset the return status
- bSuccessful = false;
-
- // Clean up trace and prepare it for storing frames
- set_tracing(true);
- clear_trace();
-
- bQuiet = false;
-
- LED_D_ON();
-
- // Configure output and enable pin that is connected to the FPGA (for modulating)
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
-
- // Set fpga in edge detect with reader field, we can modulate as reader now
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-
- // Disable modulation at default, which means enable the field
- LOW(GPIO_SSC_DOUT);
-
- // Enable Peripheral Clock for
- // TIMER_CLOCK0, used to measure exact timing before answering
- // TIMER_CLOCK1, used to capture edges of the tag frames
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
-
- AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
-
- // Disable timer during configuration
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
-
- // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
- // external trigger rising edge, load RA on falling edge of TIOA.
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
- | AT91C_TC_ETRGEDG_FALLING
- | AT91C_TC_ABETRG
- | AT91C_TC_LDRA_FALLING;
-
- // Enable and reset counters
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- while (AT91C_BASE_TC0->TC_CV > 0) {};
-
- // Reset the received frame, frame count and timing info
- lastbit = 1;
- bStop = false;
- reset_sof = 1;
- t_wait = 200;
-
- if (file_given) {
- DbpString("Loading challenges...");
- memcpy((uint8_t *)unlocker, data, 60 * 8);
- }
-
- while (file_given && !bStop && !BUTTON_PRESS()) {
- // Watchdog hit
- WDT_HIT();
-
- // Check if frame was captured and store it
- if (rxlen > 0) {
-// frame_count++;
- LogTrace(rx, nbytes(rxlen), response, 0, NULL, false);
- }
-
- uint8_t *tx = txbuf;
- size_t txlen = 0;
- if (rxlen == 0) {
- if (STATE == 2)
- // challenge failed
- Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X",
- unlocker[u1 - 1][0], unlocker[u1 - 1][1],
- unlocker[u1 - 1][2], unlocker[u1 - 1][3],
- unlocker[u1 - 1][4], unlocker[u1 - 1][5],
- unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
- STATE = 0;
- txlen = 5;
- //start new authentication
- memcpy(tx, "\xC0", nbytes(txlen));
- } else if (rxlen >= 67 && STATE == 0) {
- //received uid
- z = 0;
- for (i = 0; i < 10; i++) {
- for (j = 0; j < 8; j++) {
- response_bit[z] = 0;
- if ((rx[i] & ((mask << 7) >> j)) != 0)
- response_bit[z] = 1;
- z++;
- }
- }
- k = 0;
- for (i = 5; i < z; i += 2) {
- uid[k] = response_bit[i];
- k++;
- if (k > 31)
- break;
- }
- uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5)
- | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2)
- | (uid[6] << 1) | uid[7];
- uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5)
- | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2)
- | (uid[14] << 1) | uid[15];
- uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5)
- | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2)
- | (uid[22] << 1) | uid[23];
- uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5)
- | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2)
- | (uid[30] << 1) | uid[31];
- //Dbhexdump(10, rx, rxlen);
- STATE = 1;
- txlen = 45;
- crc = CRC_PRESET;
- calc_crc(&crc, 0x00, 5);
- calc_crc(&crc, uid_byte[0], 8);
- calc_crc(&crc, uid_byte[1], 8);
- calc_crc(&crc, uid_byte[2], 8);
- calc_crc(&crc, uid_byte[3], 8);
- for (i = 0; i < 100; i++) {
- response_bit[i] = 0;
- }
- for (i = 0; i < 5; i++) {
- response_bit[i] = 0;
- }
- for (i = 5; i < 37; i++) {
- response_bit[i] = uid[i - 5];
- }
- for (j = 0; j < 8; j++) {
- response_bit[i] = 0;
- if ((crc & ((mask << 7) >> j)) != 0)
- response_bit[i] = 1;
- i++;
- }
- k = 0;
- for (i = 0; i < 6; i++) {
- tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6)
- | (response_bit[k + 2] << 5)
- | (response_bit[k + 3] << 4)
- | (response_bit[k + 4] << 3)
- | (response_bit[k + 5] << 2)
- | (response_bit[k + 6] << 1) | response_bit[k + 7];
- k += 8;
- }
-
- } else if (STATE == 1 && rxlen == 44) {
- //received configuration
- STATE = 2;
- z = 0;
- for (i = 0; i < 6; i++) {
- for (j = 0; j < 8; j++) {
- response_bit[z] = 0;
- if ((rx[i] & ((mask << 7) >> j)) != 0)
- response_bit[z] = 1;
- z++;
- }
- }
- txlen = 64;
-
- if (u1 >= ARRAYLEN(unlocker))
- bStop = !false;
- for (i = 0; i < 8; i++)
- tx[i] = unlocker[u1][i];
- u1++;
-
- } else if (STATE == 2 && rxlen >= 44) {
- STATE = 0;
- }
-
- // Send and store the reader command
- // Disable timer 1 with external trigger to avoid triggers during our own modulation
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
- // Since the clock counts since the last falling edge, a 'one' means that the
- // falling edge occurred halfway the period. with respect to this falling edge,
- // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
- // All timer values are in terms of T0 units
-
- while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {};
-
- // Transmit the reader frame
- hitag_reader_send_frame(tx, txlen);
-
- // Enable and reset external trigger in timer for capturing future frames
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- // Add transmitted frame to total count
- if (txlen > 0) {
-// frame_count++;
- LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
- }
-
- // Reset values for receiving frames
- memset(rx, 0x00, sizeof(rx));
- rxlen = 0;
- lastbit = 1;
- bool bSkip = true;
- int tag_sof = reset_sof;
- response = 0;
-
- // Receive frame, watch for at most T0*EOF periods
- while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
- // Check if falling edge in tag modulation is detected
- if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
- // Retrieve the new timing values
- int ra = (AT91C_BASE_TC1->TC_RA / T0);
-
- // Reset timer every frame, we have to capture the last edge for timing
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-
- LED_B_ON();
-
- // Capture tag frame (manchester decoding using only falling edges)
- if (ra >= HITAG_T_EOF) {
- if (rxlen != 0) {
- //DbpString("wierd1?");
- }
- // Capture the T0 periods that have passed since last communication or field drop (reset)
- // We always recieve a 'one' first, which has the falling edge after a half period |-_|
- response = ra - HITAG_T_TAG_HALF_PERIOD;
- } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
- // Manchester coding example |-_|_-|-_| (101)
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
- // Manchester coding example |_-|...|_-|-_| (0...01)
- rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
- rxlen++;
- // We have to skip this half period at start and add the 'one' the second time
- if (!bSkip) {
- rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
- rxlen++;
- }
- lastbit = !lastbit;
- bSkip = !bSkip;
- } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
- // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
- if (tag_sof) {
- // Ignore bits that are transmitted during SOF
- tag_sof--;
- } else {
- // bit is same as last bit
- rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
- rxlen++;
- }
- } else {
- // Ignore wierd value, is to small to mean anything
- }
- }
-
- // We can break this loop if we received the last bit from a frame
- if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
- if (rxlen > 0)
- break;
- }
- }
- }
-
- LEDsoff();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- set_tracing(false);
-
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
-
- StartTicks();
-
- reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
-}
-
-
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/hitagS.h b/pm3rdv4rrg/src/main/cpp/armsrc/hitagS.h
deleted file mode 100644
index f4efd70a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/hitagS.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// HitagS emulation (preliminary test version)
-//
-// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
-//
-//-----------------------------------------------------------------------------
-
-#ifndef _HITAGS_H_
-#define _HITAGS_H_
-
-#include "common.h"
-
-#include "hitag.h"
-
-void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data);
-void ReadHitagS(hitag_function htf, hitag_data *htd);
-void WritePageHitagS(hitag_function htf, hitag_data *htd, int page);
-void check_challenges(bool file_given, uint8_t *data);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/i2c.c b/pm3rdv4rrg/src/main/cpp/armsrc/i2c.c
deleted file mode 100644
index 95023dce..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/i2c.c
+++ /dev/null
@@ -1,842 +0,0 @@
-//-----------------------------------------------------------------------------
-// Willok, June 2018
-// Edits by Iceman, July 2018
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// The main i2c code, for communications with smart card module
-//-----------------------------------------------------------------------------
-#include "i2c.h"
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "BigBuf.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "string.h"
-
-#define GPIO_RST AT91C_PIO_PA1
-#define GPIO_SCL AT91C_PIO_PA5
-#define GPIO_SDA AT91C_PIO_PA7
-
-#define SCL_H HIGH(GPIO_SCL)
-#define SCL_L LOW(GPIO_SCL)
-#define SDA_H HIGH(GPIO_SDA)
-#define SDA_L LOW(GPIO_SDA)
-
-#define SCL_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SCL)
-#define SDA_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SDA)
-
-#define I2C_ERROR "I2C_WaitAck Error"
-
-volatile unsigned long c;
-
-// Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz,
-// delay=1 is about 200kbps
-// timer.
-// I2CSpinDelayClk(4) = 12.31us
-// I2CSpinDelayClk(1) = 3.07us
-void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
- for (c = delay * 2; c; c--) {};
-}
-
-#define I2C_DELAY_1CLK I2CSpinDelayClk(1)
-#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
-#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
-
-#define ISO7618_MAX_FRAME 255
-
-// try i2c bus recovery at 100kHz = 5us high, 5us low
-void I2C_recovery(void) {
-
- DbpString("Performing i2c bus recovery");
-
- // reset I2C
- SDA_H;
- SCL_H;
-
- //9nth cycle acts as NACK
- for (int i = 0; i < 10; i++) {
- SCL_H;
- WaitUS(5);
- SCL_L;
- WaitUS(5);
- }
-
- //a STOP signal (SDA from low to high while CLK is high)
- SDA_L;
- WaitUS(5);
- SCL_H;
- WaitUS(2);
- SDA_H;
- WaitUS(2);
-
- bool isok = (SCL_read && SDA_read);
- if (!SDA_read)
- DbpString("I2C bus recovery error: SDA still LOW");
- if (!SCL_read)
- DbpString("I2C bus recovery error: SCL still LOW");
- if (isok)
- DbpString("I2C bus recovery complete");
-}
-
-void I2C_init(void) {
- // Configure reset pin, close up pull up, push-pull output, default high
- AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;
- AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;
-
- // Configure I2C pin, open up, open leakage
- AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA);
- AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA);
-
- // default three lines all pull up
- AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
-
- AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
- AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
-
- bool isok = (SCL_read && SDA_read);
- if (!isok)
- I2C_recovery();
-}
-
-// set the reset state
-void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
- if (LineRST)
- HIGH(GPIO_RST);
- else
- LOW(GPIO_RST);
-
- if (LineSCK)
- HIGH(GPIO_SCL);
- else
- LOW(GPIO_SCL);
-
- if (LineSDA)
- HIGH(GPIO_SDA);
- else
- LOW(GPIO_SDA);
-}
-
-// Reset the SIM_Adapter, then enter the main program
-// Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
-void I2C_Reset_EnterMainProgram(void) {
- StartTicks();
- I2C_init();
- I2C_SetResetStatus(0, 0, 0);
- WaitMS(30);
- I2C_SetResetStatus(1, 0, 0);
- WaitMS(30);
- I2C_SetResetStatus(1, 1, 1);
- WaitMS(10);
-}
-
-// Reset the SIM_Adapter, then enter the bootloader program
-// Reserve for firmware update.
-void I2C_Reset_EnterBootloader(void) {
- StartTicks();
- I2C_init();
- I2C_SetResetStatus(0, 1, 1);
- WaitMS(100);
- I2C_SetResetStatus(1, 1, 1);
- WaitMS(10);
-}
-
-// Wait for the clock to go High.
-bool WaitSCL_H_delay(uint32_t delay) {
- while (delay--) {
- if (SCL_read) {
- return true;
- }
- I2C_DELAY_1CLK;
- }
- return false;
-}
-
-// 5000 * 3.07us = 15350us. 15.35ms
-// 15000 * 3.07us = 46050us. 46.05ms
-bool WaitSCL_H(void) {
- return WaitSCL_H_delay(15000);
-}
-
-bool WaitSCL_L_delay(uint32_t delay) {
- while (delay--) {
- if (!SCL_read) {
- return true;
- }
- I2C_DELAY_1CLK;
- }
- return false;
-}
-// 5000 * 3.07us = 15350us. 15.35ms
-bool WaitSCL_L(void) {
- return WaitSCL_L_delay(15000);
-}
-
-// Wait max 1800ms or until SCL goes LOW.
-// It timeout reading response from card
-// Which ever comes first
-bool WaitSCL_L_timeout(void) {
- volatile uint16_t delay = 1800;
- while (delay--) {
- // exit on SCL LOW
- if (!SCL_read)
- return true;
-
- WaitMS(1);
- }
- return (delay == 0);
-}
-
-bool I2C_Start(void) {
-
- I2C_DELAY_XCLK(4);
- SDA_H;
- I2C_DELAY_1CLK;
- SCL_H;
- if (!WaitSCL_H()) return false;
-
- I2C_DELAY_2CLK;
-
- if (!SCL_read) return false;
- if (!SDA_read) return false;
-
- SDA_L;
- I2C_DELAY_2CLK;
- return true;
-}
-
-bool I2C_WaitForSim() {
-
- // wait for data from card
- if (!WaitSCL_L_timeout())
- return false;
-
- // 8051 speaks with smart card.
- // 1000*50*3.07 = 153.5ms
- // 1byte transfer == 1ms with max frame being 256bytes
- if (!WaitSCL_H_delay(10 * 1000 * 50))
- return false;
-
- return true;
-}
-
-// write i2c STOP
-void I2C_Stop(void) {
- SCL_L;
- I2C_DELAY_2CLK;
- SDA_L;
- I2C_DELAY_2CLK;
- SCL_H;
- I2C_DELAY_2CLK;
- if (!WaitSCL_H()) return;
- SDA_H;
- I2C_DELAY_XCLK(8);
-}
-
-// Send i2c ACK
-void I2C_Ack(void) {
- SCL_L;
- I2C_DELAY_2CLK;
- SDA_L;
- I2C_DELAY_2CLK;
- SCL_H;
- I2C_DELAY_2CLK;
- if (!WaitSCL_H()) return;
- SCL_L;
- I2C_DELAY_2CLK;
-}
-
-// Send i2c NACK
-void I2C_NoAck(void) {
- SCL_L;
- I2C_DELAY_2CLK;
- SDA_H;
- I2C_DELAY_2CLK;
- SCL_H;
- I2C_DELAY_2CLK;
- if (!WaitSCL_H()) return;
- SCL_L;
- I2C_DELAY_2CLK;
-}
-
-bool I2C_WaitAck(void) {
- SCL_L;
- I2C_DELAY_1CLK;
- SDA_H;
- I2C_DELAY_1CLK;
- SCL_H;
- if (!WaitSCL_H())
- return false;
-
- I2C_DELAY_2CLK;
- I2C_DELAY_2CLK;
- if (SDA_read) {
- SCL_L;
- return false;
- }
- SCL_L;
- return true;
-}
-
-void I2C_SendByte(uint8_t data) {
- uint8_t bits = 8;
-
- while (bits--) {
- SCL_L;
-
- I2C_DELAY_1CLK;
-
- if (data & 0x80)
- SDA_H;
- else
- SDA_L;
-
- data <<= 1;
-
- I2C_DELAY_1CLK;
-
- SCL_H;
- if (!WaitSCL_H())
- return;
-
- I2C_DELAY_2CLK;
- }
- SCL_L;
-}
-
-int16_t I2C_ReadByte(void) {
- uint8_t bits = 8, b = 0;
-
- SDA_H;
- while (bits--) {
- b <<= 1;
- SCL_L;
- if (!WaitSCL_L()) return -2;
-
- I2C_DELAY_1CLK;
-
- SCL_H;
- if (!WaitSCL_H()) return -1;
-
- I2C_DELAY_1CLK;
- if (SDA_read)
- b |= 0x01;
- }
- SCL_L;
- return b;
-}
-
-// Sends one byte ( command to be written, SlaveDevice address)
-bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
- bool bBreak = true;
- do {
- if (!I2C_Start())
- return false;
-
- I2C_SendByte(device_address & 0xFE);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(device_cmd);
- if (!I2C_WaitAck())
- break;
-
- bBreak = false;
- } while (false);
-
- I2C_Stop();
- if (bBreak) {
- if (DBGLEVEL > 3) DbpString(I2C_ERROR);
- return false;
- }
- return true;
-}
-
-// Sends 1 byte data (Data to be written, command to be written , SlaveDevice address ).
-bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
- bool bBreak = true;
- do {
- if (!I2C_Start())
- return false;
-
- I2C_SendByte(device_address & 0xFE);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(device_cmd);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(data);
- if (!I2C_WaitAck())
- break;
-
- bBreak = false;
- } while (false);
-
- I2C_Stop();
- if (bBreak) {
- if (DBGLEVEL > 3) DbpString(I2C_ERROR);
- return false;
- }
- return true;
-}
-
-//Sends array of data (Array, length, command to be written , SlaveDevice address ).
-// len = uint8 (max buffer to write 256bytes)
-bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
- bool bBreak = true;
- do {
- if (!I2C_Start())
- return false;
-
- I2C_SendByte(device_address & 0xFE);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(device_cmd);
- if (!I2C_WaitAck())
- break;
-
- while (len) {
-
- I2C_SendByte(*data);
- if (!I2C_WaitAck())
- break;
-
- len--;
- data++;
- }
-
- if (len == 0)
- bBreak = false;
- } while (false);
-
- I2C_Stop();
- if (bBreak) {
- if (DBGLEVEL > 3) DbpString(I2C_ERROR);
- return false;
- }
- return true;
-}
-
-// read one array of data (Data array, Readout length, command to be written , SlaveDevice address ).
-// len = uint8 (max buffer to read 256bytes)
-int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
-
- if (!data || len == 0)
- return 0;
-
- // extra wait 500us (514us measured)
- // 200us (xx measured)
- WaitUS(600);
- bool bBreak = true;
- uint16_t readcount = 0;
-
- do {
- if (!I2C_Start())
- return 0;
-
- // 0xB0 / 0xC0 == i2c write
- I2C_SendByte(device_address & 0xFE);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(device_cmd);
- if (!I2C_WaitAck())
- break;
-
- // 0xB1 / 0xC1 == i2c read
- I2C_Start();
- I2C_SendByte(device_address | 1);
- if (!I2C_WaitAck())
- break;
-
- bBreak = false;
- } while (false);
-
- if (bBreak) {
- I2C_Stop();
- if (DBGLEVEL > 3) DbpString(I2C_ERROR);
- return 0;
- }
-
- while (len) {
-
- int16_t tmp = I2C_ReadByte();
- if (tmp < 0)
- return tmp;
-
- *data = (uint8_t)tmp & 0xFF;
-
- len--;
- // 读取的第一个字节为后续长度
- // The first byte in response is the message length
- if (!readcount && (len > *data)) {
- len = *data;
- } else {
- data++;
- }
- readcount++;
-
- // acknowledgements. After last byte write NACK.
- if (len == 0)
- I2C_NoAck();
- else
- I2C_Ack();
- }
-
- I2C_Stop();
-
- // return bytecount - first byte (which is length byte)
- return --readcount;
-}
-
-int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
- //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP
- bool bBreak = true;
- uint8_t readcount = 0;
-
- // sending
- do {
- if (!I2C_Start())
- return 0;
-
- // 0xB0 / 0xC0 i2c write
- I2C_SendByte(device_address & 0xFE);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(msb);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(lsb);
- if (!I2C_WaitAck())
- break;
-
- // 0xB1 / 0xC1 i2c read
- I2C_Start();
- I2C_SendByte(device_address | 1);
- if (!I2C_WaitAck())
- break;
-
- bBreak = false;
- } while (false);
-
- if (bBreak) {
- I2C_Stop();
- if (DBGLEVEL > 3) DbpString(I2C_ERROR);
- return 0;
- }
-
- // reading
- while (len) {
-
- int16_t tmp = I2C_ReadByte();
- if (tmp < 0)
- return tmp;
-
- *data = (uint8_t)tmp & 0xFF;
-
- data++;
- readcount++;
- len--;
-
- // acknowledgements. After last byte write NACK.
- if (len == 0)
- I2C_NoAck();
- else
- I2C_Ack();
- }
-
- I2C_Stop();
- return readcount;
-}
-
-bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
- //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP
- bool bBreak = true;
-
- do {
- if (!I2C_Start())
- return false;
-
- // 0xB0 == i2c write
- I2C_SendByte(device_address & 0xFE);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(msb);
- if (!I2C_WaitAck())
- break;
-
- I2C_SendByte(lsb);
- if (!I2C_WaitAck())
- break;
-
- while (len) {
- I2C_SendByte(*data);
- if (!I2C_WaitAck())
- break;
-
- len--;
- data++;
- }
-
- if (len == 0)
- bBreak = false;
- } while (false);
-
- I2C_Stop();
- if (bBreak) {
- if (DBGLEVEL > 3) DbpString(I2C_ERROR);
- return false;
- }
- return true;
-}
-
-void I2C_print_status(void) {
- DbpString(_BLUE_("Smart card module (ISO 7816)"));
- uint8_t maj, min;
- if (I2C_get_version(&maj, &min) == PM3_SUCCESS)
- Dbprintf(" version................." _YELLOW_("v%x.%02d"), maj, min);
- else
- DbpString(" version................." _RED_("FAILED"));
-}
-
-int I2C_get_version(uint8_t *maj, uint8_t *min) {
- uint8_t resp[] = {0, 0, 0, 0};
- I2C_Reset_EnterMainProgram();
- uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN);
- if (len > 0) {
- *maj = resp[0];
- *min = resp[1];
- return PM3_SUCCESS;
- } else {
- return PM3_EDEVNOTSUPP;
- }
-}
-
-// Will read response from smart card module, retries 3 times to get the data.
-bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
-
- uint8_t i = 3;
- int16_t len = 0;
- while (i--) {
-
- I2C_WaitForSim();
-
- len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
-
- if (len > 1) {
- break;
- } else if (len == 1) {
- continue;
- } else if (len <= 0) {
- return false;
- }
- }
-
- // after three
- if (len <= 1)
- return false;
-
- *destlen = (uint8_t)len & 0xFF;
- return true;
-}
-
-bool GetATR(smart_card_atr_t *card_ptr) {
-
- if (!card_ptr)
- return false;
-
- card_ptr->atr_len = 0;
- memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
-
-
- // Send ATR
- // start [C0 01] stop start C1 len aa bb cc stop]
- I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN);
-
- //wait for sim card to answer.
- // 1byte = 1ms , max frame 256bytes. SHould wait 256ms atleast just in case.
- if (!I2C_WaitForSim())
- return false;
-
- // read bytes from module
- uint8_t len = sizeof(card_ptr->atr);
- if (!sc_rx_bytes(card_ptr->atr, &len))
- return false;
-
- uint8_t pos_td = 1;
- if ((card_ptr->atr[1] & 0x10) == 0x10) pos_td++;
- if ((card_ptr->atr[1] & 0x20) == 0x20) pos_td++;
- if ((card_ptr->atr[1] & 0x40) == 0x40) pos_td++;
-
- // T0 indicate presence T=0 vs T=1. T=1 has checksum TCK
- if ((card_ptr->atr[1] & 0x80) == 0x80) {
-
- pos_td++;
-
- // 1 == T1 , presence of checksum TCK
- if ((card_ptr->atr[pos_td] & 0x01) == 0x01) {
-
- uint8_t chksum = 0;
- // xor property. will be zero when xored with chksum.
- for (uint8_t i = 1; i < len; ++i)
- chksum ^= card_ptr->atr[i];
-
- if (chksum) {
- if (DBGLEVEL > 2) DbpString("Wrong ATR checksum");
- }
- }
- }
-
- card_ptr->atr_len = len;
- LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
- return true;
-}
-
-void SmartCardAtr(void) {
- smart_card_atr_t card;
- LED_D_ON();
- clear_trace();
- set_tracing(true);
- I2C_Reset_EnterMainProgram();
- bool isOK = GetATR(&card);
- reply_old(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
- set_tracing(false);
- LEDsoff();
-}
-
-void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
-
- LED_D_ON();
-
- uint8_t len = 0;
- uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
- smartcard_command_t flags = arg0;
-
- if ((flags & SC_CONNECT))
- clear_trace();
-
- set_tracing(true);
-
- if ((flags & SC_CONNECT)) {
-
- I2C_Reset_EnterMainProgram();
-
- if ((flags & SC_SELECT)) {
- smart_card_atr_t card;
- bool gotATR = GetATR(&card);
- //reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
- if (!gotATR)
- goto OUT;
- }
- }
-
- if ((flags & SC_RAW) || (flags & SC_RAW_T0)) {
-
- LogTrace(data, arg1, 0, 0, NULL, true);
-
- // Send raw bytes
- // asBytes = A0 A4 00 00 02
- // arg1 = len 5
- bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN);
- if (!res && DBGLEVEL > 3) DbpString(I2C_ERROR);
-
- // read bytes from module
- len = ISO7618_MAX_FRAME;
- res = sc_rx_bytes(resp, &len);
- if (res) {
- LogTrace(resp, len, 0, 0, NULL, false);
- } else {
- len = 0;
- }
- }
-OUT:
- reply_old(CMD_ACK, len, 0, 0, resp, len);
- BigBuf_free();
- set_tracing(false);
- LEDsoff();
-}
-
-void SmartCardUpgrade(uint64_t arg0) {
-
- LED_C_ON();
-
-#define I2C_BLOCK_SIZE 128
- // write. Sector0, with 11,22,33,44
- // erase is 128bytes, and takes 50ms to execute
-
- I2C_Reset_EnterBootloader();
-
- bool isOK = true;
- uint16_t length = arg0, pos = 0;
- uint8_t *fwdata = BigBuf_get_addr();
- uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE);
-
- while (length) {
-
- uint8_t msb = (pos >> 8) & 0xFF;
- uint8_t lsb = pos & 0xFF;
-
- Dbprintf("FW %02X%02X", msb, lsb);
-
- size_t size = MIN(I2C_BLOCK_SIZE, length);
-
- // write
- int16_t res = I2C_WriteFW(fwdata + pos, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
- if (!res) {
- DbpString("Writing failed");
- isOK = false;
- break;
- }
-
- // writing takes time.
- WaitMS(50);
-
- // read
- res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
- if (res <= 0) {
- DbpString("Reading back failed");
- isOK = false;
- break;
- }
-
- // cmp
- if (0 != memcmp(fwdata + pos, verfiydata, size)) {
- DbpString("not equal data");
- isOK = false;
- break;
- }
-
- length -= size;
- pos += size;
- }
- reply_mix(CMD_ACK, isOK, pos, 0, 0, 0);
- LED_C_OFF();
- BigBuf_free();
-}
-
-void SmartCardSetBaud(uint64_t arg0) {
-}
-
-void SmartCardSetClock(uint64_t arg0) {
- LED_D_ON();
- set_tracing(true);
- I2C_Reset_EnterMainProgram();
-
- // Send SIM CLC
- // start [C0 05 xx] stop
- I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN);
-
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- set_tracing(false);
- LEDsoff();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/i2c.h b/pm3rdv4rrg/src/main/cpp/armsrc/i2c.h
deleted file mode 100644
index 7b170750..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/i2c.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef __I2C_H
-#define __I2C_H
-
-#include "common.h"
-#include "mifare.h"
-
-#define I2C_DEVICE_ADDRESS_BOOT 0xB0
-#define I2C_DEVICE_ADDRESS_MAIN 0xC0
-
-#define I2C_DEVICE_CMD_GENERATE_ATR 0x01
-#define I2C_DEVICE_CMD_SEND 0x02
-#define I2C_DEVICE_CMD_READ 0x03
-#define I2C_DEVICE_CMD_SETBAUD 0x04
-#define I2C_DEVICE_CMD_SIM_CLC 0x05
-#define I2C_DEVICE_CMD_GETVERSION 0x06
-#define I2C_DEVICE_CMD_SEND_T0 0x07
-
-void I2C_recovery(void);
-void I2C_init(void);
-void I2C_Reset(void);
-void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA);
-
-void I2C_Reset_EnterMainProgram(void);
-void I2C_Reset_EnterBootloader(void);
-
-bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address);
-
-bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address);
-bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address);
-int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address);
-
-// for firmware
-int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
-bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
-
-//
-bool GetATR(smart_card_atr_t *card_ptr);
-
-// generice functions
-void SmartCardAtr(void);
-void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data);
-void SmartCardUpgrade(uint64_t arg0);
-void SmartCardSetBaud(uint64_t arg0);
-void SmartCardSetClock(uint64_t arg0);
-void I2C_print_status(void);
-int I2C_get_version(uint8_t *maj, uint8_t *min);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iclass.c b/pm3rdv4rrg/src/main/cpp/armsrc/iclass.c
deleted file mode 100644
index 9ab2b501..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iclass.c
+++ /dev/null
@@ -1,2497 +0,0 @@
-//-----------------------------------------------------------------------------
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-// Gerhard de Koning Gans - May 2011
-// Gerhard de Koning Gans - June 2012 - Added iClass card and reader emulation
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support iClass.
-//-----------------------------------------------------------------------------
-// Based on ISO14443a implementation. Still in experimental phase.
-// Contribution made during a security research at Radboud University Nijmegen
-//
-// Please feel free to contribute and extend iClass support!!
-//-----------------------------------------------------------------------------
-//
-// FIX:
-// ====
-// We still have sometimes a demodulation error when sniffing iClass communication.
-// The resulting trace of a read-block-03 command may look something like this:
-//
-// + 22279: : 0c 03 e8 01
-//
-// ...with an incorrect answer...
-//
-// + 85: 0: TAG ff! ff! ff! ff! ff! ff! ff! ff! bb 33 bb 00 01! 0e! 04! bb !crc
-//
-// We still left the error signalling bytes in the traces like 0xbb
-//
-// A correct trace should look like this:
-//
-// + 21112: : 0c 03 e8 01
-// + 85: 0: TAG ff ff ff ff ff ff ff ff ea f5
-//
-//-----------------------------------------------------------------------------
-
-#include "iclass.h"
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-// Needed for CRC in emulation mode;
-// same construction as in ISO 14443;
-// different initial value (CRC_ICLASS)
-#include "crc16.h"
-#include "optimized_cipher.h"
-
-#include "appmain.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "string.h"
-#include "util.h"
-#include "dbprint.h"
-#include "protocols.h"
-#include "ticks.h"
-
-static int g_wait = 290;
-static int timeout = 5000;
-static uint32_t time_rdr = 0;
-static uint32_t time_response = 0;
-
-static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
-int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf);
-
-#define MODE_SIM_CSN 0
-#define MODE_EXIT_AFTER_MAC 1
-#define MODE_FULLSIM 2
-
-#ifndef ICLASS_DMA_BUFFER_SIZE
-# define ICLASS_DMA_BUFFER_SIZE 256
-#endif
-
-// The length of a received command will in most cases be no more than 18 bytes.
-// 32 should be enough!
-#ifndef ICLASS_BUFFER_SIZE
-#define ICLASS_BUFFER_SIZE 32
-#endif
-
-#define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1)
-
-//-----------------------------------------------------------------------------
-// The software UART that receives commands from the reader, and its state
-// variables.
-//-----------------------------------------------------------------------------
-/*
-typedef struct {
- enum {
- STATE_UNSYNCD,
- STATE_START_OF_COMMUNICATION,
- STATE_RECEIVING
- } state;
- uint16_t shiftReg;
- int bitCnt;
- int byteCnt;
-// int byteCntMax;
- int posCnt;
- int nOutOfCnt;
- int OutOfCnt;
- int syncBit;
- int samples;
- int highCnt;
- int swapper;
- int counter;
- int bitBuffer;
- int dropPosition;
- uint8_t *output;
-} tUartIc;
-*/
-typedef struct {
- enum {
- DEMOD_IC_UNSYNCD,
- DEMOD_IC_START_OF_COMMUNICATION,
- DEMOD_IC_START_OF_COMMUNICATION2,
- DEMOD_IC_START_OF_COMMUNICATION3,
- DEMOD_IC_SOF_COMPLETE,
- DEMOD_IC_MANCHESTER_D,
- DEMOD_IC_MANCHESTER_E,
- DEMOD_IC_END_OF_COMMUNICATION,
- DEMOD_IC_END_OF_COMMUNICATION2,
- DEMOD_IC_MANCHESTER_F,
- DEMOD_IC_ERROR_WAIT
- } state;
- int bitCount;
- int posCount;
- int syncBit;
- uint16_t shiftReg;
- uint32_t buffer;
- uint32_t buffer2;
- uint32_t buffer3;
- int buff;
- int samples;
- int len;
- enum {
- SUB_NONE,
- SUB_FIRST_HALF,
- SUB_SECOND_HALF,
- SUB_BOTH
- } sub;
- uint8_t *output;
-} tDemodIc;
-
-/*
-* Abrasive's uart implementation
-* https://github.com/abrasive/proxmark3/commit/2b8bff7daea8ae1193bf7ee29b1fa46e95218902
-*/
-// Static vars for UART
-typedef struct {
- bool synced;
- bool frame;
- bool frame_done;
- uint8_t *buf;
- int len;
-} tUartIc;
-static tUartIc Uart;
-
-static void OnError(uint8_t reason) {
- reply_mix(CMD_ACK, 0, reason, 0, 0, 0);
- switch_off();
-}
-
-static void uart_reset(void) {
- Uart.frame_done = false;
- Uart.synced = false;
- Uart.frame = false;
-}
-
-static void uart_init(uint8_t *data) {
- Uart.buf = data;
- uart_reset();
-}
-
-static void uart_bit(uint8_t bit) {
- static uint8_t buf = 0xff;
- static uint8_t n_buf;
- static int nmsg_byte;
- buf <<= 1;
- buf |= bit ? 1 : 0;
-
- if (!Uart.frame) {
- if (buf == 0x7b) { // 0b0111 1011
- Uart.frame = true;
- n_buf = 0;
- Uart.len = 0;
- nmsg_byte = 0;
- }
- } else {
- static uint8_t msg_byte;
- n_buf++;
- if (n_buf == 8) {
- msg_byte >>= 2;
- switch (buf) {
- case 0xbf: // 0 - 1011 1111
- break;
- case 0xef: // 1 - 1110 1111
- msg_byte |= (1 << 6);
- break;
- case 0xfb: // 2 - 1111 1011
- msg_byte |= (2 << 6);
- break;
- case 0xfe: // 3 - 1111 1110
- msg_byte |= (3 << 6);
- break;
- case 0xdf: // eof - 1101 1111
- Uart.frame = false;
- Uart.synced = false;
- Uart.frame_done = true;
- break;
- default:
- Uart.frame = false;
- Uart.synced = false;
- Dbprintf("[-] bad %02X at %d:%d", buf, Uart.len, nmsg_byte);
- }
-
- if (Uart.frame) { // data bits
- nmsg_byte += 2;
- if (nmsg_byte >= 8) {
- Uart.buf[Uart.len++] = msg_byte;
- nmsg_byte = 0;
- }
- }
- n_buf = 0;
- buf = 0xff;
- }
- }
-}
-
-static void uart_samples(uint8_t byte) {
- static uint32_t buf;
- static int window;
- static int drop_next = 0;
-
- uint32_t falling;
- int lz;
-
- if (!Uart.synced) {
- if (byte == 0xFF)
- return;
- buf = 0xFFFFFFFF;
- window = 0;
- drop_next = 0;
- Uart.synced = true;
- }
-
- buf <<= 8;
- buf |= byte;
-
- if (drop_next) {
- drop_next = 0;
- return;
- }
-
-again:
- falling = ~buf & ((buf >> 1) ^ buf) & (0xFF << window);
-
- uart_bit(!falling);
-
- if (!falling)
- return;
-
- lz = __builtin_clz(falling) - 24 + window;
-
- // aim to get falling edge on fourth-leftmost bit of window
- window += 3 - lz;
-
- if (window < 0) {
- window += 8;
- drop_next = 1;
- } else if (window >= 8) {
- window -= 8;
- goto again;
- }
-}
-
-
-/*
-static void UartReset(){
- Uart.state = STATE_UNSYNCD;
- Uart.shiftReg = 0;
- Uart.bitCnt = 0;
- Uart.byteCnt = 0;
- Uart.posCnt = 0;
- Uart.nOutOfCnt = 0;
- Uart.OutOfCnt = 0;
- Uart.syncBit = 0;
- Uart.samples = 0;
- Uart.highCnt = 0;
- Uart.swapper = 0;
- Uart.counter = 0;
- Uart.bitBuffer = 0;
- Uart.dropPosition = 0;
-}
-*/
-
-/*
-* READER TO CARD
-* 1 out of 4 Decoding
-* 1 out of 256 Decoding
-*/
-/*
-static RAMFUNC int OutOfNDecoding(int bit) {
- //int error = 0;
- int bitright;
-
- if (!Uart.bitBuffer) {
- Uart.bitBuffer = bit ^ 0xFF0;
- return false;
- } else {
- Uart.bitBuffer <<= 4;
- Uart.bitBuffer ^= bit;
- }
-
- // if (Uart.swapper) {
- // Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
- // Uart.byteCnt++;
- // Uart.swapper = 0;
- // if (Uart.byteCnt > 15) return true;
- // }
- // else {
- // Uart.swapper = 1;
- // }
-
- if (Uart.state != STATE_UNSYNCD) {
- Uart.posCnt++;
-
- if ((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit)
- bit = 0;
- else
- bit = 1;
-
- if (((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit)
- bitright = 0;
- else
- bitright = 1;
-
- if(bit != bitright)
- bit = bitright;
-
-
- // So, now we only have to deal with *bit*, lets see...
- if (Uart.posCnt == 1) {
- // measurement first half bitperiod
- if (!bit) {
- // Drop in first half means that we are either seeing
- // an SOF or an EOF.
-
- if (Uart.nOutOfCnt == 1) {
- // End of Communication
- Uart.state = STATE_UNSYNCD;
- Uart.highCnt = 0;
- if (Uart.byteCnt == 0) {
- // Its not straightforward to show single EOFs
- // So just leave it and do not return TRUE
- Uart.output[0] = 0xf0;
- Uart.byteCnt++;
- } else {
- return true;
- }
- } else if (Uart.state != STATE_START_OF_COMMUNICATION) {
- // When not part of SOF or EOF, it is an error
- Uart.state = STATE_UNSYNCD;
- Uart.highCnt = 0;
- //error = 4;
- }
- }
- } else {
- // measurement second half bitperiod
- // Count the bitslot we are in... (ISO 15693)
- Uart.nOutOfCnt++;
-
- if (!bit) {
- if (Uart.dropPosition) {
- if (Uart.state == STATE_START_OF_COMMUNICATION) {
- //error = 1;
- } else {
- //error = 7;
- }
- // It is an error if we already have seen a drop in current frame
- Uart.state = STATE_UNSYNCD;
- Uart.highCnt = 0;
- } else {
- Uart.dropPosition = Uart.nOutOfCnt;
- }
- }
- Uart.posCnt = 0;
-
- if (Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) {
- Uart.nOutOfCnt = 0;
-
- if (Uart.state == STATE_START_OF_COMMUNICATION) {
- if (Uart.dropPosition == 4) {
- Uart.state = STATE_RECEIVING;
- Uart.OutOfCnt = 256;
- } else if (Uart.dropPosition == 3) {
- Uart.state = STATE_RECEIVING;
- Uart.OutOfCnt = 4;
- //Uart.output[Uart.byteCnt] = 0xdd;
- //Uart.byteCnt++;
- } else {
- Uart.state = STATE_UNSYNCD;
- Uart.highCnt = 0;
- }
- Uart.dropPosition = 0;
- } else {
- // RECEIVING DATA
- // 1 out of 4
- if (!Uart.dropPosition) {
- Uart.state = STATE_UNSYNCD;
- Uart.highCnt = 0;
- //error = 9;
- } else {
- Uart.shiftReg >>= 2;
-
- // Swap bit order
- Uart.dropPosition--;
- //if(Uart.dropPosition == 1) { Uart.dropPosition = 2; }
- //else if(Uart.dropPosition == 2) { Uart.dropPosition = 1; }
-
- Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6);
- Uart.bitCnt += 2;
- Uart.dropPosition = 0;
-
- if (Uart.bitCnt == 8) {
- Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff);
- Uart.byteCnt++;
- Uart.bitCnt = 0;
- Uart.shiftReg = 0;
- }
- }
- }
- } else if (Uart.nOutOfCnt == Uart.OutOfCnt) {
- // RECEIVING DATA
- // 1 out of 256
- if (!Uart.dropPosition) {
- Uart.state = STATE_UNSYNCD;
- Uart.highCnt = 0;
- //error = 3;
- } else {
- Uart.dropPosition--;
- Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff);
- Uart.byteCnt++;
- Uart.bitCnt = 0;
- Uart.shiftReg = 0;
- Uart.nOutOfCnt = 0;
- Uart.dropPosition = 0;
- }
- }
-*/
-/*if (error) {
- Uart.output[Uart.byteCnt] = 0xAA;
- Uart.byteCnt++;
- Uart.output[Uart.byteCnt] = error & 0xFF;
- Uart.byteCnt++;
- Uart.output[Uart.byteCnt] = 0xAA;
- Uart.byteCnt++;
- Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF;
- Uart.byteCnt++;
- Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
- Uart.byteCnt++;
- Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF;
- Uart.byteCnt++;
- Uart.output[Uart.byteCnt] = 0xAA;
- Uart.byteCnt++;
- return true;
-}*/
-/*
- }
- } else {
- bit = Uart.bitBuffer & 0xf0;
- bit >>= 4;
- bit ^= 0x0F; // drops become 1s ;-)
- if (bit) {
- // should have been high or at least (4 * 128) / fc
- // according to ISO this should be at least (9 * 128 + 20) / fc
- if (Uart.highCnt == 8) {
- // we went low, so this could be start of communication
- // it turns out to be safer to choose a less significant
- // syncbit... so we check whether the neighbour also represents the drop
- Uart.posCnt = 1; // apparently we are busy with our first half bit period
- Uart.syncBit = bit & 8;
- Uart.samples = 3;
-
- if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; }
- else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; }
-
- if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; }
- else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; }
-
- if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0;
- if (Uart.syncBit && (Uart.bitBuffer & 8)) {
- Uart.syncBit = 8;
-
- // the first half bit period is expected in next sample
- Uart.posCnt = 0;
- Uart.samples = 3;
- }
- } else if (bit & 1) { Uart.syncBit = bit & 1; Uart.samples = 0; }
-
- Uart.syncBit <<= 4;
- Uart.state = STATE_START_OF_COMMUNICATION;
- Uart.bitCnt = 0;
- Uart.byteCnt = 0;
- Uart.nOutOfCnt = 0;
- Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256
- Uart.dropPosition = 0;
- Uart.shiftReg = 0;
- //error = 0;
- } else {
- Uart.highCnt = 0;
- }
- } else {
- if (Uart.highCnt < 8)
- Uart.highCnt++;
- }
- }
- return false;
-}
-*/
-//=============================================================================
-// Manchester
-//=============================================================================
-static tDemodIc Demod;
-static void DemodIcReset() {
- Demod.bitCount = 0;
- Demod.posCount = 0;
- Demod.syncBit = 0;
- Demod.shiftReg = 0;
- Demod.buffer = 0;
- Demod.buffer2 = 0;
- Demod.buffer3 = 0;
- Demod.buff = 0;
- Demod.samples = 0;
- Demod.len = 0;
- Demod.sub = SUB_NONE;
- Demod.state = DEMOD_IC_UNSYNCD;
-}
-static void DemodIcInit(uint8_t *data) {
- Demod.output = data;
- DemodIcReset();
-}
-
-// UART debug
-// it adds the debug values which will be put in the tracelog,
-// visible on client when running 'hf list iclass'
-/*
-pm3 --> hf li iclass
-Recorded Activity (TraceLen = 162 bytes)
- Start | End | Src | Data (! denotes parity error) | CRC | Annotation |
-------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|
- 0 | 0 | Rdr |0a | | ACTALL
- 1280 | 1280 | Tag |bb! 33! bb! 01 02 04 08 bb! | ok |
- 1280 | 1280 | Rdr |0c | | IDENTIFY
- 1616 | 1616 | Tag |bb! 33! bb! 00! 02 00! 02 bb! | ok |
- 1616 | 1616 | Rdr |0a | | ACTALL
- 2336 | 2336 | Tag |bb! d4! bb! 02 08 00! 08 bb! | ok |
- 2336 | 2336 | Rdr |0c | | IDENTIFY
- 2448 | 2448 | Tag |bb! 33! bb! 00! 00! 00! 02 bb! | ok |
- 2448 | 2448 | Rdr |0a | | ACTALL
- 2720 | 2720 | Tag |bb! d4! bb! 08 0b 01 04 bb! | ok |
- 2720 | 2720 | Rdr |0c | | IDENTIFY
- 3232 | 3232 | Tag |bb! d4! bb! 02 02 08 04 bb! | ok |
-*/
-static void uart_debug(int error, int bit) {
- Demod.output[Demod.len] = 0xBB;
- Demod.len++;
- Demod.output[Demod.len] = error & 0xFF;
- Demod.len++;
- Demod.output[Demod.len] = 0xBB;
- Demod.len++;
- Demod.output[Demod.len] = bit & 0xFF;
- Demod.len++;
- Demod.output[Demod.len] = Demod.buffer & 0xFF;
- Demod.len++;
- // Look harder ;-)
- Demod.output[Demod.len] = Demod.buffer2 & 0xFF;
- Demod.len++;
- Demod.output[Demod.len] = Demod.syncBit & 0xFF;
- Demod.len++;
- Demod.output[Demod.len] = 0xBB;
- Demod.len++;
-}
-
-/*
-* CARD TO READER
-* in ISO15693-2 mode - Manchester
-* in ISO 14443b - BPSK coding
-*
-* Timings:
-* ISO 15693-2
-* Tout = 330 µs, Tprog 1 = 4 to 15 ms, Tslot = 330 µs + (number of slots x 160 µs)
-* ISO 14443a
-* Tout = 100 µs, Tprog = 4 to 15 ms, Tslot = 100 µs+ (number of slots x 80 µs)
-* ISO 14443b
- Tout = 76 µs, Tprog = 4 to 15 ms, Tslot = 119 µs+ (number of slots x 150 µs)
-*
-*
-* So for current implementation in ISO15693, its 330 µs from end of reader, to start of card.
-*/
-static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) {
- int bit;
- int modulation;
- int error = 0;
-
- bit = Demod.buffer;
- Demod.buffer = Demod.buffer2;
- Demod.buffer2 = Demod.buffer3;
- Demod.buffer3 = v;
-
- // too few bits?
- if (Demod.buff < 3) {
- Demod.buff++;
- return false;
- }
-
- if (Demod.state == DEMOD_IC_UNSYNCD) {
- Demod.output[Demod.len] = 0xfa;
- Demod.syncBit = 0;
- //Demod.samples = 0;
- Demod.posCount = 1; // This is the first half bit period, so after syncing handle the second part
-
- if (bit & 0x08)
- Demod.syncBit = 0x08;
-
- if (bit & 0x04) {
- if (Demod.syncBit)
- bit <<= 4;
-
- Demod.syncBit = 0x04;
- }
-
- if (bit & 0x02) {
- if (Demod.syncBit)
- bit <<= 2;
-
- Demod.syncBit = 0x02;
- }
-
- if (bit & 0x01 && Demod.syncBit)
- Demod.syncBit = 0x01;
-
- if (Demod.syncBit) {
- Demod.len = 0;
- Demod.state = DEMOD_IC_START_OF_COMMUNICATION;
- Demod.sub = SUB_FIRST_HALF;
- Demod.bitCount = 0;
- Demod.shiftReg = 0;
- Demod.samples = 0;
-
- if (Demod.posCount) {
-
- switch (Demod.syncBit) {
- case 0x08:
- Demod.samples = 3;
- break;
- case 0x04:
- Demod.samples = 2;
- break;
- case 0x02:
- Demod.samples = 1;
- break;
- case 0x01:
- Demod.samples = 0;
- break;
- }
- // SOF must be long burst... otherwise stay unsynced!!!
- if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit))
- Demod.state = DEMOD_IC_UNSYNCD;
-
- } else {
- // SOF must be long burst... otherwise stay unsynced!!!
- if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) {
- Demod.state = DEMOD_IC_UNSYNCD;
- error = 0x88;
- uart_debug(error, bit);
- return false;
- }
- }
- }
- return false;
- }
-
- // state is DEMOD is in SYNC from here on.
-
- modulation = bit & Demod.syncBit;
- modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit;
- Demod.samples += 4;
-
- if (Demod.posCount == 0) {
- Demod.posCount = 1;
- Demod.sub = (modulation) ? SUB_FIRST_HALF : SUB_NONE;
- return false;
- }
-
- Demod.posCount = 0;
-
- if (modulation) {
-
- if (Demod.sub == SUB_FIRST_HALF)
- Demod.sub = SUB_BOTH;
- else
- Demod.sub = SUB_SECOND_HALF;
- }
-
- if (Demod.sub == SUB_NONE) {
- if (Demod.state == DEMOD_IC_SOF_COMPLETE) {
- Demod.output[Demod.len] = 0x0f;
- Demod.len++;
- Demod.state = DEMOD_IC_UNSYNCD;
- return true;
- } else {
- Demod.state = DEMOD_IC_ERROR_WAIT;
- error = 0x33;
- }
- }
-
- switch (Demod.state) {
-
- case DEMOD_IC_START_OF_COMMUNICATION:
- if (Demod.sub == SUB_BOTH) {
-
- Demod.state = DEMOD_IC_START_OF_COMMUNICATION2;
- Demod.posCount = 1;
- Demod.sub = SUB_NONE;
- } else {
- Demod.output[Demod.len] = 0xab;
- Demod.state = DEMOD_IC_ERROR_WAIT;
- error = 0xd2;
- }
- break;
-
- case DEMOD_IC_START_OF_COMMUNICATION2:
- if (Demod.sub == SUB_SECOND_HALF) {
- Demod.state = DEMOD_IC_START_OF_COMMUNICATION3;
- } else {
- Demod.output[Demod.len] = 0xab;
- Demod.state = DEMOD_IC_ERROR_WAIT;
- error = 0xd3;
- }
- break;
-
- case DEMOD_IC_START_OF_COMMUNICATION3:
- if (Demod.sub == SUB_SECOND_HALF) {
- Demod.state = DEMOD_IC_SOF_COMPLETE;
- } else {
- Demod.output[Demod.len] = 0xab;
- Demod.state = DEMOD_IC_ERROR_WAIT;
- error = 0xd4;
- }
- break;
-
- case DEMOD_IC_SOF_COMPLETE:
- case DEMOD_IC_MANCHESTER_D:
- case DEMOD_IC_MANCHESTER_E:
- // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443)
- // 00001111 = 1 (0 in 14443)
- if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF
- Demod.bitCount++;
- Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100;
- Demod.state = DEMOD_IC_MANCHESTER_D;
- } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF
- Demod.bitCount++;
- Demod.shiftReg >>= 1;
- Demod.state = DEMOD_IC_MANCHESTER_E;
- } else if (Demod.sub == SUB_BOTH) {
- Demod.state = DEMOD_IC_MANCHESTER_F;
- } else {
- Demod.state = DEMOD_IC_ERROR_WAIT;
- error = 0x55;
- }
- break;
-
- case DEMOD_IC_MANCHESTER_F:
- // Tag response does not need to be a complete byte!
- if (Demod.len > 0 || Demod.bitCount > 0) {
- if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF
- Demod.shiftReg >>= (9 - Demod.bitCount); // right align data
- Demod.output[Demod.len] = Demod.shiftReg & 0xff;
- Demod.len++;
- }
-
- Demod.state = DEMOD_IC_UNSYNCD;
- return true;
- } else {
- Demod.output[Demod.len] = 0xad;
- Demod.state = DEMOD_IC_ERROR_WAIT;
- error = 0x03;
- }
- break;
-
- case DEMOD_IC_ERROR_WAIT:
- Demod.state = DEMOD_IC_UNSYNCD;
- break;
-
- default:
- Demod.output[Demod.len] = 0xdd;
- Demod.state = DEMOD_IC_UNSYNCD;
- break;
- }
-
- if (Demod.bitCount >= 8) {
- Demod.shiftReg >>= 1;
- Demod.output[Demod.len] = (Demod.shiftReg & 0xff);
- Demod.len++;
- Demod.bitCount = 0;
- Demod.shiftReg = 0;
- }
-
- if (error) {
- uart_debug(error, bit);
- return true;
- }
-
- return false;
-}
-
-//=============================================================================
-// Finally, a `sniffer' for iClass communication
-// Both sides of communication!
-//=============================================================================
-static void iclass_setup_sniff(void) {
- if (DBGLEVEL > 3) Dbprintf("iclass_setup_sniff Enter");
-
- LEDsoff();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Set up the synchronous serial port
- FpgaSetupSsc();
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // Initialize Demod and Uart structs
- DemodIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
-
- uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE));
- //UartIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
-
- if (DBGLEVEL > 1) {
- // Print debug information about the buffer sizes
- Dbprintf("[+] Sniffing buffers initialized:");
- Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
- Dbprintf(" Reader -> tag: %i bytes", ICLASS_BUFFER_SIZE);
- Dbprintf(" tag -> Reader: %i bytes", ICLASS_BUFFER_SIZE);
- Dbprintf(" DMA: %i bytes", ICLASS_DMA_BUFFER_SIZE);
- }
-
- // Set FPGA in the appropriate mode
- // put the FPGA in the appropriate mode
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
- SpinDelay(200);
-
- // Start the SSP timer
- StartCountSspClk();
-
- LED_A_ON();
- if (DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit");
-}
-
-//-----------------------------------------------------------------------------
-// Record the sequence of commands sent by the reader to the tag, with
-// triggering so that we start recording at the point that the tag is moved
-// near the reader.
-//-----------------------------------------------------------------------------
-// turn off afterwards
-void RAMFUNC SniffIClass(void) {
-
- //int datalen = 0;
- uint32_t previous_data = 0;
- uint32_t time_0 = 0, time_start = 0, time_stop;
- uint32_t sniffCounter = 0;
- bool TagIsActive = false;
- bool ReaderIsActive = false;
-
- iclass_setup_sniff();
-
- // The DMA buffer, used to stream samples from the FPGA
- // *dmaBuf is the start reference.
- uint8_t *dmaBuf = BigBuf_malloc(ICLASS_DMA_BUFFER_SIZE);
- // pointer to samples from fpga
- uint8_t *data = dmaBuf;
-
- // Setup and start DMA.
- if (!FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE)) {
- if (DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting");
- return;
- }
-
- // time ZERO, the point from which it all is calculated.
- time_0 = GetCountSspClk();
-
- // loop and listen
- // every sample (1byte in data),
- // contains HIGH nibble = reader data
- // contains LOW nibble = tag data
- // so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes)
- // since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes)
- uint16_t checked = 0;
- for (;;) {
- WDT_HIT();
-
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) break;
- checked = 0;
- }
- ++checked;
-
- previous_data <<= 8;
- previous_data |= *data;
-
- sniffCounter++;
- data++;
-
- if (data == dmaBuf + ICLASS_DMA_BUFFER_SIZE) {
- data = dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = ICLASS_DMA_BUFFER_SIZE;
- }
-
- // every odd sample
- if (sniffCounter & 0x01) {
- // no need to try decoding reader data if the tag is sending
- // READER TO CARD
- if (!TagIsActive) {
- LED_C_INV();
- // HIGH nibble is always reader data.
- uint8_t reader_byte = (previous_data & 0xF0) | (*data >> 4);
- uart_samples(reader_byte);
- if (Uart.frame_done) {
- time_stop = GetCountSspClk() - time_0;
- LogTrace(Uart.buf, Uart.len, time_start, time_stop, NULL, true);
- DemodIcReset();
- uart_reset();
- } else {
- time_start = GetCountSspClk() - time_0;
- }
- ReaderIsActive = Uart.frame_done;
- }
- }
- // every four sample
- if ((sniffCounter % 4) == 0) {
- // need two samples to feed Manchester
- // no need to try decoding tag data if the reader is sending - and we cannot afford the time
- // CARD TO READER
- if (!ReaderIsActive) {
- LED_C_INV();
- // LOW nibble is always tag data.
- /*
- uint32_t tag_byte =
- ((previous_data & 0x0F000000) >> 8 ) |
- ((previous_data & 0x000F0000) >> 4 ) |
- ((previous_data & 0x00000F00) ) |
- ((previous_data & 0x0000000F) << 4 ) |
- (*data & 0xF);
- */
-
-
- uint8_t tag_byte = ((previous_data & 0xF) << 4) | (*data & 0xF);
- if (ManchesterDecoding_iclass(tag_byte)) {
- time_stop = GetCountSspClk() - time_0;
- LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
- DemodIcReset();
- uart_reset();
- } else {
- time_start = GetCountSspClk() - time_0;
- }
- TagIsActive = (Demod.state != DEMOD_IC_UNSYNCD);
- }
- }
- } // end main loop
-
- /*
- if (DBGLEVEL >= 1) {
- DbpString("[+] Sniff statistics:");
- Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false);
- }
- */
- switch_off();
-}
-
-void rotateCSN(uint8_t *originalCSN, uint8_t *rotatedCSN) {
- int i;
- for (i = 0; i < 8; i++)
- rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i + 1) % 8] << 5);
-}
-
-//-----------------------------------------------------------------------------
-// SIMULATION
-// Wait for commands from reader
-// Stop when button is pressed
-// Or return TRUE when command is captured
-//-----------------------------------------------------------------------------
-static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) {
- // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- uart_init(received);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
- // clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint16_t checked = 0;
- for (;;) {
-
- WDT_HIT();
-
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) return false;
- checked = 0;
- }
- ++checked;
-
- // keep tx buffer in a defined state anyway.
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
- AT91C_BASE_SSC->SSC_THR = 0x00;
-
- // wait for byte to become available in rx holding register
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
- uart_samples(b);
- if (Uart.frame_done) {
- *len = Uart.len;
- return true;
- }
- }
- }
- return false;
-}
-
-/*
-static uint8_t encode4Bits(const uint8_t b) {
- // OTA, the least significant bits first
- // Manchester encoding added
- // The columns are
- // 1 - Bit value to send
- // 2 - Reversed (big-endian)
- // 3 - Machester Encoded
- // 4 - Hex values
-
- uint8_t c = b & 0xF;
- switch (c) {
- // 1 2 3 4
- case 15:
- return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55
- case 14:
- return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95
- case 13:
- return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65
- case 12:
- return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5
- case 11:
- return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59
- case 10:
- return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99
- case 9:
- return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69
- case 8:
- return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9
- case 7:
- return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56
- case 6:
- return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96
- case 5:
- return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66
- case 4:
- return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6
- case 3:
- return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a
- case 2:
- return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a
- case 1:
- return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a
- default:
- return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa
- }
-}
-*/
-
-static uint8_t lut_enc[] = { 0xAA, 0x6A, 0x9A, 0x5A, 0xA6, 0x66, 0x96, 0x56, 0xA9, 0x69, 0x99, 0x59, 0xA5, 0x65, 0x95, 0x55 };
-
-//-----------------------------------------------------------------------------
-// Prepare tag messages
-//-----------------------------------------------------------------------------
-static void CodeIClassTagAnswer(const uint8_t *cmd, int len) {
- /*
- * SOF comprises 3 parts;
- * * An unmodulated time of 56.64 us
- * * 24 pulses of 423.75 kHz (fc/32)
- * * A logic 1, which starts with an unmodulated time of 18.88us
- * followed by 8 pulses of 423.75kHz (fc/32)
- *
- *
- * EOF comprises 3 parts:
- * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated
- * time of 18.88us.
- * - 24 pulses of fc/32
- * - An unmodulated time of 56.64 us
- *
- *
- * A logic 0 starts with 8 pulses of fc/32
- * followed by an unmodulated time of 256/fc (~18,88us).
- *
- * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by
- * 8 pulses of fc/32 (also 18.88us)
- *
- * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag,
- * works like this.
- * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us).
- * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us
- *
- * In this mode
- * SOF can be written as 00011101 = 0x1D
- * EOF can be written as 10111000 = 0xb8
- * logic 1 be written as 01 = 0x1
- * logic 0 be written as 10 = 0x2
- *
- * */
- ToSendReset();
-
- // Send SOF
- ToSend[++ToSendMax] = 0x1D;
-
- int i;
- for (i = 0; i < len; i++) {
- uint8_t b = cmd[i];
- ToSend[++ToSendMax] = lut_enc[b & 0xF]; // least significant half
- ToSend[++ToSendMax] = lut_enc[(b >> 4) & 0xF]; // most significant half
- }
-
- // Send EOF
- ToSend[++ToSendMax] = 0xB8;
- //lastProxToAirDuration = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end
- // Convert from last byte pos to length
- ToSendMax++;
-}
-
-// Only SOF
-static void CodeIClassTagSOF() {
- //So far a dummy implementation, not used
- //int lastProxToAirDuration =0;
-
- ToSendReset();
- // Send SOF
- ToSend[++ToSendMax] = 0x1D;
- // lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning
-
- // Convert from last byte pos to length
- ToSendMax++;
-}
-
-/**
- * @brief SimulateIClass simulates an iClass card.
- * @param arg0 type of simulation
- * - 0 uses the first 8 bytes in usb data as CSN
- * - 2 "dismantling iclass"-attack. This mode iterates through all CSN's specified
- * in the usb data. This mode collects MAC from the reader, in order to do an offline
- * attack on the keys. For more info, see "dismantling iclass" and proxclone.com.
- * - Other : Uses the default CSN (031fec8af7ff12e0)
- * @param arg1 - number of CSN's contained in datain (applicable for mode 2 only)
- * @param arg2
- * @param datain
- */
-// turn off afterwards
-void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
-
- if (DBGLEVEL > 3) Dbprintf("[+] iClass_simulate Enter");
-
- LEDsoff();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- // this will clear out bigbuf memory, the eload command must select this before!
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaSetupSsc();
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Enable and clear the trace
- clear_trace();
- set_tracing(true);
-
- uint32_t simType = arg0;
- uint32_t numberOfCSNS = arg1;
-
- //Use the emulator memory for SIM
- uint8_t *emulator = BigBuf_get_EM_addr();
- uint8_t mac_responses[PM3_CMD_DATA_SIZE] = { 0 };
-
- if (simType == 0) {
- // Use the CSN from commandline
- memcpy(emulator, datain, 8);
- doIClassSimulation(MODE_SIM_CSN, NULL);
- } else if (simType == 1) {
- //Default CSN
- uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 };
- // Use the CSN from commandline
- memcpy(emulator, csn_crc, 8);
- doIClassSimulation(MODE_SIM_CSN, NULL);
- } else if (simType == 2) {
-
- Dbprintf("[+] going into attack mode, %d CSNS sent", numberOfCSNS);
- // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
- // in order to collect MAC's from the reader. This can later be used in an offlne-attack
- // in order to obtain the keys, as in the "dismantling iclass"-paper.
-#define EPURSE_MAC_SIZE 16
- int i = 0;
- for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) {
- // The usb data is 512 bytes, fitting 65 8-byte CSNs in there.
-
- memcpy(emulator, datain + (i * 8), 8);
-
- if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
- // Button pressed
- reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
- goto out;
- }
- }
- reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
-
- } else if (simType == 3) {
- //This is 'full sim' mode, where we use the emulator storage for data.
- //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command
- doIClassSimulation(MODE_FULLSIM, NULL);
- } else if (simType == 4) {
-
- // This is the KEYROLL version of sim 2.
- // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process.
- // Keyroll iceman 9 csns * 8 * 2 = 144
- // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240
- Dbprintf("[+] going into attack keyroll mode, %d CSNS sent", numberOfCSNS);
- // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
- // in order to collect MAC's from the reader. This can later be used in an offlne-attack
- // in order to obtain the keys, as in the "dismantling iclass"-paper.
-
- // keyroll mode, reader swaps between old key and new key alternatively when fail a authentication.
- // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys.
- int i = 0;
- // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS
- for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) {
-
- memcpy(emulator, datain + (i * 8), 8);
-
- // keyroll 1
- if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
- reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
- // Button pressed
- goto out;
- }
-
- // keyroll 2
- if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) {
- reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
- // Button pressed
- goto out;
- }
- }
- // double the amount of collected data.
- reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
-
- } else {
- // We may want a mode here where we hardcode the csns to use (from proxclone).
- // That will speed things up a little, but not required just yet.
- DbpString("[-] the mode is not implemented, reserved for future use");
- }
-
-out:
- switch_off();
- BigBuf_free_keep_EM();
-}
-
-/**
- * @brief Does the actual simulation
- * @param csn - csn to use
- * @param breakAfterMacReceived if true, returns after reader MAC has been received.
- */
-int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
-
- // free eventually allocated BigBuf memory
- BigBuf_free_keep_EM();
-
- State cipher_state;
-
- uint8_t *csn = BigBuf_get_EM_addr();
- uint8_t *emulator = csn;
- uint8_t sof_data[] = { 0x0F} ;
-
- // CSN followed by two CRC bytes
- uint8_t anticoll_data[10] = { 0 };
- uint8_t csn_data[10] = { 0 };
- memcpy(csn_data, csn, sizeof(csn_data));
-
- // Construct anticollision-CSN
- rotateCSN(csn_data, anticoll_data);
-
- // Compute CRC on both CSNs
- AddCrc(anticoll_data, 8);
- AddCrc(csn_data, 8);
-
- uint8_t diversified_key[8] = { 0 };
-
- // e-Purse
- uint8_t card_challenge_data[8] = { 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- //uint8_t card_challenge_data[8] = { 0 };
- if (simulationMode == MODE_FULLSIM) {
- //The diversified key should be stored on block 3
- //Get the diversified key from emulator memory
- memcpy(diversified_key, emulator + (8 * 3), 8);
-
- //Card challenge, a.k.a e-purse is on block 2
- memcpy(card_challenge_data, emulator + (8 * 2), 8);
-
- //Precalculate the cipher state, feeding it the CC
- cipher_state = opt_doTagMAC_1(card_challenge_data, diversified_key);
- }
- // set epurse of sim2,4 attack
- if (reader_mac_buf != NULL) {
- memcpy(reader_mac_buf, card_challenge_data, 8);
- }
-
- int exitLoop = 0;
- // Reader 0a
- // Tag 0f
- // Reader 0c
- // Tag anticoll. CSN
- // Reader 81 anticoll. CSN
- // Tag CSN
-
- uint8_t *modulated_response = NULL;
- int modulated_response_size = 0;
- uint8_t *trace_data = NULL;
- int trace_data_size = 0;
-
- // Respond SOF -- takes 1 bytes
- uint8_t *resp_sof = BigBuf_malloc(2);
- int resp_sof_Len;
-
- // Anticollision CSN (rotated CSN)
- // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
- uint8_t *resp_anticoll = BigBuf_malloc(28);
- int resp_anticoll_len;
-
- // CSN
- // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
- uint8_t *resp_csn = BigBuf_malloc(28);
- int resp_csn_len;
-
- // configuration Picopass 2ks
- uint8_t *resp_conf = BigBuf_malloc(28);
- int resp_conf_len;
- uint8_t conf_data[10] = {0x12, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xFF, 0x3C, 0x00, 0x00};
- AddCrc(conf_data, 8);
-
- // e-Purse
- // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
- uint8_t *resp_cc = BigBuf_malloc(28);
- int resp_cc_len;
-
- // Application Issuer Area
- uint8_t *resp_aia = BigBuf_malloc(28);
- int resp_aia_len;
- uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
- if (simulationMode == MODE_FULLSIM) {
-
- // (iceman) this only works for 2KS / 16KS tags.
- // Use application data from block 5
- memcpy(aia_data, emulator + (8 * 5), 8);
-
- // older 2K / 16K tags has its application issuer data on block 2
- }
- AddCrc(aia_data, 8);
-
- // receive command
- uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
- int len = 0;
-
- // Prepare card messages
- ToSendMax = 0;
-
- // First card answer: SOF
- CodeIClassTagSOF();
- memcpy(resp_sof, ToSend, ToSendMax);
- resp_sof_Len = ToSendMax;
-
- // Anticollision CSN
- CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data));
- memcpy(resp_anticoll, ToSend, ToSendMax);
- resp_anticoll_len = ToSendMax;
-
- // CSN
- CodeIClassTagAnswer(csn_data, sizeof(csn_data));
- memcpy(resp_csn, ToSend, ToSendMax);
- resp_csn_len = ToSendMax;
-
- // Configuration
- CodeIClassTagAnswer(conf_data, sizeof(conf_data));
- memcpy(resp_conf, ToSend, ToSendMax);
- resp_conf_len = ToSendMax;
-
- // e-Purse
- CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data));
- memcpy(resp_cc, ToSend, ToSendMax);
- resp_cc_len = ToSendMax;
-
- // Application Issuer Area
- CodeIClassTagAnswer(aia_data, sizeof(aia_data));
- memcpy(resp_aia, ToSend, ToSendMax);
- resp_aia_len = ToSendMax;
-
- //This is used for responding to READ-block commands or other data which is dynamically generated
- //First the 'trace'-data, not encoded for FPGA
- uint8_t *data_generic_trace = BigBuf_malloc((8 * 4) + 2);//8 bytes data + 2byte CRC is max tag answer
-
- //Then storage for the modulated data
- //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
- uint8_t *data_response = BigBuf_malloc(((8 * 4) + 2) * 2 + 2);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
- SpinDelay(100);
- StartCountSspClk();
-
- // To control where we are in the protocol
- uint32_t time_0 = GetCountSspClk();
- uint32_t t2r_stime = 0, t2r_etime = 0;
- uint32_t r2t_stime, r2t_etime = 0;
- LED_A_ON();
- bool buttonPressed = false;
- uint8_t cmd, options, block;
-
- while (!exitLoop) {
- WDT_HIT();
-
- //Signal tracer, can be used to get a trigger for an oscilloscope..
- LED_B_OFF();
- LED_C_OFF();
-
- r2t_stime = (GetCountSspClk() - time_0) << 4;
- if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) {
- buttonPressed = true;
- exitLoop = true;
- continue;
- }
- r2t_etime = ((GetCountSspClk() - time_0) << 4) - r2t_stime;
-
- // 330us normal wait, adjusted for our execution
-
- LED_C_ON(); //Signal tracer
-
- cmd = receivedCmd[0] & 0xF;
- options = (receivedCmd[0] >> 4) & 0xFF;
- block = receivedCmd[1];
-
- if (cmd == ICLASS_CMD_ACTALL) { // 0x0A
- // Reader in anticollission phase
- modulated_response = resp_sof;
- modulated_response_size = resp_sof_Len; //order = 1;
- trace_data = sof_data;
- trace_data_size = sizeof(sof_data);
- // adjusted for 330 + (160*num of slot)
- goto send;
- } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C
- if (len == 1) {
- // Reader asks for anticollission CSN
- modulated_response = resp_anticoll;
- modulated_response_size = resp_anticoll_len; //order = 2;
- trace_data = anticoll_data;
- trace_data_size = sizeof(anticoll_data);
- goto send;
- }
-
- if (len == 4) {
- // block0,1,2,5 is always readable.
- switch (block) {
- case 0: // csn (0c 00)
- modulated_response = resp_csn;
- modulated_response_size = resp_csn_len;
- trace_data = csn_data;
- trace_data_size = sizeof(csn_data);
- goto send;
- case 1: // configuration (0c 01)
- modulated_response = resp_conf;
- modulated_response_size = resp_conf_len;
- trace_data = conf_data;
- trace_data_size = sizeof(conf_data);
- goto send;
- case 2: // e-purse (0c 02)
- modulated_response = resp_cc;
- modulated_response_size = resp_cc_len;
- trace_data = card_challenge_data;
- trace_data_size = sizeof(card_challenge_data);
- // set epurse of sim2,4 attack
- if (reader_mac_buf != NULL) {
- memcpy(reader_mac_buf, card_challenge_data, 8);
- }
- goto send;
- case 5:// Application Issuer Area (0c 05)
- modulated_response = resp_aia;
- modulated_response_size = resp_aia_len;
- trace_data = aia_data;
- trace_data_size = sizeof(aia_data);
- goto send;
- default : {
- if (simulationMode == MODE_FULLSIM) { // 0x0C
- //Read block
- //Take the data...
- memcpy(data_generic_trace, emulator + (block << 3), 8);
- AddCrc(data_generic_trace, 8);
- trace_data = data_generic_trace;
- trace_data_size = 10;
- CodeIClassTagAnswer(trace_data, trace_data_size);
- memcpy(modulated_response, ToSend, ToSendMax);
- modulated_response_size = ToSendMax;
- goto send;
- }
- break;
- }
- }//swith
- }// if 4
- } else if (cmd == ICLASS_CMD_SELECT) { // 0x81
- // Reader selects anticollission CSN.
- // Tag sends the corresponding real CSN
- modulated_response = resp_csn;
- modulated_response_size = resp_csn_len; //order = 3;
- trace_data = csn_data;
- trace_data_size = sizeof(csn_data);
- goto send;
- } else if (cmd == ICLASS_CMD_READCHECK) { // 0x88
- // Read e-purse KD (88 02) KC (18 02)
- modulated_response = resp_cc;
- modulated_response_size = resp_cc_len; //order = 4;
- trace_data = card_challenge_data;
- trace_data_size = sizeof(card_challenge_data);
- LED_B_ON();
- goto send;
- } else if (cmd == ICLASS_CMD_CHECK) { // 0x05
- // Reader random and reader MAC!!!
- if (simulationMode == MODE_FULLSIM) {
- // NR, from reader, is in receivedCmd +1
- opt_doTagMAC_2(cipher_state, receivedCmd + 1, data_generic_trace, diversified_key);
-
- trace_data = data_generic_trace;
- trace_data_size = 4;
- CodeIClassTagAnswer(trace_data, trace_data_size);
- memcpy(data_response, ToSend, ToSendMax);
- modulated_response = data_response;
- modulated_response_size = ToSendMax;
- } else {
- // Not fullsim, we don't respond
- // We do not know what to answer, so lets keep quiet
- modulated_response = resp_sof;
- modulated_response_size = 0;
- trace_data = NULL;
- trace_data_size = 0;
-
- if (simulationMode == MODE_EXIT_AFTER_MAC) {
-
- if (DBGLEVEL == DBG_EXTENDED) {
- Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]);
- Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len,
- receivedCmd[0], receivedCmd[1], receivedCmd[2],
- receivedCmd[3], receivedCmd[4], receivedCmd[5],
- receivedCmd[6], receivedCmd[7], receivedCmd[8]);
- } else {
- Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]);
- }
- if (reader_mac_buf != NULL) {
- memcpy(reader_mac_buf + 8, receivedCmd + 1, 8);
- }
- exitLoop = true;
- }
- }
- goto send;
- } else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
- // Reader ends the session
- modulated_response = resp_sof;
- modulated_response_size = 0; //order = 0;
- trace_data = NULL;
- trace_data_size = 0;
- goto send;
- } else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
- //Read block
- //Take the data...
- memcpy(data_generic_trace, emulator + (block << 3), 8 * 4);
- AddCrc(data_generic_trace, 8 * 4);
- trace_data = data_generic_trace;
- trace_data_size = 34;
- CodeIClassTagAnswer(trace_data, trace_data_size);
- memcpy(modulated_response, ToSend, ToSendMax);
- modulated_response_size = ToSendMax;
- goto send;
- } else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_UPDATE) {
-
- //Probably the reader wants to update the nonce. Let's just ignore that for now.
- // OBS! If this is implemented, don't forget to regenerate the cipher_state
- //We're expected to respond with the data+crc, exactly what's already in the receivedcmd
- //receivedcmd is now UPDATE 1b | ADDRESS 1b| DATA 8b| Signature 4b or CRC 2b|
-
- //Take the data...
- memcpy(data_generic_trace, receivedCmd + 2, 8);
- AddCrc(data_generic_trace, 8);
- trace_data = data_generic_trace;
- trace_data_size = 10;
- CodeIClassTagAnswer(trace_data, trace_data_size);
-
- memcpy(data_response, ToSend, ToSendMax);
- modulated_response = data_response;
- modulated_response_size = ToSendMax;
-// response_delay = 4600 * 1.5; // tPROG 4-15ms
- goto send;
-// } else if(receivedCmd[0] == ICLASS_CMD_PAGESEL) { // 0x84
- //Pagesel
- //Pagesel enables to select a page in the selected chip memory and return its configuration block
- //Chips with a single page will not answer to this command
- // It appears we're fine ignoring this.
- //Otherwise, we should answer 8bytes (block) + 2bytes CRC
-// } else if(receivedCmd[0] == ICLASS_CMD_DETECT) { // 0x0F
- } else {
- //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44
- // Never seen this command before
- if (DBGLEVEL == DBG_EXTENDED)
- print_result("[-] Unhandled command received ", receivedCmd, len);
-
- // Do not respond
- modulated_response = resp_sof;
- modulated_response_size = 0; //order = 0;
- trace_data = NULL;
- trace_data_size = 0;
- }
-
-send:
- /**
- A legit tag has about 330us delay between reader EOT and tag SOF.
- **/
- if (modulated_response_size > 0) {
- t2r_stime = GetCountSspClkDelta(time_0) << 4;
- SendIClassAnswer(modulated_response, modulated_response_size, 0);
- t2r_etime = ((GetCountSspClk() - time_0) << 4) - t2r_stime;
- }
-
- LogTrace(receivedCmd, len, r2t_stime, r2t_etime, NULL, true);
-
- if (trace_data != NULL)
- LogTrace(trace_data, trace_data_size, t2r_stime, t2r_etime, NULL, false);
- }
-
- LEDsoff();
-
- if (buttonPressed)
- DbpString("[+] button pressed");
-
- return buttonPressed;
-}
-
-/**
- * @brief sends our simulated tag answer
- * @param resp
- * @param respLen
- * @param delay
- */
-static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) {
- int i = 0;
- volatile uint8_t b;
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
-
- AT91C_BASE_SSC->SSC_THR = 0x00;
-
- uint16_t checked = 0;
- for (;;) {
-
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) return 0;
- checked = 0;
- }
- ++checked;
-
- // Prevent rx holding register from overflowing
- if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {
- b = AT91C_BASE_SSC->SSC_RHR;
- (void) b;
- }
-
- // Put byte into tx holding register as soon as it is ready
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- b = 0x00;
- if (i < respLen) {
- b = resp[i];
- //Hack
- //b = 0xAC;
- }
- i++;
- AT91C_BASE_SSC->SSC_THR = b;
- }
-// if (i > respLen + 4) break;
- if (i > respLen + 1) break;
- }
- return 0;
-}
-
-/// THE READER CODE
-
-//-----------------------------------------------------------------------------
-// Transmit the command (to the tag) that was placed in ToSend[].
-//-----------------------------------------------------------------------------
-static void TransmitIClassCommand(const uint8_t *cmd, int len, int *wait) {
-
- int c = 0;
- bool firstpart = true;
- uint8_t sendbyte;
-
- time_rdr = 0;
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
-
- AT91C_BASE_SSC->SSC_THR = 0x00;
-
- // make sure we timeout previous comms.
- if (*wait)
- SpinDelayUs(*wait);
-
- for (;;) {
-
- WDT_HIT();
-
- // Put byte into tx holding register as soon as it is ready
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-
- // DOUBLE THE SAMPLES!
- if (firstpart) {
- sendbyte = (cmd[c] & 0xf0) | (cmd[c] >> 4);
- } else {
- sendbyte = (cmd[c] & 0x0f) | (cmd[c] << 4);
- c++;
- }
-
- if (sendbyte == 0xff)
- sendbyte = 0xfe;
-
- AT91C_BASE_SSC->SSC_THR = sendbyte;
- firstpart = !firstpart;
-
- if (c >= len) break;
- }
- }
-
- time_rdr = GetCountSspClk();
-}
-
-//-----------------------------------------------------------------------------
-// Prepare iClass reader command to send to FPGA
-//-----------------------------------------------------------------------------
-void CodeIClassCommand(const uint8_t *cmd, int len) {
- int i, j, k;
-
- ToSendReset();
-
- // (SOC) Start of Communication: 1 out of 4
- ToSend[++ToSendMax] = 0xf0;
- ToSend[++ToSendMax] = 0x00;
- ToSend[++ToSendMax] = 0x0f;
- ToSend[++ToSendMax] = 0x00;
-
- // Modulate the bytes
- for (i = 0; i < len; i++) {
- uint8_t b = cmd[i];
- for (j = 0; j < 4; j++) {
- for (k = 0; k < 4; k++) {
-
- if (k == (b & 3))
- ToSend[++ToSendMax] = 0x0f;
- else
- ToSend[++ToSendMax] = 0x00;
- }
- b >>= 2;
- }
- }
-
- // (EOC) End of Communication
- ToSend[++ToSendMax] = 0x00;
- ToSend[++ToSendMax] = 0x00;
- ToSend[++ToSendMax] = 0xf0;
- ToSend[++ToSendMax] = 0x00;
-
- // Convert from last character reference to length
- ToSendMax++;
-}
-
-void ReaderTransmitIClass_ext(uint8_t *frame, int len, int wait) {
-
- // This is tied to other size changes
- CodeIClassCommand(frame, len);
-
- // Select the card
- TransmitIClassCommand(ToSend, ToSendMax, &wait);
- LED_A_ON();
-
- LogTrace(frame, len, rsamples, rsamples, NULL, true);
-}
-void ReaderTransmitIClass(uint8_t *frame, int len) {
- ReaderTransmitIClass_ext(frame, len, 330);
-}
-
-//-----------------------------------------------------------------------------
-// Wait a certain time for tag response
-// If a response is captured return TRUE
-// If it takes too long return FALSE
-//-----------------------------------------------------------------------------
-static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *wait) {
- // buffer needs to be 512 bytes
- // maxLen is not used...
- bool skip = false;
-
- LED_D_ON();
- // Set FPGA mode to "reader listen mode", no modulation (listen
- // only, since we are receiving, not transmitting).
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
-
- // Setup UART/DEMOD to receive
- DemodIcInit(receivedResponse);
-
- SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments.
-
- // clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint16_t checked = 0;
-
- uint32_t card_start = GetCountSspClk();
- for (;;) {
- WDT_HIT();
-
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) return false;
- checked = 0;
- }
- ++checked;
-
- // Wait for byte be become available in rx holding register
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-
- b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- skip = !skip;
- if (skip) continue;
-
- if (ManchesterDecoding_iclass(b & 0x0f)) {
- time_response = GetCountSspClk() - card_start;
- return true;
- } else if (GetCountSspClkDelta(card_start) > timeout && Demod.state == DEMOD_IC_UNSYNCD) {
- return false;
- }
- }
- }
- return false;
-}
-
-int ReaderReceiveIClass(uint8_t *receivedAnswer) {
-
- if (GetIClassAnswer(receivedAnswer, 0, NULL) == false)
- return 0;
-
- LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false);
- return Demod.len;
-}
-
-void setupIclassReader() {
-
- LEDsoff();
-
- // Start from off (no field generated)
- // Signal field is off with the appropriate LED
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- FpgaSetupSsc();
-
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- clear_trace();
- set_tracing(true);
-
- // Now give it time to spin up.
- // Signal field is on with the appropriate LED
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
- SpinDelay(500);
-
- StartCountSspClk();
-
- LED_A_ON();
-}
-
-bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, int8_t retries) {
- while (retries-- > 0) {
-
- ReaderTransmitIClass(command, cmdsize);
-
- //iceman - if received size is bigger than expected, we smash the stack here
- // since its called with fixed sized arrays
-
- // update/write command takes 4ms to 15ms before responding
- int old_wait = g_wait;
- if ((command[0] & 0xF) == ICLASS_CMD_UPDATE)
- g_wait = 3900;
-
- uint8_t got_n = ReaderReceiveIClass(resp);
-
- g_wait = old_wait;
-
- // 0xBB is the internal debug separator byte..
- if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) {
- //try again
-// SpinDelayUs(360);
- continue;
- }
-
- if (got_n == expected_size)
- return true;
- }
- return false;
-}
-
-/**
- * @brief Talks to an iclass tag, sends the commands to get CSN and CC.
- * @param card_data where the CSN and CC are stored for return
- * @return 0 = fail
- * 1 = Got CSN
- * 2 = Got CSN and CC
- */
-uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) {
-
- // act_all...
- static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
- static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
- static uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
-
- // Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) willbe used
- // bit 7: parity.
-
- if (use_credit_key)
- readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
-
- uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
-
- // Send act_all ( 330 timeout + 160 timeslot);
- ReaderTransmitIClass_ext(act_all, 1, 330 + 180);
-
- // Card present?
- if (ReaderReceiveIClass(resp) == 0)
- return 0;
-
- //Send Identify
- ReaderTransmitIClass(identify, 1);
-
- //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC
- if (ReaderReceiveIClass(resp) != 10)
- return 0;
-
- //Copy the Anti-collision CSN to our select-packet
- memcpy(&select[1], resp, 8);
-
- //Select the card
- ReaderTransmitIClass(select, sizeof(select));
-
- //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC
- if (ReaderReceiveIClass(resp) != 10)
- return 0;
-
- // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
- // ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
- // if (ReaderReceiveIClass(resp) == 8) {
- // //Save CC (e-purse) in response data
- // memcpy(card_data+8, resp, 8);
- // read_status++;
- // }
-
- //Success - level 1, we got CSN
- //Save CSN in response data
- memcpy(card_data, resp, 8);
-
- bool isBlk_2 = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3);
-
- //Flag that we got to at least stage 1, read CSN
- if (isBlk_2 == false) {
- return 1;
- }
-
- //Save CC (e-purse) in response data
- memcpy(card_data + 8, resp, 8);
-
- // we got all data;
- return 2;
-}
-uint8_t handshakeIclassTag(uint8_t *card_data) {
- return handshakeIclassTag_ext(card_data, false);
-}
-
-// Reader iClass Anticollission
-// turn off afterwards
-void ReaderIClass(uint8_t arg0) {
-
- uint8_t card_data[6 * 8] = {0};
- uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t resp[ICLASS_BUFFER_SIZE];
-
- memset(card_data, 0xFF, sizeof(card_data));
- memset(resp, 0xFF, sizeof(resp));
-
- //Read conf block CRC(0x01) => 0xfa 0x22
- uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22};
-
- //Read App Issuer Area block CRC(0x05) => 0xde 0x64
- uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
-
- uint16_t tryCnt = 0;
-
- bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully
- bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag
- bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key
- bool flagReadConfig = arg0 & FLAG_ICLASS_READER_CONF; // flag to read block1, configuration
- bool flagReadCC = arg0 & FLAG_ICLASS_READER_CC; // flag to read block2, e-purse
- bool flagReadAIA = arg0 & FLAG_ICLASS_READER_AIA; // flag to read block5, application issuer area
-
- setupIclassReader();
-
- uint16_t checked = 0;
- bool userCancelled = BUTTON_PRESS() || data_available();
- while (!userCancelled) {
-
- WDT_HIT();
-
- // if only looking for one card try 2 times if we missed it the first time
- if (try_once && tryCnt > 10) {
- if (DBGLEVEL > 1) DbpString("Failed to find a tag");
- break;
- }
-
- tryCnt++;
- uint8_t result_status = 0;
-
- int read_status = handshakeIclassTag_ext(card_data, use_credit_key);
-
- if (read_status == 0) continue;
- if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
- if (read_status == 2) result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC;
-
- // handshakeIclass returns CSN|CC, but the actual block
- // layout is CSN|CONFIG|CC, so here we reorder the data,
- // moving CC forward 8 bytes
- memcpy(card_data + 16, card_data + 8, 8);
-
- //Read block 1, config
- if (flagReadConfig) {
- if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, 10, 5)) {
- result_status |= FLAG_ICLASS_READER_CONF;
- memcpy(card_data + 8, resp, 8);
- } else {
- if (DBGLEVEL > 1) DbpString("Failed to dump config block");
- }
- }
-
- //Read block 5, AIA
- if (flagReadAIA) {
- if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, 10, 5)) {
- result_status |= FLAG_ICLASS_READER_AIA;
- memcpy(card_data + (8 * 5), resp, 8);
- } else {
- if (DBGLEVEL > 1) DbpString("Failed to dump AA block");
- }
- }
-
- // 0 : CSN
- // 1 : Configuration
- // 2 : e-purse
- // 3 : kd / debit / aa2 (write-only)
- // 4 : kc / credit / aa1 (write-only)
- // 5 : AIA, Application issuer area
- //
- //Then we can 'ship' back the 6 * 8 bytes of data,
- // with 0xFF:s in block 3 and 4.
-
- LED_B_ON();
- //Send back to client, but don't bother if we already sent this -
- // only useful if looping in arm (not try_once && not abort_after_read)
- if (memcmp(last_csn, card_data, 8) != 0) {
- // If caller requires that we get Conf, CC, AA, continue until we got it
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("STATUS %02X | CSN %c | CONF %c | CC %c | AIA %c | ONCE %c | 1TRY %c",
- result_status,
- (result_status & FLAG_ICLASS_READER_CSN) ? 'Y' : 'N',
- (result_status & FLAG_ICLASS_READER_CONF) ? 'Y' : 'N',
- (result_status & FLAG_ICLASS_READER_CC) ? 'Y' : 'N',
- (result_status & FLAG_ICLASS_READER_AIA) ? 'Y' : 'N'
- );
- Dbprintf(" aar %c | to %c, | uc %c | frc %c | fra %c | cc %c",
- abort_after_read ? 'Y' : 'N',
- try_once ? 'Y' : 'N',
- use_credit_key ? 'Y' : 'N',
- flagReadConfig ? 'Y' : 'N',
- flagReadAIA ? 'Y' : 'N',
- flagReadCC ? 'Y' : 'N'
- );
- }
-
- bool send = (result_status & FLAG_ICLASS_READER_CSN);
- if (flagReadCC)
- send |= (result_status & FLAG_ICLASS_READER_CC);
- if (flagReadAIA)
- send |= (result_status & FLAG_ICLASS_READER_AIA);
- if (flagReadConfig)
- send |= (result_status & FLAG_ICLASS_READER_CONF);
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SEND %c", send ? 'y' : 'n');
-
- if (send) {
- reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
- if (abort_after_read) {
- LED_B_OFF();
- return;
- }
- //Save that we already sent this....
- memcpy(last_csn, card_data, 8);
- }
- }
- LED_B_OFF();
-
- if (checked == 1000) {
- userCancelled = BUTTON_PRESS() || data_available();
- checked = 0;
- }
- ++checked;
- }
-
- if (userCancelled) {
- reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
- switch_off();
- } else {
- reply_mix(CMD_ACK, 0, 0, 0, card_data, 0);
- }
-}
-
-// turn off afterwards
-void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) {
-
- uint8_t cardsize = 0;
- uint8_t mem = 0;
- uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
- uint8_t card_data[PM3_CMD_DATA_SIZE] = {0};
- uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
-
- static struct memory_t {
- int k16;
- int book;
- int k2;
- int lockauth;
- int keyaccess;
- } memory;
-
- setupIclassReader();
-
- while (!BUTTON_PRESS()) {
-
- WDT_HIT();
-
- uint8_t read_status = handshakeIclassTag(card_data);
- if (read_status < 2) continue;
-
- //for now replay captured auth (as cc not updated)
- memcpy(check + 5, mac, 4);
-
- if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) {
- DbpString("Error: Authentication Fail!");
- continue;
- }
-
- //first get configuration block (block 1)
- read[1] = 1;
- AddCrc(read + 1, 1);
-
- if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 5)) {
- DbpString("Dump config (block 1) failed");
- continue;
- }
-
- mem = resp[5];
- memory.k16 = (mem & 0x80);
- memory.book = (mem & 0x20);
- memory.k2 = (mem & 0x8);
- memory.lockauth = (mem & 0x2);
- memory.keyaccess = (mem & 0x1);
-
- cardsize = memory.k16 ? 255 : 32;
-
- WDT_HIT();
- //Set card_data to all zeroes, we'll fill it with data
- memset(card_data, 0x0, PM3_CMD_DATA_SIZE);
- uint8_t failedRead = 0;
- uint32_t stored_data_length = 0;
-
- //then loop around remaining blocks
- for (uint16_t block = 0; block < cardsize; block++) {
-
- read[1] = block;
- AddCrc(read + 1, 1);
-
- if (sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 5)) {
- Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
- block, resp[0], resp[1], resp[2],
- resp[3], resp[4], resp[5],
- resp[6], resp[7]
- );
-
- //Fill up the buffer
- memcpy(card_data + stored_data_length, resp, 8);
- stored_data_length += 8;
- if (stored_data_length + 8 > PM3_CMD_DATA_SIZE) {
- //Time to send this off and start afresh
- reply_old(CMD_ACK,
- stored_data_length,//data length
- failedRead,//Failed blocks?
- 0,//Not used ATM
- card_data,
- stored_data_length
- );
- //reset
- stored_data_length = 0;
- failedRead = 0;
- }
- } else {
- failedRead = 1;
- stored_data_length += 8;//Otherwise, data becomes misaligned
- Dbprintf("Failed to dump block %d", block);
- }
- }
-
- //Send off any remaining data
- if (stored_data_length > 0) {
- reply_old(CMD_ACK,
- stored_data_length,//data length
- failedRead,//Failed blocks?
- 0,//Not used ATM
- card_data,
- stored_data_length
- );
- }
- //If we got here, let's break
- break;
- }
- //Signal end of transmission
- reply_old(CMD_ACK,
- 0,//data length
- 0,//Failed blocks?
- 0,//Not used ATM
- card_data,
- 0
- );
- switch_off();
-}
-
-// not used. ?!? ( CMD_HF_ICLASS_READCHECK)
-// turn off afterwards
-void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) {
- uint8_t readcheck[] = { keytype, blockno };
- uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0};
- size_t isOK = 0;
- isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6);
- reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
- switch_off();
-}
-
-// used with function select_and_auth (cmdhficlass.c)
-// which needs to authenticate before doing more things like read/write
-void iClass_Authentication(uint8_t *mac) {
- uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t resp[ICLASS_BUFFER_SIZE];
-
- // copy MAC to check command (readersignature)
- check[5] = mac[0];
- check[6] = mac[1];
- check[7] = mac[2];
- check[8] = mac[3];
- //memcpy(check+5, mac, 4);
-
- // 6 retries
- uint8_t isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6);
- reply_ng(CMD_HF_ICLASS_AUTH, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
-}
-
-typedef struct iclass_premac {
- uint8_t mac[4];
-} iclass_premac_t;
-
-/* this function works on the following assumptions.
-* - one select first, to get CSN / CC (e-purse)
-* - calculate before diversified keys and precalc mac based on CSN/KEY.
-* - data in contains of diversified keys, mac
-* - key loop only test one type of authtication key. Ie two calls needed
-* to cover debit and credit key. (AA1/AA2)
-*/
-void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
- uint8_t i = 0, isOK = 0;
- uint8_t lastChunk = ((arg0 >> 8) & 0xFF);
- bool use_credit_key = ((arg0 >> 16) & 0xFF);
- uint8_t keyCount = arg1 & 0xFF;
- uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t resp[ICLASS_BUFFER_SIZE];
- uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
-
- if (use_credit_key)
- readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
-
- // select card / e-purse
- uint8_t card_data[6 * 8] = {0};
-
- iclass_premac_t *keys = (iclass_premac_t *)datain;
-
- LED_A_ON();
-
- switch_off();
- SpinDelay(20);
-
- setupIclassReader();
-
- uint16_t checked = 0;
- int read_status = 0;
- uint8_t startup_limit = 10;
- while (read_status != 2) {
-
- if (checked == 1000) {
- if (BUTTON_PRESS() || !data_available()) goto out;
- checked = 0;
- }
- ++checked;
-
- read_status = handshakeIclassTag_ext(card_data, use_credit_key);
- if (startup_limit-- == 0) {
- Dbprintf("[-] Handshake status | %d (fail 10)", read_status);
- isOK = 99;
- goto out;
- }
- };
- // since handshakeIclassTag_ext call sends s readcheck, we start with sending first response.
-
- checked = 0;
-
- // Keychunk loop
- for (i = 0; i < keyCount; i++) {
-
- // Allow button press / usb cmd to interrupt device
- if (checked == 1000) {
- if (BUTTON_PRESS() || !data_available()) goto out;
- checked = 0;
- }
- ++checked;
-
- WDT_HIT();
- LED_B_ON();
-
- // copy MAC to check command (readersignature)
- check[5] = keys[i].mac[0];
- check[6] = keys[i].mac[1];
- check[7] = keys[i].mac[2];
- check[8] = keys[i].mac[3];
-
- // expect 4bytes, 3 retries times..
- isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 3);
- if (isOK)
- goto out;
-
- // Auth Sequence MUST begin with reading e-purse. (block2)
- // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
- ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
-
- LED_B_OFF();
- }
-
-out:
- // send keyindex.
- reply_mix(CMD_ACK, isOK, i, 0, 0, 0);
-
- if (isOK >= 1 || lastChunk) {
- switch_off();
- LED_A_OFF();
- }
-
- LED_B_OFF();
- LED_C_OFF();
-}
-
-// Tries to read block.
-// retries 10times.
-bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) {
- uint8_t resp[10];
- uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
- AddCrc(cmd + 1, 1);
- // expect size 10, retry 5times
- bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5);
- memcpy(data, resp, len);
- return isOK;
-}
-
-// turn off afterwards
-// readblock 8 + 2. only want 8.
-void iClass_ReadBlk(uint8_t blockno) {
- struct p {
- bool isOK;
- uint8_t blockdata[8];
- } PACKED result;
-
- result.isOK = iClass_ReadBlock(blockno, result.blockdata, sizeof(result.blockdata));
- switch_off();
- reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&result, sizeof(result));
-}
-
-// turn off afterwards
-void iClass_Dump(uint8_t blockno, uint8_t numblks) {
- uint8_t blockdata[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- bool isOK = false;
- uint8_t blkCnt = 0;
-
- BigBuf_free();
- uint8_t *dataout = BigBuf_malloc(255 * 8);
- if (dataout == NULL) {
- DbpString("[!] fail to allocate memory");
- OnError(1);
- return;
- }
- // fill mem with 0xFF
- memset(dataout, 0xFF, 255 * 8);
-
- for (; blkCnt < numblks; blkCnt++) {
- isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata));
-
- // 0xBB is the internal debug separator byte..
- if (!isOK || (blockdata[0] == 0xBB || blockdata[7] == 0xBB || blockdata[2] == 0xBB)) { //try again
- isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata));
- if (!isOK) {
- Dbprintf("[!] block %02X failed to read", blkCnt + blockno);
- break;
- }
- }
- memcpy(dataout + (blkCnt * 8), blockdata, 8);
- }
-
- switch_off();
- //return pointer to dump memory in arg3
- reply_mix(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0);
- BigBuf_free();
-}
-
-bool iClass_WriteBlock_ext(uint8_t blockno, uint8_t *data) {
- uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t write[] = { 0x80 | ICLASS_CMD_UPDATE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- memcpy(write + 2, data, 12); // data + mac
- AddCrc(write + 1, 13);
- return sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5);
-}
-
-// turn off afterwards
-void iClass_WriteBlock(uint8_t blockno, uint8_t *data) {
- uint8_t isOK = iClass_WriteBlock_ext(blockno, data);
- switch_off();
- reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
-}
-
-// turn off afterwards
-void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
- int i, written = 0;
- int total_block = (endblock - startblock) + 1;
- for (i = 0; i < total_block; i++) {
- // block number
- if (iClass_WriteBlock_ext(startblock + i, data + (i * 12))) {
- Dbprintf("Write block [%02x] successful", startblock + i);
- written++;
- } else {
- Dbprintf("Write block [%02x] failed", startblock + i);
- }
- }
-
- switch_off();
-
- uint8_t isOK = 0;
- if (written == total_block)
- isOK = 1;
-
- reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iclass.h b/pm3rdv4rrg/src/main/cpp/armsrc/iclass.h
deleted file mode 100644
index a9edbdfe..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iclass.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __ICLASS_H
-#define __ICLASS_H
-
-#include "common.h"
-
-void RAMFUNC SniffIClass(void);
-void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void ReaderIClass(uint8_t arg0);
-void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
-void iClass_Authentication(uint8_t *mac);
-void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
-void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
-void iClass_ReadBlk(uint8_t blockno);
-bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
-void iClass_Dump(uint8_t blockno, uint8_t numblks);
-void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
-void iClass_ReadCheck(uint8_t blockno, uint8_t keytype);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443a.c b/pm3rdv4rrg/src/main/cpp/armsrc/iso14443a.c
deleted file mode 100644
index f37f2419..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443a.c
+++ /dev/null
@@ -1,3292 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011, 2012
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443 type A.
-//-----------------------------------------------------------------------------
-#include "iso14443a.h"
-
-#include "string.h"
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "appmain.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "parity.h"
-#include "mifareutil.h"
-#include "commonutil.h"
-#include "crc16.h"
-#include "protocols.h"
-
-#define MAX_ISO14A_TIMEOUT 524288
-static uint32_t iso14a_timeout;
-// if iso14443a not active - transmit/read dont try to execute
-static bool hf_field_active = false;
-
-uint8_t colpos = 0;
-int rsamples = 0;
-uint8_t trigger = 0;
-// the block number for the ISO14443-4 PCB
-static uint8_t iso14_pcb_blocknum = 0;
-
-//
-// ISO14443 timing:
-//
-// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56MHz) cycles
-#define REQUEST_GUARD_TIME (7000/16 + 1)
-// minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles
-#define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1)
-// bool LastCommandWasRequest = false;
-
-//
-// Total delays including SSC-Transfers between ARM and FPGA. These are in carrier clock cycles (1/13,56MHz)
-//
-// When the PM acts as reader and is receiving tag data, it takes
-// 3 ticks delay in the AD converter
-// 16 ticks until the modulation detector completes and sets curbit
-// 8 ticks until bit_to_arm is assigned from curbit
-// 8*16 ticks for the transfer from FPGA to ARM
-// 4*16 ticks until we measure the time
-// - 8*16 ticks because we measure the time of the previous transfer
-#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16)
-
-// When the PM acts as a reader and is sending, it takes
-// 4*16 ticks until we can write data to the sending hold register
-// 8*16 ticks until the SHR is transferred to the Sending Shift Register
-// 8 ticks until the first transfer starts
-// 8 ticks later the FPGA samples the data
-// 1 tick to assign mod_sig_coil
-#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1)
-
-// The FPGA will report its internal sending delay in
-uint16_t FpgaSendQueueDelay;
-// the 5 first bits are the number of bits buffered in mod_sig_buf
-// the last three bits are the remaining ticks/2 after the mod_sig_buf shift
-#define DELAY_FPGA_QUEUE (FpgaSendQueueDelay<<1)
-
-// When the PM acts as tag and is sending, it takes
-// 4*16 + 8 ticks until we can write data to the sending hold register
-// 8*16 ticks until the SHR is transferred to the Sending Shift Register
-// 8 ticks later the FPGA samples the first data
-// + 16 ticks until assigned to mod_sig
-// + 1 tick to assign mod_sig_coil
-// + a varying number of ticks in the FPGA Delay Queue (mod_sig_buf)
-#define DELAY_ARM2AIR_AS_TAG (4*16 + 8 + 8*16 + 8 + 16 + 1 + DELAY_FPGA_QUEUE)
-
-// When the PM acts as sniffer and is receiving tag data, it takes
-// 3 ticks A/D conversion
-// 14 ticks to complete the modulation detection
-// 8 ticks (on average) until the result is stored in to_arm
-// + the delays in transferring data - which is the same for
-// sniffing reader and tag data and therefore not relevant
-#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
-
-// When the PM acts as sniffer and is receiving reader data, it takes
-// 2 ticks delay in analogue RF receiver (for the falling edge of the
-// start bit, which marks the start of the communication)
-// 3 ticks A/D conversion
-// 8 ticks on average until the data is stored in to_arm.
-// + the delays in transferring data - which is the same for
-// sniffing reader and tag data and therefore not relevant
-#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8)
-
-//variables used for timing purposes:
-//these are in ssp_clk cycles:
-static uint32_t NextTransferTime;
-static uint32_t LastTimeProxToAirStart;
-static uint32_t LastProxToAirDuration;
-
-// CARD TO READER - manchester
-// Sequence D: 11110000 modulation with subcarrier during first half
-// Sequence E: 00001111 modulation with subcarrier during second half
-// Sequence F: 00000000 no modulation with subcarrier
-// Sequence COLL: 11111111 load modulation over the full bitlength.
-// Tricks the reader to think that multiple cards answer (at least one card with 1 and at least one card with 0).
-// READER TO CARD - miller
-// Sequence X: 00001100 drop after half a period
-// Sequence Y: 00000000 no drop
-// Sequence Z: 11000000 drop at start
-#define SEC_D 0xf0
-#define SEC_E 0x0f
-#define SEC_F 0x00
-#define SEC_COLL 0xff
-#define SEC_X 0x0c
-#define SEC_Y 0x00
-#define SEC_Z 0xc0
-
-void iso14a_set_trigger(bool enable) {
- trigger = enable;
-}
-
-void iso14a_set_timeout(uint32_t timeout) {
- iso14a_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) + 2;
-}
-
-uint32_t iso14a_get_timeout(void) {
- return iso14a_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2;
-}
-
-//-----------------------------------------------------------------------------
-// Generate the parity value for a byte sequence
-//-----------------------------------------------------------------------------
-void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par) {
- uint16_t paritybit_cnt = 0;
- uint16_t paritybyte_cnt = 0;
- uint8_t parityBits = 0;
-
- for (uint16_t i = 0; i < len; i++) {
- // Generate the parity bits
- parityBits |= ((oddparity8(pbtCmd[i])) << (7 - paritybit_cnt));
- if (paritybit_cnt == 7) {
- par[paritybyte_cnt] = parityBits; // save 8 Bits parity
- parityBits = 0; // and advance to next Parity Byte
- paritybyte_cnt++;
- paritybit_cnt = 0;
- } else {
- paritybit_cnt++;
- }
- }
-
- // save remaining parity bits
- par[paritybyte_cnt] = parityBits;
-}
-
-
-//=============================================================================
-// ISO 14443 Type A - Miller decoder
-//=============================================================================
-// Basics:
-// This decoder is used when the PM3 acts as a tag.
-// The reader will generate "pauses" by temporarily switching of the field.
-// At the PM3 antenna we will therefore measure a modulated antenna voltage.
-// The FPGA does a comparison with a threshold and would deliver e.g.:
-// ........ 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 .......
-// The Miller decoder needs to identify the following sequences:
-// 2 (or 3) ticks pause followed by 6 (or 5) ticks unmodulated: pause at beginning - Sequence Z ("start of communication" or a "0")
-// 8 ticks without a modulation: no pause - Sequence Y (a "0" or "end of communication" or "no information")
-// 4 ticks unmodulated followed by 2 (or 3) ticks pause: pause in second half - Sequence X (a "1")
-// Note 1: the bitstream may start at any time. We therefore need to sync.
-// Note 2: the interpretation of Sequence Y and Z depends on the preceding sequence.
-//-----------------------------------------------------------------------------
-static tUart14a Uart;
-
-// Lookup-Table to decide if 4 raw bits are a modulation.
-// We accept the following:
-// 0001 - a 3 tick wide pause
-// 0011 - a 2 tick wide pause, or a three tick wide pause shifted left
-// 0111 - a 2 tick wide pause shifted left
-// 1001 - a 2 tick wide pause shifted right
-const bool Mod_Miller_LUT[] = {
- false, true, false, true, false, false, false, true,
- false, true, false, false, false, false, false, false
-};
-#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
-#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
-
-tUart14a *GetUart14a() {
- return &Uart;
-}
-
-void Uart14aReset(void) {
- Uart.state = STATE_14A_UNSYNCD;
- Uart.bitCount = 0;
- Uart.len = 0; // number of decoded data bytes
- Uart.parityLen = 0; // number of decoded parity bytes
- Uart.shiftReg = 0; // shiftreg to hold decoded data bits
- Uart.parityBits = 0; // holds 8 parity bits
- Uart.startTime = 0;
- Uart.endTime = 0;
- Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits
- Uart.posCnt = 0;
- Uart.syncBit = 9999;
-}
-
-void Uart14aInit(uint8_t *data, uint8_t *par) {
- Uart.output = data;
- Uart.parity = par;
- Uart14aReset();
-}
-
-// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
-RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
- Uart.fourBits = (Uart.fourBits << 8) | bit;
-
- if (Uart.state == STATE_14A_UNSYNCD) { // not yet synced
- Uart.syncBit = 9999; // not set
-
- // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication")
- // 11111111 8 ticks unmodulation Sequence Y (a "0" or "end of communication" or "no information")
- // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause Sequence X (a "1")
-
- // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
- // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
- // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern
- // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
-#define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000
-#define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000
- if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
- else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
-
- if (Uart.syncBit != 9999) { // found a sync bit
- Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
- Uart.startTime -= Uart.syncBit;
- Uart.endTime = Uart.startTime;
- Uart.state = STATE_14A_START_OF_COMMUNICATION;
- }
- } else {
-
- if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
- if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
- Uart14aReset();
- } else { // Modulation in first half = Sequence Z = logic "0"
- if (Uart.state == STATE_14A_MILLER_X) { // error - must not follow after X
- Uart14aReset();
- } else {
- Uart.bitCount++;
- Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
- Uart.state = STATE_14A_MILLER_Z;
- Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6;
- if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
- Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
- Uart.parityBits <<= 1; // make room for the parity bit
- Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
- Uart.bitCount = 0;
- Uart.shiftReg = 0;
- if ((Uart.len & 0x0007) == 0) { // every 8 data bytes
- Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
- Uart.parityBits = 0;
- }
- }
- }
- }
- } else {
- if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
- Uart.bitCount++;
- Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
- Uart.state = STATE_14A_MILLER_X;
- Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2;
- if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
- Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
- Uart.parityBits <<= 1; // make room for the new parity bit
- Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
- Uart.bitCount = 0;
- Uart.shiftReg = 0;
- if ((Uart.len & 0x0007) == 0) { // every 8 data bytes
- Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
- Uart.parityBits = 0;
- }
- }
- } else { // no modulation in both halves - Sequence Y
- if (Uart.state == STATE_14A_MILLER_Z || Uart.state == STATE_14A_MILLER_Y) { // Y after logic "0" - End of Communication
- Uart.state = STATE_14A_UNSYNCD;
- Uart.bitCount--; // last "0" was part of EOC sequence
- Uart.shiftReg <<= 1; // drop it
- if (Uart.bitCount > 0) { // if we decoded some bits
- Uart.shiftReg >>= (9 - Uart.bitCount); // right align them
- Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output
- Uart.parityBits <<= 1; // add a (void) parity bit
- Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align parity bits
- Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it
- return true;
- } else if (Uart.len & 0x0007) { // there are some parity bits to store
- Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align remaining parity bits
- Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them
- }
- if (Uart.len) {
- return true; // we are finished with decoding the raw data sequence
- } else {
- Uart14aReset(); // Nothing received - start over
- }
- }
- if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
- Uart14aReset();
- } else { // a logic "0"
- Uart.bitCount++;
- Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
- Uart.state = STATE_14A_MILLER_Y;
- if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
- Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
- Uart.parityBits <<= 1; // make room for the parity bit
- Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
- Uart.bitCount = 0;
- Uart.shiftReg = 0;
- if ((Uart.len & 0x0007) == 0) { // every 8 data bytes
- Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
- Uart.parityBits = 0;
- }
- }
- }
- }
- }
- }
- return false; // not finished yet, need more data
-}
-
-//=============================================================================
-// ISO 14443 Type A - Manchester decoder
-//=============================================================================
-// Basics:
-// This decoder is used when the PM3 acts as a reader.
-// The tag will modulate the reader field by asserting different loads to it. As a consequence, the voltage
-// at the reader antenna will be modulated as well. The FPGA detects the modulation for us and would deliver e.g. the following:
-// ........ 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .......
-// The Manchester decoder needs to identify the following sequences:
-// 4 ticks modulated followed by 4 ticks unmodulated: Sequence D = 1 (also used as "start of communication")
-// 4 ticks unmodulated followed by 4 ticks modulated: Sequence E = 0
-// 8 ticks unmodulated: Sequence F = end of communication
-// 8 ticks modulated: A collision. Save the collision position and treat as Sequence D
-// Note 1: the bitstream may start at any time. We therefore need to sync.
-// Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only)
-tDemod14a Demod;
-
-// Lookup-Table to decide if 4 raw bits are a modulation.
-// We accept three or four "1" in any position
-const bool Mod_Manchester_LUT[] = {
- false, false, false, false, false, false, false, true,
- false, false, false, true, false, true, true, true
-};
-
-#define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4])
-#define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)])
-
-tDemod14a *GetDemod14a() {
- return &Demod;
-}
-void Demod14aReset(void) {
- Demod.state = DEMOD_14A_UNSYNCD;
- Demod.len = 0; // number of decoded data bytes
- Demod.parityLen = 0;
- Demod.shiftReg = 0; // shiftreg to hold decoded data bits
- Demod.parityBits = 0; //
- Demod.collisionPos = 0; // Position of collision bit
- Demod.twoBits = 0xFFFF; // buffer for 2 Bits
- Demod.highCnt = 0;
- Demod.startTime = 0;
- Demod.endTime = 0;
- Demod.bitCount = 0;
- Demod.syncBit = 0xFFFF;
- Demod.samples = 0;
-}
-
-void Demod14aInit(uint8_t *data, uint8_t *par) {
- Demod.output = data;
- Demod.parity = par;
- Demod14aReset();
-}
-
-// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
-RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) {
- Demod.twoBits = (Demod.twoBits << 8) | bit;
-
- if (Demod.state == DEMOD_14A_UNSYNCD) {
-
- if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
- if (Demod.twoBits == 0x0000) {
- Demod.highCnt++;
- } else {
- Demod.highCnt = 0;
- }
- } else {
- Demod.syncBit = 0xFFFF; // not set
- if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7;
- else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6;
- else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5;
- else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4;
- else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3;
- else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2;
- else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1;
- else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0;
- if (Demod.syncBit != 0xFFFF) {
- Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
- Demod.startTime -= Demod.syncBit;
- Demod.bitCount = offset; // number of decoded data bits
- Demod.state = DEMOD_14A_MANCHESTER_DATA;
- }
- }
- } else {
-
- if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half
- if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision
- if (!Demod.collisionPos) {
- Demod.collisionPos = (Demod.len << 3) + Demod.bitCount;
- }
- } // modulation in first half only - Sequence D = 1
- Demod.bitCount++;
- Demod.shiftReg = (Demod.shiftReg >> 1) | 0x100; // in both cases, add a 1 to the shiftreg
- if (Demod.bitCount == 9) { // if we decoded a full byte (including parity)
- Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
- Demod.parityBits <<= 1; // make room for the parity bit
- Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit
- Demod.bitCount = 0;
- Demod.shiftReg = 0;
- if ((Demod.len & 0x0007) == 0) { // every 8 data bytes
- Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits
- Demod.parityBits = 0;
- }
- }
- Demod.endTime = Demod.startTime + 8 * (9 * Demod.len + Demod.bitCount + 1) - 4;
- } else { // no modulation in first half
- if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0
- Demod.bitCount++;
- Demod.shiftReg = (Demod.shiftReg >> 1); // add a 0 to the shiftreg
- if (Demod.bitCount >= 9) { // if we decoded a full byte (including parity)
- Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
- Demod.parityBits <<= 1; // make room for the new parity bit
- Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit
- Demod.bitCount = 0;
- Demod.shiftReg = 0;
- if ((Demod.len & 0x0007) == 0) { // every 8 data bytes
- Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1
- Demod.parityBits = 0;
- }
- }
- Demod.endTime = Demod.startTime + 8 * (9 * Demod.len + Demod.bitCount + 1);
- } else { // no modulation in both halves - End of communication
- if (Demod.bitCount > 0) { // there are some remaining data bits
- Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits
- Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
- Demod.parityBits <<= 1; // add a (void) parity bit
- Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits
- Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
- return true;
- } else if (Demod.len & 0x0007) { // there are some parity bits to store
- Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits
- Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
- }
- if (Demod.len) {
- return true; // we are finished with decoding the raw data sequence
- } else { // nothing received. Start over
- Demod14aReset();
- }
- }
- }
- }
- return false; // not finished yet, need more data
-}
-
-
-// Thinfilm, Kovio mangels ISO14443A in the way that they don't use start bit nor parity bits.
-RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) {
- Demod.twoBits = (Demod.twoBits << 8) | bit;
-
- if (Demod.state == DEMOD_14A_UNSYNCD) {
-
- if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
- if (Demod.twoBits == 0x0000) {
- Demod.highCnt++;
- } else {
- Demod.highCnt = 0;
- }
- } else {
- Demod.syncBit = 0xFFFF; // not set
- if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7;
- else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6;
- else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5;
- else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4;
- else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3;
- else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2;
- else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1;
- else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0;
- if (Demod.syncBit != 0xFFFF) {
- Demod.startTime = (GetCountSspClk() & 0xfffffff8);
- Demod.startTime -= Demod.syncBit;
- Demod.bitCount = 1; // number of decoded data bits
- Demod.shiftReg = 1;
- Demod.state = DEMOD_14A_MANCHESTER_DATA;
- }
- }
- } else {
-
- if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half
- if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision
- if (!Demod.collisionPos) {
- Demod.collisionPos = (Demod.len << 3) + Demod.bitCount;
- }
- } // modulation in first half only - Sequence D = 1
- Demod.bitCount++;
- Demod.shiftReg = (Demod.shiftReg << 1) | 0x1; // in both cases, add a 1 to the shiftreg
- if (Demod.bitCount == 8) { // if we decoded a full byte
- Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
- Demod.bitCount = 0;
- Demod.shiftReg = 0;
- }
- Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1) - 4;
- } else { // no modulation in first half
- if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0
- Demod.bitCount++;
- Demod.shiftReg = (Demod.shiftReg << 1); // add a 0 to the shiftreg
- if (Demod.bitCount >= 8) { // if we decoded a full byte
- Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
- Demod.bitCount = 0;
- Demod.shiftReg = 0;
- }
- Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1);
- } else { // no modulation in both halves - End of communication
- if (Demod.bitCount > 0) { // there are some remaining data bits
- Demod.shiftReg <<= (8 - Demod.bitCount); // left align the decoded bits
- Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
- return true;
- }
- if (Demod.len) {
- return true; // we are finished with decoding the raw data sequence
- } else { // nothing received. Start over
- Demod14aReset();
- }
- }
- }
- }
- return false; // not finished yet, need more data
-}
-
-//=============================================================================
-// Finally, a `sniffer' for ISO 14443 Type A
-// Both sides of communication!
-//=============================================================================
-
-//-----------------------------------------------------------------------------
-// Record the sequence of commands sent by the reader to the tag, with
-// triggering so that we start recording at the point that the tag is moved
-// near the reader.
-// "hf 14a sniff"
-//-----------------------------------------------------------------------------
-void RAMFUNC SniffIso14443a(uint8_t param) {
- LEDsoff();
- // param:
- // bit 0 - trigger from first card answer
- // bit 1 - trigger from first reader 7-bit request
- iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
-
- // Allocate memory from BigBuf for some buffers
- // free all previous allocations first
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // The command (reader -> tag) that we're receiving.
- uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
- uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
-
- // The response (tag -> reader) that we're receiving.
- uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
- uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
-
- // The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
- uint8_t *data = dmaBuf;
-
- uint8_t previous_data = 0;
- int maxDataLen = 0, dataLen;
- bool TagIsActive = false;
- bool ReaderIsActive = false;
-
- // Set up the demodulator for tag -> reader responses.
- Demod14aInit(receivedResp, receivedRespPar);
-
- // Set up the demodulator for the reader -> tag commands
- Uart14aInit(receivedCmd, receivedCmdPar);
-
- DbpString("Starting to sniff");
-
- // Setup and start DMA.
- if (!FpgaSetupSscDma((uint8_t *) dmaBuf, DMA_BUFFER_SIZE)) {
- if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
- return;
- }
-
- // We won't start recording the frames that we acquire until we trigger;
- // a good trigger condition to get started is probably when we see a
- // response from the tag.
- // triggered == false -- to wait first for card
- bool triggered = !(param & 0x03);
-
- uint32_t rx_samples = 0;
-
- // loop and listen
- while (!BUTTON_PRESS()) {
- WDT_HIT();
- LED_A_ON();
-
- int register readBufDataP = data - dmaBuf;
- int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
- if (readBufDataP <= dmaBufDataP)
- dataLen = dmaBufDataP - readBufDataP;
- else
- dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP;
-
- // test for length of buffer
- if (dataLen > maxDataLen) {
- maxDataLen = dataLen;
- if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
- Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
- break;
- }
- }
- if (dataLen < 1) continue;
-
- // primary buffer was stopped( <-- we lost data!
- if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
- AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
- Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
- }
- // secondary buffer sets as primary, secondary buffer was stopped
- if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
- }
-
- LED_A_OFF();
-
- // Need two samples to feed Miller and Manchester-Decoder
- if (rx_samples & 0x01) {
-
- if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
- uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
- if (MillerDecoding(readerdata, (rx_samples - 1) * 4)) {
- LED_C_ON();
-
- // check - if there is a short 7bit request from reader
- if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = true;
-
- if (triggered) {
- if (!LogTrace(receivedCmd,
- Uart.len,
- Uart.startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
- Uart.endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
- Uart.parity,
- true)) break;
- }
- /* ready to read another command. */
- Uart14aReset();
- /* reset the demod code, which might have been */
- /* false-triggered by the commands from the reader. */
- Demod14aReset();
- LED_B_OFF();
- }
- ReaderIsActive = (Uart.state != STATE_14A_UNSYNCD);
- }
-
- // no need to try decoding tag data if the reader is sending - and we cannot afford the time
- if (!ReaderIsActive) {
- uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
- if (ManchesterDecoding(tagdata, 0, (rx_samples - 1) * 4)) {
- LED_B_ON();
-
- if (!LogTrace(receivedResp,
- Demod.len,
- Demod.startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
- Demod.endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
- Demod.parity,
- false)) break;
-
- if ((!triggered) && (param & 0x01)) triggered = true;
-
- // ready to read another response.
- Demod14aReset();
- // reset the Miller decoder including its (now outdated) input buffer
- Uart14aReset();
- //Uart14aInit(receivedCmd, receivedCmdPar);
- LED_C_OFF();
- }
- TagIsActive = (Demod.state != DEMOD_14A_UNSYNCD);
- }
- }
-
- previous_data = *data;
- rx_samples++;
- data++;
- if (data == dmaBuf + DMA_BUFFER_SIZE) {
- data = dmaBuf;
- }
- } // end main loop
-
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_ERROR) {
- Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len);
- Dbprintf("traceLen=" _YELLOW_("%d")", Uart.output[0]="_YELLOW_("%08x"), BigBuf_get_traceLen(), (uint32_t)Uart.output[0]);
- }
- switch_off();
-}
-
-//-----------------------------------------------------------------------------
-// Prepare tag messages
-//-----------------------------------------------------------------------------
-static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par, bool collision) {
-
- //uint8_t localCol = 0;
- ToSendReset();
-
- // Correction bit, might be removed when not needed
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(1); // <-----
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
-
- // Send startbit
- ToSend[++ToSendMax] = SEC_D;
- LastProxToAirDuration = 8 * ToSendMax - 4;
-
- for (uint16_t i = 0; i < len; i++) {
- uint8_t b = cmd[i];
-
- // Data bits
- for (uint16_t j = 0; j < 8; j++) {
- //if (collision && (localCol >= colpos)){
- if (collision) {
- ToSend[++ToSendMax] = SEC_COLL;
- //localCol++;
- } else {
- if (b & 1) {
- ToSend[++ToSendMax] = SEC_D;
- } else {
- ToSend[++ToSendMax] = SEC_E;
- }
- b >>= 1;
- }
- }
-
- if (collision) {
- ToSend[++ToSendMax] = SEC_COLL;
- LastProxToAirDuration = 8 * ToSendMax;
- } else {
- // Get the parity bit
- if (par[i >> 3] & (0x80 >> (i & 0x0007))) {
- ToSend[++ToSendMax] = SEC_D;
- LastProxToAirDuration = 8 * ToSendMax - 4;
- } else {
- ToSend[++ToSendMax] = SEC_E;
- LastProxToAirDuration = 8 * ToSendMax;
- }
- }
- }
-
- // Send stopbit
- ToSend[++ToSendMax] = SEC_F;
-
- // Convert from last byte pos to length
- ToSendMax++;
-}
-
-static void CodeIso14443aAsTagEx(const uint8_t *cmd, uint16_t len, bool collision) {
- uint8_t par[MAX_PARITY_SIZE] = {0};
- GetParity(cmd, len, par);
- CodeIso14443aAsTagPar(cmd, len, par, collision);
-}
-static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) {
- CodeIso14443aAsTagEx(cmd, len, false);
-}
-
-static void Code4bitAnswerAsTag(uint8_t cmd) {
- uint8_t b = cmd;
-
- ToSendReset();
-
- // Correction bit, might be removed when not needed
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(1); // 1
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
-
- // Send startbit
- ToSend[++ToSendMax] = SEC_D;
-
- for (uint8_t i = 0; i < 4; i++) {
- if (b & 1) {
- ToSend[++ToSendMax] = SEC_D;
- LastProxToAirDuration = 8 * ToSendMax - 4;
- } else {
- ToSend[++ToSendMax] = SEC_E;
- LastProxToAirDuration = 8 * ToSendMax;
- }
- b >>= 1;
- }
-
- // Send stopbit
- ToSend[++ToSendMax] = SEC_F;
-
- // Convert from last byte pos to length
- ToSendMax++;
-}
-
-//-----------------------------------------------------------------------------
-// Wait for commands from reader
-// stop when button is pressed or client usb connection resets
-// or return TRUE when command is captured
-//-----------------------------------------------------------------------------
-static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
- // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
-
- // Now run a `software UART` on the stream of incoming samples.
- Uart14aInit(received, par);
-
- // clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint16_t check = 0;
-
- for (;;) {
- if (check == 1000) {
- if (BUTTON_PRESS() || data_available())
- return false;
- check = 0;
- }
- ++check;
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- if (MillerDecoding(b, 0)) {
- *len = Uart.len;
- return true;
- }
- }
- }
- return false;
-}
-
-static bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size) {
- // Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes
- // This will need the following byte array for a modulation sequence
- // 144 data bits (18 * 8)
- // 18 parity bits
- // 2 Start and stop
- // 1 Correction bit (Answer in 1172 or 1236 periods, see FPGA)
- // 1 just for the case
- // ----------- +
- // 166 bytes, since every bit that needs to be write costs us a byte
- //
- // Prepare the tag modulation bits from the message
- CodeIso14443aAsTag(response_info->response, response_info->response_n);
-
- // Make sure we do not exceed the free buffer space
- if (ToSendMax > max_buffer_size) {
- Dbprintf("Out of memory, when modulating bits for tag answer:");
- Dbhexdump(response_info->response_n, response_info->response, false);
- return false;
- }
-
- // Copy the byte array, used for this modulation to the buffer position
- memcpy(response_info->modulation, ToSend, ToSendMax);
-
- // Store the number of bytes that were used for encoding/modulation and the time needed to transfer them
- response_info->modulation_n = ToSendMax;
- response_info->ProxToAirDuration = LastProxToAirDuration;
- return true;
-}
-
-bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size) {
-
- // Retrieve and store the current buffer index
- response_info->modulation = *buffer;
-
- // Forward the prepare tag modulation function to the inner function
- if (prepare_tag_modulation(response_info, *max_buffer_size)) {
- // Update the free buffer offset and the remaining buffer size
- *buffer += ToSendMax;
- *max_buffer_size -= ToSendMax;
- return true;
- } else {
- return false;
- }
-}
-
-static bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) {
- uint8_t sak = 0;
- // The first response contains the ATQA (note: bytes are transmitted in reverse order).
- static uint8_t rATQA[2] = { 0x00 };
- // The second response contains the (mandatory) first 24 bits of the UID
- static uint8_t rUIDc1[5] = { 0x00 };
- // For UID size 7,
- static uint8_t rUIDc2[5] = { 0x00 };
- // Prepare the mandatory SAK (for 4 and 7 byte UID)
- static uint8_t rSAKc1[3] = { 0x00 };
- // Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
- static uint8_t rSAKc2[3] = { 0x00 };
- // dummy ATS (pseudo-ATR), answer to RATS
- static uint8_t rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 };
- // GET_VERSION response for EV1/NTAG
- static uint8_t rVERSION[10] = { 0x00 };
- // READ_SIG response for EV1/NTAG
- static uint8_t rSIGN[34] = { 0x00 };
-
- switch (tagType) {
- case 1: { // MIFARE Classic 1k
- rATQA[0] = 0x04;
- sak = 0x08;
- }
- break;
- case 2: { // MIFARE Ultralight
- rATQA[0] = 0x44;
- sak = 0x00;
- // some first pages of UL/NTAG dump is special data
- mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr();
- *pages = MAX(mfu_header->pages, 15);
- }
- break;
- case 3: { // MIFARE DESFire
- rATQA[0] = 0x04;
- rATQA[1] = 0x03;
- sak = 0x20;
- }
- break;
- case 4: { // ISO/IEC 14443-4 - javacard (JCOP)
- rATQA[0] = 0x04;
- sak = 0x28;
- }
- break;
- case 5: { // MIFARE TNP3XXX
- rATQA[0] = 0x01;
- rATQA[1] = 0x0f;
- sak = 0x01;
- }
- break;
- case 6: { // MIFARE Mini 320b
- rATQA[0] = 0x44;
- sak = 0x09;
- }
- break;
- case 7: { // NTAG
- rATQA[0] = 0x44;
- sak = 0x00;
- // some first pages of UL/NTAG dump is special data
- mfu_dump_t *mfu_header = (mfu_dump_t *) BigBuf_get_EM_addr();
- *pages = MAX(mfu_header->pages, 19);
- // counters and tearing flags
- for (int i = 0; i < 3; i++) {
- counters[i] = le24toh(mfu_header->counter_tearing[i]);
- tearings[i] = mfu_header->counter_tearing[i][3];
- }
- // GET_VERSION
- memcpy(rVERSION, mfu_header->version, 8);
- AddCrc14A(rVERSION, sizeof(rVERSION) - 2);
- // READ_SIG
- memcpy(rSIGN, mfu_header->signature, 32);
- AddCrc14A(rSIGN, sizeof(rSIGN) - 2);
- }
- break;
- case 8: { // MIFARE Classic 4k
- rATQA[0] = 0x02;
- sak = 0x18;
- }
- break;
- case 9 : { // FM11RF005SH (Shanghai Metro)
- rATQA[0] = 0x03;
- rATQA[1] = 0x00;
- sak = 0x0A;
- }
- break;
- default: {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType);
- return false;
- }
- break;
- }
-
- // if uid not supplied then get from emulator memory
- if (data[0] == 0 || (flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) {
- if (tagType == 2 || tagType == 7) {
- uint16_t start = MFU_DUMP_PREFIX_LENGTH;
- uint8_t emdata[8];
- emlGetMemBt(emdata, start, sizeof(emdata));
- memcpy(data, emdata, 3); // uid bytes 0-2
- memcpy(data + 3, emdata + 4, 4); // uid bytes 3-7
- flags |= FLAG_7B_UID_IN_DATA;
- } else {
- emlGetMemBt(data, 0, 4);
- flags |= FLAG_4B_UID_IN_DATA;
- }
- }
-
- if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
- rUIDc1[0] = 0x88; // Cascade Tag marker
- rUIDc1[1] = data[0];
- rUIDc1[2] = data[1];
- rUIDc1[3] = data[2];
-
- rUIDc2[0] = data[3];
- rUIDc2[1] = data[4];
- rUIDc2[2] = data[5];
- rUIDc2[3] = data[6];
- rUIDc2[4] = rUIDc2[0] ^ rUIDc2[1] ^ rUIDc2[2] ^ rUIDc2[3];
-
- // Configure the ATQA and SAK accordingly
- rATQA[0] |= 0x40;
- sak |= 0x04;
-
- *cuid = bytes_to_num(data + 3, 4);
- } else if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) {
- memcpy(rUIDc1, data, 4);
- // Configure the ATQA and SAK accordingly
- rATQA[0] &= 0xBF;
- sak &= 0xFB;
- *cuid = bytes_to_num(data, 4);
- } else {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("[-] ERROR: UID size not defined");
- return false;
- }
-
- // Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID.
- rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3];
-
- rSAKc1[0] = sak;
- AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
-
- rSAKc2[0] = sak & 0xFB;
- AddCrc14A(rSAKc2, sizeof(rSAKc2) - 2);
-
- // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
- // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
- // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
- // TC(1) = 0x02: CID supported, NAD not supported
- AddCrc14A(rRATS, sizeof(rRATS) - 2);
-
-#define TAG_RESPONSE_COUNT 8
- static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
- { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
- { .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid
- { .response = rUIDc2, .response_n = sizeof(rUIDc2) }, // Anticollision cascade2 - respond with 2nd half of uid if asked
- { .response = rSAKc1, .response_n = sizeof(rSAKc1) }, // Acknowledge select - cascade 1
- { .response = rSAKc2, .response_n = sizeof(rSAKc2) }, // Acknowledge select - cascade 2
- { .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS
- { .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response
- { .response = rSIGN, .response_n = sizeof(rSIGN) } // EV1/NTAG READ_SIG response
- };
-
- // "precompile" responses. There are 8 predefined responses with a total of 68 bytes data to transmit.
- // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
- // 68 * 8 data bits, 68 * 1 parity bits, 8 start bits, 8 stop bits, 8 correction bits -- 636 bytes buffer
-#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 636
-
- uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
- // modulation buffer pointer and current buffer free space size
- uint8_t *free_buffer_pointer = free_buffer;
- size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
-
- // Prepare the responses of the anticollision phase
- // there will be not enough time to do this at the moment the reader sends it REQA
- for (size_t i = 0; i < TAG_RESPONSE_COUNT; i++) {
- if (prepare_allocated_tag_modulation(&responses_init[i], &free_buffer_pointer, &free_buffer_size) == false) {
- BigBuf_free_keep_EM();
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Not enough modulation buffer size, exit after %d elements", i);
- return false;
- }
- }
-
- *responses = responses_init;
-
- // indices into responses array:
-#define ATQA 0
-#define UIDC1 1
-#define UIDC2 2
-#define SAKC1 3
-#define SAKC2 4
-#define RATS 5
-#define VERSION 6
-#define SIGNATURE 7
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Main loop of simulated tag: read commands from reader, decide what
-// response to write, and write it.
-// 'hf 14a sim'
-//-----------------------------------------------------------------------------
-void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
-
-#define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
-
- tag_response_info_t *responses;
- uint32_t cuid = 0;
- uint32_t nonce = 0;
- uint32_t counters[3] = { 0x00, 0x00, 0x00 };
- uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
- uint8_t pages = 0;
-
- // Here, we collect CUID, block1, keytype1, NT1, NR1, AR1, CUID, block2, keytyp2, NT2, NR2, AR2
- // it should also collect block, keytype.
- uint8_t cardAUTHSC = 0;
- uint8_t cardAUTHKEY = 0xff; // no authentication
- // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys
-
- nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; // for attack types moebius
- memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces));
- uint8_t moebius_count = 0;
-
- // command buffers
- uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
- uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
-
- // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
- // Such a response is less time critical, so we can prepare them on the fly
-#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
-#define DYNAMIC_MODULATION_BUFFER_SIZE 512
- uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE];
- uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE];
- tag_response_info_t dynamic_response_info = {
- .response = dynamic_response_buffer,
- .response_n = 0,
- .modulation = dynamic_modulation_buffer,
- .modulation_n = 0
- };
-
- // free eventually allocated BigBuf memory but keep Emulator Memory
- BigBuf_free_keep_EM();
-
- if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
- BigBuf_free_keep_EM();
- reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
- return;
- }
-
- // We need to listen to the high-frequency, peak-detected path.
- iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
-
- int len = 0;
-
- // To control where we are in the protocol
-#define ORDER_NONE 0
-#define ORDER_REQA 1
-#define ORDER_SELECT_ALL_CL1 2
-#define ORDER_SELECT_CL1 3
-#define ORDER_HALTED 5
-#define ORDER_WUPA 6
-#define ORDER_AUTH 7
-#define ORDER_SELECT_ALL_CL2 20
-#define ORDER_SELECT_CL2 30
-#define ORDER_EV1_COMP_WRITE 40
-#define ORDER_RATS 70
- uint8_t order = ORDER_NONE;
-
- int retval = PM3_SUCCESS;
-
- // Just to allow some checks
- int happened = 0;
- int happened2 = 0;
- int cmdsRecvd = 0;
-
- // compatible write block number
- uint8_t wrblock = 0;
-
- clear_trace();
- set_tracing(true);
- LED_A_ON();
- for (;;) {
- WDT_HIT();
-
- // Clean read command buffer
- if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
- Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
- retval = PM3_EOPABORTED;
- break;
- }
- tag_response_info_t *p_response = NULL;
-
- // Okay, look at the command now.
- int lastorder = order;
-
- //
- // we need to check "ordered" states before, because received data may be same to any command - is wrong!!!
- //
-
- if (order == ORDER_EV1_COMP_WRITE && len == 18) {
- // MIFARE_ULC_COMP_WRITE part 2
- // 16 bytes data + 2 bytes crc, only least significant 4 bytes are written
- bool isCrcCorrect = CheckCrc14A(receivedCmd, len);
- if (isCrcCorrect) {
- // first blocks of emu are header
- emlSetMem_xt(receivedCmd, wrblock + MFU_DUMP_PREFIX_LENGTH / 4, 1, 4);
- // write ACK
- EmSend4bit(CARD_ACK);
- } else {
- // write NACK 0x1 == crc/parity error
- EmSend4bit(CARD_NACK_PA);
- }
- order = ORDER_NONE; // back to work state
- p_response = NULL;
-
- } else if (order == ORDER_AUTH && len == 8) {
- // Received {nr] and {ar} (part of authentication)
- LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
- uint32_t nr = bytes_to_num(receivedCmd, 4);
- uint32_t ar = bytes_to_num(receivedCmd + 4, 4);
-
- // Collect AR/NR per keytype & sector
- if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
-
- int8_t index = -1;
- int8_t empty = -1;
- for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
- // find which index to use
- if ((cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype))
- index = i;
-
- // keep track of empty slots.
- if (ar_nr_nonces[i].state == EMPTY)
- empty = i;
- }
- // if no empty slots. Choose first and overwrite.
- if (index == -1) {
- if (empty == -1) {
- index = 0;
- ar_nr_nonces[index].state = EMPTY;
- } else {
- index = empty;
- }
- }
-
- switch (ar_nr_nonces[index].state) {
- case EMPTY: {
- // first nonce collect
- ar_nr_nonces[index].cuid = cuid;
- ar_nr_nonces[index].sector = cardAUTHSC;
- ar_nr_nonces[index].keytype = cardAUTHKEY;
- ar_nr_nonces[index].nonce = nonce;
- ar_nr_nonces[index].nr = nr;
- ar_nr_nonces[index].ar = ar;
- ar_nr_nonces[index].state = FIRST;
- break;
- }
- case FIRST : {
- // second nonce collect
- ar_nr_nonces[index].nonce2 = nonce;
- ar_nr_nonces[index].nr2 = nr;
- ar_nr_nonces[index].ar2 = ar;
- ar_nr_nonces[index].state = SECOND;
-
- // write to client (one struct nonces_t)
- reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t));
-
- ar_nr_nonces[index].state = EMPTY;
- ar_nr_nonces[index].sector = 0;
- ar_nr_nonces[index].keytype = 0;
-
- moebius_count++;
- break;
- }
- default:
- break;
- }
- }
- order = ORDER_NONE; // back to work state
- p_response = NULL;
-
- //
- // now check commands in received buffer
- //
-
- } else if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST
- p_response = &responses[ATQA];
- order = ORDER_REQA;
- } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
- p_response = &responses[ATQA];
- order = ORDER_WUPA;
- } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1)
- p_response = &responses[UIDC1];
- order = ORDER_SELECT_ALL_CL1;
- } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 2) { // Received request for UID (cascade 2)
- p_response = &responses[UIDC2];
- order = ORDER_SELECT_ALL_CL2;
- } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
- p_response = &responses[SAKC1];
- order = ORDER_SELECT_CL1;
- } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2)
- p_response = &responses[SAKC2];
- order = ORDER_SELECT_CL2;
- } else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK && len == 4) { // Received a (plain) READ
- uint8_t block = receivedCmd[1];
- // if Ultralight or NTAG (4 byte blocks)
- if (tagType == 7 || tagType == 2) {
- if (block > pages) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- // first blocks of emu are header
- uint16_t start = block * 4 + MFU_DUMP_PREFIX_LENGTH;
- uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
- emlGetMemBt(emdata, start, 16);
- AddCrc14A(emdata, 16);
- EmSendCmd(emdata, sizeof(emdata));
- }
- // We already responded, do not write anything with the EmSendCmd14443aRaw() that is called below
- p_response = NULL;
- } else if (tagType == 9 && block == 1) {
- // FM11005SH. 16blocks, 4bytes / block.
- // block0 = 2byte Customer ID (CID), 2byte Manufacture ID (MID)
- // block1 = 4byte UID.
- p_response = &responses[UIDC1];
- } else { // all other tags (16 byte block tags)
- uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
- emlGetMemBt(emdata, block, 16);
- AddCrc14A(emdata, 16);
- EmSendCmd(emdata, sizeof(emdata));
- // EmSendCmd(data+(4*receivedCmd[1]),16);
- // Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]);
- // We already responded, do not write anything with the EmSendCmd14443aRaw() that is called below
- p_response = NULL;
- }
- } else if (receivedCmd[0] == MIFARE_ULEV1_FASTREAD && len == 5) { // Received a FAST READ (ranged read)
- uint8_t block1 = receivedCmd[1];
- uint8_t block2 = receivedCmd[2];
- if (block1 > pages) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- uint8_t emdata[MAX_FRAME_SIZE];
- // first blocks of emu are header
- int start = block1 * 4 + MFU_DUMP_PREFIX_LENGTH;
- len = (block2 - block1 + 1) * 4;
- emlGetMemBt(emdata, start, len);
- AddCrc14A(emdata, len);
- EmSendCmd(emdata, len + 2);
- }
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7)) { // Received a WRITE
- // cmd + block + 4 bytes data + 2 bytes crc
- bool isCrcCorrect = CheckCrc14A(receivedCmd, len);
- if (isCrcCorrect) {
- uint8_t block = receivedCmd[1];
- if (block > pages) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- // first blocks of emu are header
- emlSetMem_xt(&receivedCmd[2], block + MFU_DUMP_PREFIX_LENGTH / 4, 1, 4);
- // write ACK
- EmSend4bit(CARD_ACK);
- }
- } else {
- // write NACK 0x1 == crc/parity error
- EmSend4bit(CARD_NACK_PA);
- }
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7)) {
- // cmd + block + 2 bytes crc
- bool isCrcCorrect = CheckCrc14A(receivedCmd, len);
- if (isCrcCorrect) {
- wrblock = receivedCmd[1];
- if (wrblock > pages) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- // write ACK
- EmSend4bit(CARD_ACK);
- // go to part 2
- order = ORDER_EV1_COMP_WRITE;
- }
- } else {
- // write NACK 0x1 == crc/parity error
- EmSend4bit(CARD_NACK_PA);
- }
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && len == 4 && tagType == 7) { // Received a READ SIGNATURE --
- p_response = &responses[SIGNATURE];
- } else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && len == 4 && tagType == 7) { // Received a READ COUNTER --
- uint8_t index = receivedCmd[1];
- if (index > 2) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- uint8_t cmd[] = {0x00, 0x00, 0x00, 0x14, 0xa5};
- htole24(counters[index], cmd);
- AddCrc14A(cmd, sizeof(cmd) - 2);
- EmSendCmd(cmd, sizeof(cmd));
- }
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && len == 8 && tagType == 7) { // Received a INC COUNTER --
- uint8_t index = receivedCmd[1];
- if (index > 2) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- uint32_t val = le24toh(receivedCmd + 2) + counters[index];
- // if new value + old value is bigger 24bits, fail
- if (val > 0xFFFFFF) {
- // write NACK 0x4 == counter overflow
- EmSend4bit(CARD_NACK_NA);
- } else {
- counters[index] = val;
- // write ACK
- EmSend4bit(CARD_ACK);
- }
- }
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && len == 4 && tagType == 7) { // Received a CHECK_TEARING_EVENT --
- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature]
- uint8_t index = receivedCmd[1];
- if (index > 2) {
- // write NACK 0x0 == invalid argument
- EmSend4bit(CARD_NACK_IV);
- } else {
- uint8_t cmd[3];
- cmd[0] = tearings[index];
- AddCrc14A(cmd, sizeof(cmd) - 2);
- EmSendCmd(cmd, sizeof(cmd));
- }
- p_response = NULL;
- } else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
- LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
- p_response = NULL;
- order = ORDER_HALTED;
- } else if (receivedCmd[0] == MIFARE_ULEV1_VERSION && len == 3 && (tagType == 2 || tagType == 7)) {
- p_response = &responses[VERSION];
- } else if ((receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) && len == 4 && tagType != 2 && tagType != 7) { // Received an authentication request
- cardAUTHKEY = receivedCmd[0] - 0x60;
- cardAUTHSC = receivedCmd[1] / 4; // received block num
-
- // incease nonce at AUTH requests. this is time consuming.
- nonce = prng_successor(GetTickCount(), 32);
- num_to_bytes(nonce, 4, dynamic_response_info.response);
- dynamic_response_info.response_n = 4;
-
- prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE);
- p_response = &dynamic_response_info;
- order = ORDER_AUTH;
- } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
- if (tagType == 1 || tagType == 2) { // RATS not supported
- EmSend4bit(CARD_NACK_NA);
- p_response = NULL;
- } else {
- p_response = &responses[RATS];
- order = ORDER_RATS;
- }
- } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication
- LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH && len == 7 && tagType == 7) { // NTAG / EV-1 authentication
- // PWD stored in dump now
- uint8_t pwd[4];
- emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
- if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
- uint8_t cmd[4];
- emlGetMemBt(cmd, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
- AddCrc14A(cmd, sizeof(cmd) - 2);
- EmSendCmd(cmd, sizeof(cmd));
- } else {
- EmSend4bit(CARD_NACK_NA);
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Auth attempt: %08x", bytes_to_num(receivedCmd + 1, 4));
- }
- p_response = NULL;
- } else if (receivedCmd[0] == MIFARE_ULEV1_VCSL && len == 23 && tagType == 7) {
- uint8_t cmd[3];
- emlGetMemBt(cmd, (pages - 2) * 4 + 1 + MFU_DUMP_PREFIX_LENGTH, 1);
- AddCrc14A(cmd, sizeof(cmd) - 2);
- EmSendCmd(cmd, sizeof(cmd));
- p_response = NULL;
- } else {
- // Check for ISO 14443A-4 compliant commands, look at left nibble
- switch (receivedCmd[0]) {
- case 0x02:
- case 0x03: { // IBlock (command no CID)
- dynamic_response_info.response[0] = receivedCmd[0];
- dynamic_response_info.response[1] = 0x90;
- dynamic_response_info.response[2] = 0x00;
- dynamic_response_info.response_n = 3;
- }
- break;
- case 0x0B:
- case 0x0A: { // IBlock (command CID)
- dynamic_response_info.response[0] = receivedCmd[0];
- dynamic_response_info.response[1] = 0x00;
- dynamic_response_info.response[2] = 0x90;
- dynamic_response_info.response[3] = 0x00;
- dynamic_response_info.response_n = 4;
- }
- break;
-
- case 0x1A:
- case 0x1B: { // Chaining command
- dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1);
- dynamic_response_info.response_n = 2;
- }
- break;
-
- case 0xAA:
- case 0xBB: {
- dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11;
- dynamic_response_info.response_n = 2;
- }
- break;
-
- case 0xBA: { // ping / pong
- dynamic_response_info.response[0] = 0xAB;
- dynamic_response_info.response[1] = 0x00;
- dynamic_response_info.response_n = 2;
- }
- break;
-
- case 0xCA:
- case 0xC2: { // Readers sends deselect command
- dynamic_response_info.response[0] = 0xCA;
- dynamic_response_info.response[1] = 0x00;
- dynamic_response_info.response_n = 2;
- }
- break;
-
- default: {
- // Never seen this command before
- LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
- if (DBGLEVEL >= DBG_DEBUG) {
- Dbprintf("Received unknown command (len=%d):", len);
- Dbhexdump(len, receivedCmd, false);
- }
- // Do not respond
- dynamic_response_info.response_n = 0;
- order = ORDER_NONE; // back to work state
- }
- break;
- }
-
- if (dynamic_response_info.response_n > 0) {
- // Copy the CID from the reader query
- dynamic_response_info.response[1] = receivedCmd[1];
-
- // Add CRC bytes, always used in ISO 14443A-4 compliant cards
- AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n);
- dynamic_response_info.response_n += 2;
-
- if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
- if (DBGLEVEL >= DBG_DEBUG) DbpString("Error preparing tag response");
- LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
- break;
- }
- p_response = &dynamic_response_info;
- }
- }
-
- // Count number of wakeups received after a halt
- if (order == ORDER_WUPA && lastorder == ORDER_HALTED) { happened++; }
-
- // Count number of other messages after a halt
- if (order != ORDER_WUPA && lastorder == ORDER_HALTED) { happened2++; }
-
- cmdsRecvd++;
-
- if (p_response != NULL) {
- EmSendPrecompiledCmd(p_response);
- }
- }
-
- switch_off();
-
- set_tracing(false);
- BigBuf_free_keep_EM();
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("-[ Wake ups after halt [%d]", happened);
- Dbprintf("-[ Messages after halt [%d]", happened2);
- Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd);
- Dbprintf("-[ Num of moebius tries [%d]", moebius_count);
- }
-
- reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
-}
-
-// prepare a delayed transfer. This simply shifts ToSend[] by a number
-// of bits specified in the delay parameter.
-void PrepareDelayedTransfer(uint16_t delay) {
- delay &= 0x07;
- if (!delay) return;
-
- uint8_t bitmask = 0;
- uint8_t bits_shifted = 0;
-
- for (uint16_t i = 0; i < delay; i++)
- bitmask |= (0x01 << i);
-
- ToSend[ToSendMax++] = 0x00;
-
- for (uint16_t i = 0; i < ToSendMax; i++) {
- uint8_t bits_to_shift = ToSend[i] & bitmask;
- ToSend[i] = ToSend[i] >> delay;
- ToSend[i] = ToSend[i] | (bits_shifted << (8 - delay));
- bits_shifted = bits_to_shift;
- }
-}
-
-
-//-------------------------------------------------------------------------------------
-// Transmit the command (to the tag) that was placed in ToSend[].
-// Parameter timing:
-// if NULL: transfer at next possible time, taking into account
-// request guard time and frame delay time
-// if == 0: transfer immediately and return time of transfer
-// if != 0: delay transfer until time specified
-//-------------------------------------------------------------------------------------
-static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
-
- if (!hf_field_active)
- return;
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
-
- if (timing) {
- if (*timing == 0) // Measure time
- *timing = (GetCountSspClk() + 8) & 0xfffffff8;
- else
- PrepareDelayedTransfer(*timing & 0x00000007); // Delay transfer (fine tuning - up to 7 MF clock ticks)
-
- if (DBGLEVEL >= DBG_EXTENDED && GetCountSspClk() >= (*timing & 0xfffffff8))
- Dbprintf("TransmitFor14443a: Missed timing");
- while (GetCountSspClk() < (*timing & 0xfffffff8)) {}; // Delay transfer (multiple of 8 MF clock ticks)
- LastTimeProxToAirStart = *timing;
- } else {
-
- uint32_t ThisTransferTime = 0;
- ThisTransferTime = ((MAX(NextTransferTime, GetCountSspClk()) & 0xfffffff8) + 8);
-
- while (GetCountSspClk() < ThisTransferTime) {};
-
- LastTimeProxToAirStart = ThisTransferTime;
- }
-
- uint16_t c = 0;
- while (c < len) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = cmd[c];
- c++;
- }
- }
-
- NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME);
-}
-
-//-----------------------------------------------------------------------------
-// Prepare reader command (in bits, support short frames) to write to FPGA
-//-----------------------------------------------------------------------------
-void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *par) {
- int last = 0;
-
- ToSendReset();
-
- // Start of Communication (Seq. Z)
- ToSend[++ToSendMax] = SEC_Z;
- LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
-
- size_t bytecount = nbytes(bits);
- // Generate write structure for the data bits
- for (int i = 0; i < bytecount; i++) {
- // Get the current byte to write
- uint8_t b = cmd[i];
- size_t bitsleft = MIN((bits - (i * 8)), 8);
- int j;
- for (j = 0; j < bitsleft; j++) {
- if (b & 1) {
- // Sequence X
- ToSend[++ToSendMax] = SEC_X;
- LastProxToAirDuration = 8 * (ToSendMax + 1) - 2;
- last = 1;
- } else {
- if (last == 0) {
- // Sequence Z
- ToSend[++ToSendMax] = SEC_Z;
- LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
- } else {
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
- last = 0;
- }
- }
- b >>= 1;
- }
-
- // Only transmit parity bit if we transmitted a complete byte
- if (j == 8 && par != NULL) {
- // Get the parity bit
- if (par[i >> 3] & (0x80 >> (i & 0x0007))) {
- // Sequence X
- ToSend[++ToSendMax] = SEC_X;
- LastProxToAirDuration = 8 * (ToSendMax + 1) - 2;
- last = 1;
- } else {
- if (last == 0) {
- // Sequence Z
- ToSend[++ToSendMax] = SEC_Z;
- LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
- } else {
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
- last = 0;
- }
- }
- }
- }
-
- // End of Communication: Logic 0 followed by Sequence Y
- if (last == 0) {
- // Sequence Z
- ToSend[++ToSendMax] = SEC_Z;
- LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
- } else {
- // Sequence Y
- ToSend[++ToSendMax] = SEC_Y;
- }
- ToSend[++ToSendMax] = SEC_Y;
-
- // Convert to length of command:
- ToSendMax++;
-}
-
-//-----------------------------------------------------------------------------
-// Prepare reader command to write to FPGA
-//-----------------------------------------------------------------------------
-void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *par) {
- CodeIso14443aBitsAsReaderPar(cmd, len * 8, par);
-}
-
-//-----------------------------------------------------------------------------
-// Wait for commands from reader
-// Stop when button is pressed (return 1) or field was gone (return 2)
-// Or return 0 when command is captured
-//-----------------------------------------------------------------------------
-int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
- *len = 0;
-
- uint32_t timer = 0;
- int analogCnt = 0;
- int analogAVG = 0;
-
- // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
-
- // Set ADC to read field strength
- AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
- AT91C_BASE_ADC->ADC_MR =
- ADC_MODE_PRESCALE(63) |
- ADC_MODE_STARTUP_TIME(1) |
- ADC_MODE_SAMPLE_HOLD_TIME(15);
- AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF);
- // start ADC
- AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
-
- // Now run a 'software UART' on the stream of incoming samples.
- Uart14aInit(received, par);
-
- // Clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint16_t check = 0;
-
- for (;;) {
- WDT_HIT();
-
- if (check == 1000) {
- if (BUTTON_PRESS() || data_available())
- return 1;
- check = 0;
- }
- ++check;
-
- // test if the field exists
- if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
- analogCnt++;
- analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
- AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
- if (analogCnt >= 32) {
- if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
- if (timer == 0) {
- timer = GetTickCount();
- } else {
- // 50ms no field --> card to idle state
- if (GetTickCountDelta(timer) > 50) {
- return 2;
- }
- }
- } else {
- timer = 0;
- }
- analogCnt = 0;
- analogAVG = 0;
- }
- }
-
- // read and test the miller decoding
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- if (MillerDecoding(b, 0)) {
- *len = Uart.len;
- return 0;
- }
- }
- }
-}
-
-int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
- volatile uint8_t b;
- uint16_t i = 0;
- uint32_t ThisTransferTime;
- bool correctionNeeded;
-
- // Modulate Manchester
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
-
- // Include correction bit if necessary
- if (Uart.bitCount == 7) {
- // Short tags (7 bits) don't have parity, determine the correct value from MSB
- correctionNeeded = Uart.output[0] & 0x40;
- } else {
- // The parity bits are left-aligned
- correctionNeeded = Uart.parity[(Uart.len - 1) / 8] & (0x80 >> ((Uart.len - 1) & 7));
- }
- // 1236, so correction bit needed
- i = (correctionNeeded) ? 0 : 1;
-
- // clear receiving shift register and holding register
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
- b = AT91C_BASE_SSC->SSC_RHR;
- (void) b;
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
- b = AT91C_BASE_SSC->SSC_RHR;
- (void) b;
-
- // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
- for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
- if (AT91C_BASE_SSC->SSC_RHR) break;
- }
-
- while ((ThisTransferTime = GetCountSspClk()) & 0x00000007);
-
- // Clear TXRDY:
- AT91C_BASE_SSC->SSC_THR = SEC_F;
-
- // write cycle
- for (; i < respLen;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = resp[i++];
- FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- }
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
- (void)b;
- }
- if (BUTTON_PRESS()) break;
- }
-
- // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
- uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
- for (i = 0; i <= fpga_queued_bits / 8 + 1;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = SEC_F;
- FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- i++;
- }
- }
- LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded ? 8 : 0);
- return 0;
-}
-
-int EmSend4bit(uint8_t resp) {
- Code4bitAnswerAsTag(resp);
- int res = EmSendCmd14443aRaw(ToSend, ToSendMax);
- // do the tracing for the previous reader request and this tag answer:
- uint8_t par[1] = {0x00};
- GetParity(&resp, 1, par);
- EmLogTrace(Uart.output,
- Uart.len,
- Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG,
- Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG,
- Uart.parity,
- &resp,
- 1,
- LastTimeProxToAirStart * 16 + DELAY_ARM2AIR_AS_TAG,
- (LastTimeProxToAirStart + LastProxToAirDuration) * 16 + DELAY_ARM2AIR_AS_TAG,
- par);
- return res;
-}
-int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par) {
- return EmSendCmdParEx(resp, respLen, par, false);
-}
-int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision) {
- CodeIso14443aAsTagPar(resp, respLen, par, collision);
- int res = EmSendCmd14443aRaw(ToSend, ToSendMax);
- // do the tracing for the previous reader request and this tag answer:
- EmLogTrace(Uart.output,
- Uart.len,
- Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG,
- Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG,
- Uart.parity,
- resp,
- respLen,
- LastTimeProxToAirStart * 16 + DELAY_ARM2AIR_AS_TAG,
- (LastTimeProxToAirStart + LastProxToAirDuration) * 16 + DELAY_ARM2AIR_AS_TAG,
- par);
- return res;
-}
-int EmSendCmd(uint8_t *resp, uint16_t respLen) {
- return EmSendCmdEx(resp, respLen, false);
-}
-int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision) {
- uint8_t par[MAX_PARITY_SIZE] = {0x00};
- GetParity(resp, respLen, par);
- return EmSendCmdParEx(resp, respLen, par, collision);
-}
-
-int EmSendPrecompiledCmd(tag_response_info_t *p_response) {
- int ret = EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n);
- // do the tracing for the previous reader request and this tag answer:
- uint8_t par[MAX_PARITY_SIZE] = {0x00};
- GetParity(p_response->response, p_response->response_n, par);
-
- EmLogTrace(Uart.output,
- Uart.len,
- Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG,
- Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG,
- Uart.parity,
- p_response->response,
- p_response->response_n,
- LastTimeProxToAirStart * 16 + DELAY_ARM2AIR_AS_TAG,
- (LastTimeProxToAirStart + p_response->ProxToAirDuration) * 16 + DELAY_ARM2AIR_AS_TAG,
- par);
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("response_info->response %02X", p_response->response);
- Dbprintf("response_info->response_n %02X", p_response->response_n);
- Dbprintf("response_info->par %02X", &(p_response->par));
- }
-
- return ret;
-}
-
-bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime,
- uint32_t reader_EndTime, uint8_t *reader_Parity, uint8_t *tag_data,
- uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) {
-
- // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from
- // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp.
- // with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated:
-
- uint16_t reader_modlen = reader_EndTime - reader_StartTime;
- uint16_t approx_fdt = tag_StartTime - reader_EndTime;
- uint16_t exact_fdt = (approx_fdt - 20 + 32) / 64 * 64 + 20;
- reader_EndTime = tag_StartTime - exact_fdt;
- reader_StartTime = reader_EndTime - reader_modlen;
-
- if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, true))
- return false;
- else
- return (!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false));
-
-}
-
-//-----------------------------------------------------------------------------
-// Kovio - Thinfilm barcode. TAG-TALK-FIRST -
-// Wait a certain time for tag response
-// If a response is captured return TRUE
-// If it takes too long return FALSE
-//-----------------------------------------------------------------------------
-bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
-
- if (!hf_field_active)
- return false;
-
- // Set FPGA mode to "reader listen mode", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is on with the appropriate LED
- LED_D_ON();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
-
- // Now get the answer from the card
- Demod14aInit(receivedResponse, NULL);
-
- // clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint32_t receive_timer = GetTickCount();
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- if (ManchesterDecoding_Thinfilm(b)) {
- *received_len = Demod.len;
- // log
- LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false);
- return true;
- }
- }
-
- if (GetTickCountDelta(receive_timer) > 100)
- break;
- }
- *received_len = Demod.len;
- // log
- LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false);
- return false;
-}
-
-
-//-----------------------------------------------------------------------------
-// Wait a certain time for tag response
-// If a response is captured return TRUE
-// If it takes too long return FALSE
-//-----------------------------------------------------------------------------
-static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
- uint32_t c = 0;
-
- if (!hf_field_active)
- return false;
-
- // Set FPGA mode to "reader listen mode", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is on with the appropriate LED
- LED_D_ON();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
-
- // Now get the answer from the card
- Demod14aInit(receivedResponse, receivedResponsePar);
-
- // clear RXRDY:
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
-
- uint32_t timeout = iso14a_get_timeout();
- uint32_t receive_timer = GetTickCount();
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- if (ManchesterDecoding(b, offset, 0)) {
- NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FRAME_DELAY_TIME_PICC_TO_PCD);
- return true;
- } else if (c++ > timeout && Demod.state == DEMOD_14A_UNSYNCD) {
- return false;
- }
- }
-
- // timeout already in ms + 100ms guard time
- if (GetTickCountDelta(receive_timer) > timeout + 100)
- break;
- }
- return false;
-}
-
-void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing) {
-
- CodeIso14443aBitsAsReaderPar(frame, bits, par);
- // Send command to tag
- TransmitFor14443a(ToSend, ToSendMax, timing);
- if (trigger) LED_A_ON();
-
- LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart << 4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration) << 4) + DELAY_ARM2AIR_AS_READER, par, true);
-}
-
-void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing) {
- ReaderTransmitBitsPar(frame, len * 8, par, timing);
-}
-
-void ReaderTransmitBits(uint8_t *frame, uint16_t len, uint32_t *timing) {
- // Generate parity and redirect
- uint8_t par[MAX_PARITY_SIZE] = {0x00};
- GetParity(frame, len / 8, par);
- ReaderTransmitBitsPar(frame, len, par, timing);
-}
-
-void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) {
- // Generate parity and redirect
- uint8_t par[MAX_PARITY_SIZE] = {0x00};
- GetParity(frame, len, par);
- ReaderTransmitBitsPar(frame, len * 8, par, timing);
-}
-
-int ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) {
- if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset))
- return false;
- LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
- return Demod.len;
-}
-
-int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
- if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0))
- return false;
- LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
- return Demod.len;
-}
-
-
-// This function misstreats the ISO 14443a anticollision procedure.
-// by fooling the reader there is a collision and forceing the reader to
-// increase the uid bytes. The might be an overflow, DoS will occure.
-void iso14443a_antifuzz(uint32_t flags) {
-
- // We need to listen to the high-frequency, peak-detected path.
- iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
-
- BigBuf_free_keep_EM();
- clear_trace();
- set_tracing(true);
-
- int len = 0;
-
- // allocate buffers:
- uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE);
- uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
- uint8_t *resp = BigBuf_malloc(20);
-
- memset(resp, 0xFF, 20);
-
- LED_A_ON();
- for (;;) {
- WDT_HIT();
-
- // Clean read command buffer
- if (!GetIso14443aCommandFromReader(received, receivedPar, &len)) {
- Dbprintf("Anti-fuzz stopped. Trace length: %d ", BigBuf_get_traceLen());
- break;
- }
- if (received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) {
- resp[0] = 0x04;
- resp[1] = 0x00;
-
- if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
- resp[0] = 0x44;
- }
-
- EmSendCmd(resp, 2);
- continue;
- }
-
- // Received request for UID (cascade 1)
- //if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) {
- if (received[1] >= 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) {
- resp[0] = 0xFF;
- resp[1] = 0xFF;
- resp[2] = 0xFF;
- resp[3] = 0xFF;
- resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3];
- colpos = 0;
-
- if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
- resp[0] = 0x88;
- colpos = 8;
- }
-
- EmSendCmdEx(resp, 5, true);
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("ANTICOLL or SELECT %x", received[1]);
- LED_D_INV();
-
- continue;
- } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2)
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("ANTICOLL or SELECT_2");
- } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1)
- } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2)
- } else {
- Dbprintf("unknown command %x", received[0]);
- }
- }
-
- reply_old(CMD_ACK, 1, 0, 0, 0, 0);
- switch_off();
- BigBuf_free_keep_EM();
-}
-
-static void iso14a_set_ATS_times(uint8_t *ats) {
-
- if (ats[0] > 1) { // there is a format byte T0
- if ((ats[1] & 0x20) == 0x20) { // there is an interface byte TB(1)
- uint8_t tb1;
- if ((ats[1] & 0x10) == 0x10) { // there is an interface byte TA(1) preceding TB(1)
- tb1 = ats[3];
- } else {
- tb1 = ats[2];
- }
- uint8_t fwi = (tb1 & 0xf0) >> 4; // frame waiting time integer (FWI)
- if (fwi != 15) {
- uint32_t fwt = 256 * 16 * (1 << fwi); // frame waiting time (FWT) in 1/fc
- iso14a_set_timeout(fwt / (8 * 16));
- }
- uint8_t sfgi = tb1 & 0x0f; // startup frame guard time integer (SFGI)
- if (sfgi != 0 && sfgi != 15) {
- uint32_t sfgt = 256 * 16 * (1 << sfgi); // startup frame guard time (SFGT) in 1/fc
- NextTransferTime = MAX(NextTransferTime, Demod.endTime + (sfgt - DELAY_AIR2ARM_AS_READER - DELAY_ARM2AIR_AS_READER) / 16);
- }
- }
- }
-}
-
-static int GetATQA(uint8_t *resp, uint8_t *resp_par) {
-
-#define WUPA_RETRY_TIMEOUT 10 // 10ms
- uint8_t wupa[] = { ISO14443A_CMD_WUPA }; // 0x26 - REQA 0x52 - WAKE-UP
-
- uint32_t save_iso14a_timeout = iso14a_get_timeout();
- iso14a_set_timeout(1236 / (16 * 8) + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
-
- uint32_t start_time = GetTickCount();
- int len;
-
- // we may need several tries if we did write an unknown command or a wrong authentication before...
- do {
- // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
- ReaderTransmitBitsPar(wupa, 7, NULL, NULL);
- // Receive the ATQA
- len = ReaderReceive(resp, resp_par);
- } while (len == 0 && GetTickCountDelta(start_time) <= WUPA_RETRY_TIMEOUT);
-
- iso14a_set_timeout(save_iso14a_timeout);
- return len;
-}
-
-// performs iso14443a anticollision (optional) and card select procedure
-// fills the uid and cuid pointer unless NULL
-// fills the card info record unless NULL
-// if anticollision is false, then the UID must be provided in uid_ptr[]
-// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
-// requests ATS unless no_rats is true
-int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
-
- uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
- uint8_t resp_par[MAX_PARITY_SIZE] = {0};
-
- uint8_t sak = 0x04; // cascade uid
- int cascade_level = 0;
-
- if (p_card) {
- p_card->uidlen = 0;
- memset(p_card->uid, 0, 10);
- p_card->ats_len = 0;
- }
-
- if (!GetATQA(resp, resp_par)) {
- return 0;
- }
-
- if (p_card) {
- p_card->atqa[0] = resp[0];
- p_card->atqa[1] = resp[1];
- }
-
- if (anticollision) {
- // clear uid
- if (uid_ptr)
- memset(uid_ptr, 0, 10);
- }
-
- // check for proprietary anticollision:
- if ((resp[0] & 0x1F) == 0) return 3;
-
- // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
- // which case we need to make a cascade 2 request and select - this is a long UID
- // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
- for (; sak & 0x04; cascade_level++) {
- // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
- uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
- uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- uint8_t uid_resp[4] = {0};
- sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
-
- if (anticollision) {
- // SELECT_ALL
- ReaderTransmit(sel_all, sizeof(sel_all), NULL);
- if (!ReaderReceive(resp, resp_par)) return 0;
-
- if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
- memset(uid_resp, 0, 4);
- uint16_t uid_resp_bits = 0;
- uint16_t collision_answer_offset = 0;
- // anti-collision-loop:
- while (Demod.collisionPos) {
- Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
- for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
- uint16_t UIDbit = (resp[i / 8] >> (i % 8)) & 0x01;
- uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8);
- }
- uid_resp[uid_resp_bits / 8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
- uid_resp_bits++;
- // construct anticollosion command:
- sel_uid[1] = ((2 + uid_resp_bits / 8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
- for (uint16_t i = 0; i <= uid_resp_bits / 8; i++) {
- sel_uid[2 + i] = uid_resp[i];
- }
- collision_answer_offset = uid_resp_bits % 8;
- ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
- if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
- }
- // finally, add the last bits and BCC of the UID
- for (uint16_t i = collision_answer_offset; i < (Demod.len - 1) * 8; i++, uid_resp_bits++) {
- uint16_t UIDbit = (resp[i / 8] >> (i % 8)) & 0x01;
- uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8);
- }
-
- } else { // no collision, use the response to SELECT_ALL as current uid
- memcpy(uid_resp, resp, 4);
- }
-
- } else {
- if (cascade_level < num_cascades - 1) {
- uid_resp[0] = 0x88;
- memcpy(uid_resp + 1, uid_ptr + cascade_level * 3, 3);
- } else {
- memcpy(uid_resp, uid_ptr + cascade_level * 3, 4);
- }
- }
- size_t uid_resp_len = 4;
-
- // calculate crypto UID. Always use last 4 Bytes.
- if (cuid_ptr)
- *cuid_ptr = bytes_to_num(uid_resp, 4);
-
- // Construct SELECT UID command
- sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
- memcpy(sel_uid + 2, uid_resp, 4); // the UID received during anticollision, or the provided UID
- sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
- AddCrc14A(sel_uid, 7); // calculate and add CRC
- ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
-
- // Receive the SAK
- if (!ReaderReceive(resp, resp_par)) return 0;
-
- sak = resp[0];
-
- // Test if more parts of the uid are coming
- if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
- // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
- // http://www.nxp.com/documents/application_note/AN10927.pdf
- uid_resp[0] = uid_resp[1];
- uid_resp[1] = uid_resp[2];
- uid_resp[2] = uid_resp[3];
- uid_resp_len = 3;
- }
-
- if (uid_ptr && anticollision)
- memcpy(uid_ptr + (cascade_level * 3), uid_resp, uid_resp_len);
-
- if (p_card) {
- memcpy(p_card->uid + (cascade_level * 3), uid_resp, uid_resp_len);
- p_card->uidlen += uid_resp_len;
- }
- }
-
- if (p_card) {
- p_card->sak = sak;
- }
-
- // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
- if ((sak & 0x20) == 0) return 2;
-
- // RATS, Request for answer to select
- if (!no_rats) {
- uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
- AddCrc14A(rats, 2);
- ReaderTransmit(rats, sizeof(rats), NULL);
- int len = ReaderReceive(resp, resp_par);
-
- if (!len) return 0;
-
- if (p_card) {
- memcpy(p_card->ats, resp, sizeof(p_card->ats));
- p_card->ats_len = len;
- }
-
- // reset the PCB block number
- iso14_pcb_blocknum = 0;
-
- // set default timeout and delay next transfer based on ATS
- iso14a_set_ATS_times(resp);
- }
- return 1;
-}
-
-int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
- uint8_t resp[5] = {0}; // theoretically. A usual RATS will be much smaller
- uint8_t resp_par[1] = {0};
- uint8_t uid_resp[4] = {0};
-
- uint8_t sak = 0x04; // cascade uid
- int cascade_level = 0;
-
- if (!GetATQA(resp, resp_par)) {
- return 0;
- }
-
- // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
- // which case we need to make a cascade 2 request and select - this is a long UID
- // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
- for (; sak & 0x04; cascade_level++) {
- uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
- uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
- sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
-
- if (cascade_level < num_cascades - 1) {
- uid_resp[0] = 0x88;
- memcpy(uid_resp + 1, uid_ptr + cascade_level * 3, 3);
- } else {
- memcpy(uid_resp, uid_ptr + cascade_level * 3, 4);
- }
-
- // Construct SELECT UID command
- //sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
- memcpy(sel_uid + 2, uid_resp, 4); // the UID received during anticollision, or the provided UID
- sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
- AddCrc14A(sel_uid, 7); // calculate and add CRC
- ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
-
- // Receive the SAK
- if (!ReaderReceive(resp, resp_par)) return 0;
-
- sak = resp[0];
-
- // Test if more parts of the uid are coming
- if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
- // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
- // http://www.nxp.com/documents/application_note/AN10927.pdf
- uid_resp[0] = uid_resp[1];
- uid_resp[1] = uid_resp[2];
- uid_resp[2] = uid_resp[3];
- }
- }
- return 1;
-}
-
-void iso14443a_setup(uint8_t fpga_minor_mode) {
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- // Set up the synchronous serial port
- FpgaSetupSsc();
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- LED_D_OFF();
- // Signal field is on with the appropriate LED
- if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
- LED_D_ON();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
- SpinDelay(100);
-
- // Start the timer
- StartCountSspClk();
-
- // Prepare the demodulation functions
- Demod14aReset();
- Uart14aReset();
- NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER;
- iso14a_set_timeout(1060); // 106 * 10ms default
-
- hf_field_active = true;
-}
-
-
-void hf_field_off(void) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- hf_field_active = false;
-}
-
-/* Peter Fillmore 2015
-Added card id field to the function
- info from ISO14443A standard
-b1 = Block Number
-b2 = RFU (always 1)
-b3 = depends on block
-b4 = Card ID following if set to 1
-b5 = depends on block type
-b6 = depends on block type
-b7,b8 = block type.
-Coding of I-BLOCK:
-b8 b7 b6 b5 b4 b3 b2 b1
-0 0 0 x x x 1 x
-b5 = chaining bit
-Coding of R-block:
-b8 b7 b6 b5 b4 b3 b2 b1
-1 0 1 x x 0 1 x
-b5 = ACK/NACK
-Coding of S-block:
-b8 b7 b6 b5 b4 b3 b2 b1
-1 1 x x x 0 1 0
-b5,b6 = 00 - DESELECT
- 11 - WTX
-*/
-int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res) {
- uint8_t parity[MAX_PARITY_SIZE] = {0x00};
- uint8_t real_cmd[cmd_len + 4];
-
- if (cmd_len) {
- // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02
- real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00)
- if (send_chaining) {
- real_cmd[0] |= 0x10;
- }
- // put block number into the PCB
- real_cmd[0] |= iso14_pcb_blocknum;
- memcpy(real_cmd + 1, cmd, cmd_len);
- } else {
- // R-block. ACK
- real_cmd[0] = 0xA2; // r-block + ACK
- real_cmd[0] |= iso14_pcb_blocknum;
- }
- AddCrc14A(real_cmd, cmd_len + 1);
-
- ReaderTransmit(real_cmd, cmd_len + 3, NULL);
-
- size_t len = ReaderReceive(data, parity);
- uint8_t *data_bytes = (uint8_t *) data;
-
- if (!len) {
- return 0; //DATA LINK ERROR
- } else {
- // S-Block WTX
- while (len && ((data_bytes[0] & 0xF2) == 0xF2)) {
- uint32_t save_iso14a_timeout = iso14a_get_timeout();
- // temporarily increase timeout
- iso14a_set_timeout(MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT));
- // Transmit WTX back
- // byte1 - WTXM [1..59]. command FWT=FWT*WTXM
- data_bytes[1] = data_bytes[1] & 0x3f; // 2 high bits mandatory set to 0b
- // now need to fix CRC.
- AddCrc14A(data_bytes, len - 2);
- // transmit S-Block
- ReaderTransmit(data_bytes, len, NULL);
- // retrieve the result again (with increased timeout)
- len = ReaderReceive(data, parity);
- data_bytes = data;
- // restore timeout
- iso14a_set_timeout(save_iso14a_timeout);
- }
-
- // if we received an I- or R(ACK)-Block with a block number equal to the
- // current block number, toggle the current block number
- if (len >= 3 // PCB+CRC = 3 bytes
- && ((data_bytes[0] & 0xC0) == 0 // I-Block
- || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
- && (data_bytes[0] & 0x01) == iso14_pcb_blocknum) { // equal block numbers
- iso14_pcb_blocknum ^= 1;
- }
-
- // if we received I-block with chaining we need to write ACK and read another block of data
- if (res)
- *res = data_bytes[0];
-
- // crc check
- if (len >= 3 && !CheckCrc14A(data_bytes, len)) {
- return -1;
- }
-
- }
-
- if (len) {
- // cut frame byte
- len -= 1;
- // memmove(data_bytes, data_bytes + 1, len);
- for (int i = 0; i < len; i++)
- data_bytes[i] = data_bytes[i + 1];
- }
-
- return len;
-}
-
-//-----------------------------------------------------------------------------
-// Read an ISO 14443a tag. Send out commands and store answers.
-//-----------------------------------------------------------------------------
-// arg0 iso_14a flags
-// arg1 high :: number of bits, if you want to write 7bits etc
-// low :: len of commandbytes
-// arg2 timeout
-// d.asBytes command bytes to write
-void ReaderIso14443a(PacketCommandNG *c) {
- iso14a_command_t param = c->oldarg[0];
- size_t len = c->oldarg[1] & 0xffff;
- size_t lenbits = c->oldarg[1] >> 16;
- uint32_t timeout = c->oldarg[2];
- uint8_t *cmd = c->data.asBytes;
- uint32_t arg0;
- uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00};
- uint8_t par[MAX_PARITY_SIZE] = {0x00};
-
- if ((param & ISO14A_CONNECT))
- clear_trace();
-
- set_tracing(true);
-
- if ((param & ISO14A_REQUEST_TRIGGER))
- iso14a_set_trigger(true);
-
- if ((param & ISO14A_CONNECT)) {
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- // notify client selecting status.
- // if failed selecting, turn off antenna and quite.
- if (!(param & ISO14A_NO_SELECT)) {
- iso14a_card_select_t *card = (iso14a_card_select_t *)buf;
- arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS);
- FpgaDisableTracing();
-
- reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
- if (arg0 == 0)
- goto OUT;
- }
- }
-
- if ((param & ISO14A_SET_TIMEOUT))
- iso14a_set_timeout(timeout);
-
- if ((param & ISO14A_APDU)) {
- uint8_t res;
- arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res);
- FpgaDisableTracing();
-
- reply_old(CMD_ACK, arg0, res, 0, buf, sizeof(buf));
- }
-
- if ((param & ISO14A_RAW)) {
-
- if ((param & ISO14A_APPEND_CRC)) {
- // Don't append crc on empty bytearray...
- if (len > 0) {
- if ((param & ISO14A_TOPAZMODE))
- AddCrc14B(cmd, len);
- else
- AddCrc14A(cmd, len);
-
- len += 2;
- if (lenbits) lenbits += 16;
- }
- }
-
- if (lenbits > 0) { // want to write a specific number of bits (e.g. short commands)
- if ((param & ISO14A_TOPAZMODE)) {
- int bits_to_send = lenbits;
- uint16_t i = 0;
- ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity
- bits_to_send -= 7;
- while (bits_to_send > 0) {
- ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity
- bits_to_send -= 8;
- }
- } else {
- GetParity(cmd, lenbits / 8, par);
- ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity
- }
- } else { // want to write complete bytes only
- if ((param & ISO14A_TOPAZMODE)) {
- uint16_t i = 0;
- ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy
- while (i < len) {
- ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy
- }
- } else {
- ReaderTransmit(cmd, len, NULL); // 8 bits, odd parity
- }
- }
- arg0 = ReaderReceive(buf, par);
- FpgaDisableTracing();
-
- reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
- }
-
- if ((param & ISO14A_REQUEST_TRIGGER))
- iso14a_set_trigger(false);
-
- if ((param & ISO14A_NO_DISCONNECT))
- return;
-
-OUT:
- hf_field_off();
- set_tracing(false);
-}
-
-// Determine the distance between two nonces.
-// Assume that the difference is small, but we don't know which is first.
-// Therefore try in alternating directions.
-int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
-
- if (nt1 == nt2) return 0;
-
- uint32_t nttmp1 = nt1;
- uint32_t nttmp2 = nt2;
-
- for (uint16_t i = 1; i < 32768; i++) {
- nttmp1 = prng_successor(nttmp1, 1);
- if (nttmp1 == nt2) return i;
-
- nttmp2 = prng_successor(nttmp2, 1);
- if (nttmp2 == nt1) return -i;
- }
-
- return (-99999); // either nt1 or nt2 are invalid nonces
-}
-
-
-#define PRNG_SEQUENCE_LENGTH (1 << 16)
-#define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
-#define MAX_SYNC_TRIES 32
-
-//-----------------------------------------------------------------------------
-// Recover several bits of the cypher stream. This implements (first stages of)
-// the algorithm described in "The Dark Side of Security by Obscurity and
-// Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime"
-// (article by Nicolas T. Courtois, 2009)
-//-----------------------------------------------------------------------------
-void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- uint8_t mf_auth[] = { keytype, block, 0x00, 0x00 };
- uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t par_list[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t ks_list[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
- uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
- uint8_t nt_diff = 0;
-
- uint32_t nt = 0, previous_nt = 0, cuid = 0;
- uint32_t sync_time = GetCountSspClk() & 0xfffffff8;
-
- int32_t catch_up_cycles = 0;
- int32_t last_catch_up = 0;
- int32_t isOK = 0;
-
- uint16_t elapsed_prng_sequences = 1;
- uint16_t consecutive_resyncs = 0;
- uint16_t unexpected_random = 0;
- uint16_t sync_tries = 0;
-
- bool have_uid = false;
- uint8_t cascade_levels = 0;
-
- // static variables here, is re-used in the next call
- static uint32_t nt_attacked = 0;
- static int32_t sync_cycles = 0;
- static uint8_t par_low = 0;
- static uint8_t mf_nr_ar3 = 0;
-
- int return_status = PM3_SUCCESS;
-
- AddCrc14A(mf_auth, 2);
-
- if (first_try) {
- sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
- nt_attacked = 0;
- mf_nr_ar3 = 0;
- par_low = 0;
- } else {
- // we were unsuccessful on a previous call.
- // Try another READER nonce (first 3 parity bits remain the same)
- mf_nr_ar3++;
- mf_nr_ar[3] = mf_nr_ar3;
- par[0] = par_low;
- }
-
- LED_C_ON();
- uint16_t checkbtn_cnt = 0;
- uint16_t i;
- for (i = 0; true; ++i) {
-
- bool received_nack = false;
-
- WDT_HIT();
-
- // Test if the action was cancelled
- if (checkbtn_cnt == 1000) {
- if (BUTTON_PRESS() || data_available()) {
- isOK = -1;
- return_status = PM3_EOPABORTED;
- break;
- }
- checkbtn_cnt = 0;
- }
- ++checkbtn_cnt;
-
- // this part is from Piwi's faster nonce collecting part in Hardnested.
- if (!have_uid) { // need a full select cycle to get the uid first
- iso14a_card_select_t card_info;
- if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (ALL)");
- continue;
- }
- switch (card_info.uidlen) {
- case 4 :
- cascade_levels = 1;
- break;
- case 7 :
- cascade_levels = 2;
- break;
- case 10:
- cascade_levels = 3;
- break;
- default:
- break;
- }
- have_uid = true;
- } else { // no need for anticollision. We can directly select the card
- if (!iso14443a_fast_select_card(uid, cascade_levels)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (UID)");
- continue;
- }
- }
-
- elapsed_prng_sequences = 1;
-
- // Sending timeslot of ISO14443a frame
- sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
- catch_up_cycles = 0;
-
-#define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle
-
- // if we missed the sync time already or are about to miss it, advance to the next nonce repeat
- while (sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) {
- ++elapsed_prng_sequences;
- sync_time = (sync_time & 0xfffffff8) + sync_cycles;
- }
-
- // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked)
- ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
-
- // Receive the (4 Byte) "random" TAG nonce
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar))
- continue;
-
- previous_nt = nt;
- nt = bytes_to_num(receivedAnswer, 4);
-
- // Transmit reader nonce with fake par
- ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
-
- // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
- int resp_res = ReaderReceive(receivedAnswer, receivedAnswerPar);
- if (resp_res == 1)
- received_nack = true;
- else if (resp_res == 4) {
- // did we get lucky and got our dummykey to be valid?
- // however we dont feed key w uid it the prng..
- isOK = -6;
- break;
- }
-
-
- // we didn't calibrate our clock yet,
- // iceman: has to be calibrated every time.
- if (previous_nt && !nt_attacked) {
-
- int nt_distance = dist_nt(previous_nt, nt);
-
- // if no distance between, then we are in sync.
- if (nt_distance == 0) {
- nt_attacked = nt;
- } else {
- if (nt_distance == -99999) { // invalid nonce received
- unexpected_random++;
- if (unexpected_random > MAX_UNEXPECTED_RANDOM) {
- isOK = -3; // Card has an unpredictable PRNG. Give up
- break;
- } else {
- continue; // continue trying...
- }
- }
-
- if (++sync_tries > MAX_SYNC_TRIES) {
- isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly
- break;
- }
-
- sync_cycles = (sync_cycles - nt_distance) / elapsed_prng_sequences;
-
- // no negative sync_cycles
- if (sync_cycles <= 0) sync_cycles += PRNG_SEQUENCE_LENGTH;
-
- // reset sync_cycles
- if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2) {
- sync_cycles = PRNG_SEQUENCE_LENGTH;
- sync_time = GetCountSspClk() & 0xfffffff8;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles);
-
- LED_B_OFF();
- continue;
- }
- }
- LED_B_OFF();
-
- if ((nt != nt_attacked) && nt_attacked) { // we somehow lost sync. Try to catch up again...
-
- catch_up_cycles = -dist_nt(nt_attacked, nt);
- if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one.
- catch_up_cycles = 0;
- continue;
- }
- // average?
- catch_up_cycles /= elapsed_prng_sequences;
-
- if (catch_up_cycles == last_catch_up) {
- consecutive_resyncs++;
- } else {
- last_catch_up = catch_up_cycles;
- consecutive_resyncs = 0;
- }
-
- if (consecutive_resyncs < 3) {
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs);
- }
- } else {
- sync_cycles += catch_up_cycles;
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles);
-
- last_catch_up = 0;
- catch_up_cycles = 0;
- consecutive_resyncs = 0;
- }
- continue;
- }
-
- // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
- if (received_nack) {
- catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer
-
- if (nt_diff == 0)
- par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change
-
- par_list[nt_diff] = reflect8(par[0]);
- ks_list[nt_diff] = receivedAnswer[0] ^ 0x05; // xor with NACK value to get keystream
-
- // Test if the information is complete
- if (nt_diff == 0x07) {
- isOK = 1;
- break;
- }
-
- nt_diff = (nt_diff + 1) & 0x07;
- mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5);
- par[0] = par_low;
-
- } else {
- // No NACK.
- if (nt_diff == 0 && first_try) {
- par[0]++;
- if (par[0] == 0) { // tried all 256 possible parities without success. Card doesn't write NACK.
- isOK = -2;
- break;
- }
- } else {
- // Why this?
- par[0] = ((par[0] & 0x1F) + 1) | par_low;
- }
- }
-
- // reset the resyncs since we got a complete transaction on right time.
- consecutive_resyncs = 0;
- } // end for loop
-
- mf_nr_ar[3] &= 0x1F;
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Number of sent auth requests: %u", i);
-
- FpgaDisableTracing();
-
- struct {
- int32_t isOK;
- uint8_t cuid[4];
- uint8_t nt[4];
- uint8_t par_list[8];
- uint8_t ks_list[8];
- uint8_t nr[4];
- uint8_t ar[4];
- } PACKED payload;
-
- payload.isOK = isOK;
- num_to_bytes(cuid, 4, payload.cuid);
- num_to_bytes(nt, 4, payload.nt);
- memcpy(payload.par_list, par_list, sizeof(payload.par_list));
- memcpy(payload.ks_list, ks_list, sizeof(payload.ks_list));
- memcpy(payload.nr, mf_nr_ar, sizeof(payload.nr));
- memcpy(payload.ar, mf_nr_ar + 4, sizeof(payload.ar));
-
- reply_ng(CMD_HF_MIFARE_READER, return_status, (uint8_t *)&payload, sizeof(payload));
-
- hf_field_off();
- set_tracing(false);
-}
-
-/*
- * Mifare Classic NACK-bug detection
- * Thanks to @doegox for the feedback and new approaches.
-*/
-void DetectNACKbug(void) {
- uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B};
- uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
- uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
-
- uint32_t nt = 0, previous_nt = 0, nt_attacked = 0, cuid = 0;
- int32_t catch_up_cycles = 0, last_catch_up = 0;
- uint8_t cascade_levels = 0, num_nacks = 0, isOK = 0;
- uint16_t elapsed_prng_sequences = 1;
- uint16_t consecutive_resyncs = 0;
- uint16_t unexpected_random = 0;
- uint16_t sync_tries = 0;
- uint32_t sync_time = 0;
- bool have_uid = false;
-
- int32_t status = PM3_SUCCESS;
-
- // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
- int32_t sync_cycles = PRNG_SEQUENCE_LENGTH;
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
- iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
-
- sync_time = GetCountSspClk() & 0xfffffff8;
-
- LED_C_ON();
- uint16_t checkbtn_cnt = 0;
-
- uint16_t i;
- for (i = 1; true; ++i) {
-
- bool received_nack = false;
-
- // Cards always leaks a NACK, no matter the parity
- if ((i == 10) && (num_nacks == i - 1)) {
- isOK = 2;
- break;
- }
-
- WDT_HIT();
-
- // Test if the action was cancelled
- if (checkbtn_cnt == 1000) {
- if (BUTTON_PRESS() || data_available()) {
- status = PM3_EOPABORTED;
- break;
- }
- checkbtn_cnt = 0;
- }
- ++checkbtn_cnt;
-
- // this part is from Piwi's faster nonce collecting part in Hardnested.
- if (!have_uid) { // need a full select cycle to get the uid first
- iso14a_card_select_t card_info;
- if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (ALL)");
- i = 0;
- continue;
- }
- switch (card_info.uidlen) {
- case 4 :
- cascade_levels = 1;
- break;
- case 7 :
- cascade_levels = 2;
- break;
- case 10:
- cascade_levels = 3;
- break;
- default:
- i = 0;
- have_uid = false;
- continue;
- }
- have_uid = true;
- } else { // no need for anticollision. We can directly select the card
- if (!iso14443a_fast_select_card(uid, cascade_levels)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (UID)");
- i = 0;
- have_uid = false;
- continue;
- }
- }
-
- elapsed_prng_sequences = 1;
-
- // Sending timeslot of ISO14443a frame
- sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
- catch_up_cycles = 0;
-
- // if we missed the sync time already, advance to the next nonce repeat
- while (GetCountSspClk() > sync_time) {
- ++elapsed_prng_sequences;
- sync_time = (sync_time & 0xfffffff8) + sync_cycles;
- }
-
- // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked)
- ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
-
- // Receive the (4 Byte) "random" TAG nonce
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar))
- continue;
-
- previous_nt = nt;
- nt = bytes_to_num(receivedAnswer, 4);
-
- // Transmit reader nonce with fake par
- ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
-
- // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
- if (ReaderReceive(receivedAnswer, receivedAnswerPar)) {
- received_nack = true;
- num_nacks++;
- // ALWAYS leak Detection. Well, we could be lucky and get a response nack on first try.
- if (i == num_nacks) {
- continue;
- }
- }
-
- // we didn't calibrate our clock yet,
- // iceman: has to be calibrated every time.
- if (previous_nt && !nt_attacked) {
-
- int nt_distance = dist_nt(previous_nt, nt);
-
- // if no distance between, then we are in sync.
- if (nt_distance == 0) {
- nt_attacked = nt;
- } else {
- if (nt_distance == -99999) { // invalid nonce received
- unexpected_random++;
- if (unexpected_random > MAX_UNEXPECTED_RANDOM) {
- // Card has an unpredictable PRNG. Give up
- isOK = 98;
- break;
- } else {
- if (sync_cycles <= 0) {
- sync_cycles += PRNG_SEQUENCE_LENGTH;
- }
- continue;
- }
- }
-
- if (++sync_tries > MAX_SYNC_TRIES) {
- isOK = 97; // Card's PRNG runs at an unexpected frequency or resets unexpectedly
- break;
- }
-
- sync_cycles = (sync_cycles - nt_distance) / elapsed_prng_sequences;
-
- if (sync_cycles <= 0)
- sync_cycles += PRNG_SEQUENCE_LENGTH;
-
- if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2) {
- isOK = 96; // Card's PRNG runs at an unexpected frequency or resets unexpectedly
- break;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles);
-
- continue;
- }
- }
-
- if ((nt != nt_attacked) && nt_attacked) {
- // we somehow lost sync. Try to catch up again...
- catch_up_cycles = -dist_nt(nt_attacked, nt);
-
- if (catch_up_cycles == 99999) {
- // invalid nonce received. Don't resync on that one.
- catch_up_cycles = 0;
- continue;
- }
- // average?
- catch_up_cycles /= elapsed_prng_sequences;
-
- if (catch_up_cycles == last_catch_up) {
- consecutive_resyncs++;
- } else {
- last_catch_up = catch_up_cycles;
- consecutive_resyncs = 0;
- }
-
- if (consecutive_resyncs < 3) {
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs);
- }
- } else {
- sync_cycles += catch_up_cycles;
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles);
- Dbprintf("nt [%08x] attacted [%08x]", nt, nt_attacked);
- }
- last_catch_up = 0;
- catch_up_cycles = 0;
- consecutive_resyncs = 0;
- }
- continue;
- }
-
- // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
- if (received_nack)
- catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer
-
- // we are testing all 256 possibilities.
- par[0]++;
-
- // tried all 256 possible parities without success.
- if (par[0] == 0) {
- // did we get one NACK?
- if (num_nacks == 1)
- isOK = 1;
- break;
- }
-
- // reset the resyncs since we got a complete transaction on right time.
- consecutive_resyncs = 0;
- } // end for loop
-
- // num_nacks = number of nacks recieved. should be only 1. if not its a clone card which always sends NACK (parity == 0) ?
- // i = number of authentications sent. Not always 256, since we are trying to sync but close to it.
- FpgaDisableTracing();
-
- uint8_t *data = BigBuf_malloc(4);
- data[0] = isOK;
- data[1] = num_nacks;
- num_to_bytes(i, 2, data + 2);
- reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4);
-
- BigBuf_free();
- hf_field_off();
- set_tracing(false);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443a.h b/pm3rdv4rrg/src/main/cpp/armsrc/iso14443a.h
deleted file mode 100644
index 33e5b299..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443a.h
+++ /dev/null
@@ -1,148 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443 type A.
-//-----------------------------------------------------------------------------
-
-#ifndef __ISO14443A_H
-#define __ISO14443A_H
-
-#include "common.h"
-#include "mifare.h" // struct
-#include "pm3_cmd.h"
-#include "crc16.h" // compute_crc
-
-// When the PM acts as tag and is receiving it takes
-// 2 ticks delay in the RF part (for the first falling edge),
-// 3 ticks for the A/D conversion,
-// 8 ticks on average until the start of the SSC transfer,
-// 8 ticks until the SSC samples the first data
-// 7*16 ticks to complete the transfer from FPGA to ARM
-// 8 ticks until the next ssp_clk rising edge
-// 4*16 ticks until we measure the time
-// - 8*16 ticks because we measure the time of the previous transfer
-#define DELAY_AIR2ARM_AS_TAG (2 + 3 + 8 + 8 + 7*16 + 8 + 4*16 - 8*16)
-
-typedef struct {
- enum {
- DEMOD_14A_UNSYNCD,
- // DEMOD_14A_HALF_SYNCD,
- // DEMOD_14A_MOD_FIRST_HALF,
- // DEMOD_14A_NOMOD_FIRST_HALF,
- DEMOD_14A_MANCHESTER_DATA
- } state;
- uint16_t twoBits;
- uint16_t highCnt;
- uint16_t bitCount;
- uint16_t collisionPos;
- uint16_t syncBit;
- uint8_t parityBits;
- uint8_t parityLen;
- uint16_t shiftReg;
- uint16_t samples;
- uint16_t len;
- uint32_t startTime, endTime;
- uint8_t *output;
- uint8_t *parity;
-} tDemod14a;
-/*
-typedef enum {
- MOD_NOMOD = 0,
- MOD_SECOND_HALF,
- MOD_FIRST_HALF,
- MOD_BOTH_HALVES
- } Modulation_t;
-*/
-
-typedef struct {
- enum {
- STATE_14A_UNSYNCD,
- STATE_14A_START_OF_COMMUNICATION,
- STATE_14A_MILLER_X,
- STATE_14A_MILLER_Y,
- STATE_14A_MILLER_Z,
- // DROP_NONE,
- // DROP_FIRST_HALF,
- } state;
- uint16_t shiftReg;
- int16_t bitCount;
- uint16_t len;
- //uint16_t byteCntMax;
- uint16_t posCnt;
- uint16_t syncBit;
- uint8_t parityBits;
- uint8_t parityLen;
- uint32_t fourBits;
- uint32_t startTime, endTime;
- uint8_t *output;
- uint8_t *parity;
-} tUart14a;
-
-#ifndef AddCrc14A
-# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
-#endif
-
-#ifndef AddCrc14B
-# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
-#endif
-
-#ifndef CheckCrc14A
-# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
-#endif
-
-void iso14a_set_timeout(uint32_t timeout);
-uint32_t iso14a_get_timeout(void);
-
-void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
-
-tDemod14a *GetDemod14a(void);
-void Demod14aReset(void);
-void Demod14aInit(uint8_t *data, uint8_t *par);
-tUart14a *GetUart14a(void);
-void Uart14aReset(void);
-void Uart14aInit(uint8_t *data, uint8_t *par);
-RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
-RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
-
-void RAMFUNC SniffIso14443a(uint8_t param);
-void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data);
-void iso14443a_antifuzz(uint32_t flags);
-void ReaderIso14443a(PacketCommandNG *c);
-void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing);
-void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
-void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
-int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
-
-void iso14443a_setup(uint8_t fpga_minor_mode);
-int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res);
-int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
-int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
-void iso14a_set_trigger(bool enable);
-void hf_field_off(void);
-
-int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
-int EmSend4bit(uint8_t resp);
-int EmSendCmd(uint8_t *resp, uint16_t respLen);
-int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision);
-int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par);
-int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
-int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision);
-int EmSendPrecompiledCmd(tag_response_info_t *p_response);
-
-bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size);
-
-bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
- uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
-
-void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
-void DetectNACKbug(void);
-
-bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len);
-
-#endif /* __ISO14443A_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443b.c b/pm3rdv4rrg/src/main/cpp/armsrc/iso14443b.c
deleted file mode 100644
index ba51f58c..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443b.c
+++ /dev/null
@@ -1,1658 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, split Nov 2006
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443B. This includes both the reader software and
-// the `fake tag' modes.
-//-----------------------------------------------------------------------------
-#include "iso14443b.h"
-
-#include "proxmark3_arm.h"
-#include "common.h" // access to global variable: DBGLEVEL
-#include "util.h"
-#include "string.h"
-#include "crc16.h"
-#include "protocols.h"
-#include "appmain.h"
-#include "BigBuf.h"
-#include "cmd.h"
-#include "fpgaloader.h"
-#include "commonutil.h"
-#include "dbprint.h"
-#include "ticks.h"
-
-#ifndef FWT_TIMEOUT_14B
-// defaults to 2000ms
-# define FWT_TIMEOUT_14B 35312
-#endif
-#ifndef ISO14443B_DMA_BUFFER_SIZE
-# define ISO14443B_DMA_BUFFER_SIZE 256
-#endif
-#ifndef RECEIVE_MASK
-# define RECEIVE_MASK (ISO14443B_DMA_BUFFER_SIZE-1)
-#endif
-
-// Guard Time (per 14443-2)
-#ifndef TR0
-# define TR0 0
-#endif
-
-// Synchronization time (per 14443-2)
-#ifndef TR1
-# define TR1 0
-#endif
-// Frame Delay Time PICC to PCD (per 14443-3 Amendment 1)
-#ifndef TR2
-# define TR2 0
-#endif
-
-// 4sample
-#define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);
-//#define SEND4STUFFBIT(x) ToSendStuffBit(x);
-// iceman, this threshold value, what makes 8 a good amplitude for this IQ values?
-#ifndef SUBCARRIER_DETECT_THRESHOLD
-# define SUBCARRIER_DETECT_THRESHOLD 8
-#endif
-
-static void iso14b_set_timeout(uint32_t timeout);
-static void iso14b_set_maxframesize(uint16_t size);
-
-// the block number for the ISO14443-4 PCB (used with APDUs)
-static uint8_t pcb_blocknum = 0;
-static uint32_t iso14b_timeout = FWT_TIMEOUT_14B;
-
-//=============================================================================
-// An ISO 14443 Type B tag. We listen for commands from the reader, using
-// a kind of thing that's implemented in software. When we get a
-// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
-// If it's good, then we can do something appropriate with it, and write
-// a response.
-//=============================================================================
-
-
-//-----------------------------------------------------------------------------
-// The software that receives commands from the reader, and its state variables.
-//-----------------------------------------------------------------------------
-static struct {
- enum {
- STATE_14B_UNSYNCD,
- STATE_14B_GOT_FALLING_EDGE_OF_SOF,
- STATE_14B_AWAITING_START_BIT,
- STATE_14B_RECEIVING_DATA
- } state;
- uint16_t shiftReg;
- int bitCnt;
- int byteCnt;
- int byteCntMax;
- int posCnt;
- uint8_t *output;
-} Uart;
-
-static void Uart14bReset() {
- Uart.state = STATE_14B_UNSYNCD;
- Uart.shiftReg = 0;
- Uart.bitCnt = 0;
- Uart.byteCnt = 0;
- Uart.byteCntMax = MAX_FRAME_SIZE;
- Uart.posCnt = 0;
-}
-
-static void Uart14bInit(uint8_t *data) {
- Uart.output = data;
- Uart14bReset();
-// memset(Uart.output, 0x00, MAX_FRAME_SIZE);
-}
-
-//-----------------------------------------------------------------------------
-// The software Demod that receives commands from the tag, and its state variables.
-//-----------------------------------------------------------------------------
-static struct {
- enum {
- DEMOD_UNSYNCD,
- DEMOD_PHASE_REF_TRAINING,
- DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
- DEMOD_GOT_FALLING_EDGE_OF_SOF,
- DEMOD_AWAITING_START_BIT,
- DEMOD_RECEIVING_DATA
- } state;
- uint16_t bitCount;
- int posCount;
- int thisBit;
- /* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
- int metric;
- int metricN;
- */
- uint16_t shiftReg;
- uint8_t *output;
- uint16_t len;
- int sumI;
- int sumQ;
- uint32_t startTime, endTime;
-} Demod;
-
-// Clear out the state of the "UART" that receives from the tag.
-static void Demod14bReset() {
- Demod.state = DEMOD_UNSYNCD;
- Demod.bitCount = 0;
- Demod.posCount = 0;
- Demod.thisBit = 0;
- Demod.shiftReg = 0;
- Demod.len = 0;
- Demod.sumI = 0;
- Demod.sumQ = 0;
- Demod.startTime = 0;
- Demod.endTime = 0;
-}
-
-static void Demod14bInit(uint8_t *data) {
- Demod.output = data;
- Demod14bReset();
- // memset(Demod.output, 0x00, MAX_FRAME_SIZE);
-}
-
-
-/*
-* 9.4395 us = 1 ETU and clock is about 1.5 us
-* 13560000Hz
-* 1000ms/s
-* timeout in ETUs (time to transfer 1 bit, 9.4395 us)
-*
-* Formula to calculate FWT (in ETUs) by timeout (in ms):
-* fwt = 13560000 * 1000 / (8*16) * timeout;
-* Sample: 3sec == 3000ms
-* 13560000 * 1000 / (8*16) * 3000 ==
-* 13560000000 / 384000 = 35312 FWT
-* @param timeout is in frame wait time, fwt, measured in ETUs
-*/
-static void iso14b_set_timeout(uint32_t timeout) {
-#define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16)
- if (timeout > MAX_TIMEOUT)
- timeout = MAX_TIMEOUT;
-
- iso14b_timeout = timeout;
- if (DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout);
-}
-static void iso14b_set_maxframesize(uint16_t size) {
- if (size > 256)
- size = MAX_FRAME_SIZE;
-
- Uart.byteCntMax = size;
- if (DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax);
-}
-
-//-----------------------------------------------------------------------------
-// Code up a string of octets at layer 2 (including CRC, we don't generate
-// that here) so that they can be transmitted to the reader. Doesn't transmit
-// them yet, just leaves them ready to write in ToSend[].
-//-----------------------------------------------------------------------------
-static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
- /* ISO 14443 B
- *
- * Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig)
- * Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B)
- *
- * fc - carrier frequency 13.56 MHz
- * TR0 - Guard Time per 14443-2
- * TR1 - Synchronization Time per 14443-2
- * TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1)
- *
- * Elementary Time Unit (ETU) is
- * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units
- * - 1 ETU = 1 bit
- * - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length)
- * - startbit is a 0
- * - stopbit is a 1
- *
- * Start of frame (SOF) is
- * - [10-11] ETU of ZEROS, unmodulated time
- * - [2-3] ETU of ONES,
- *
- * End of frame (EOF) is
- * - [10-11] ETU of ZEROS, unmodulated time
- *
- * -TO VERIFY THIS BELOW-
- * The mode FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK which we use to simulate tag
- * works like this:
- * - A 1-bit input to the FPGA becomes 8 pulses at 847.5kHz (1.18µS / pulse) == 9.44us
- * - A 0-bit input to the FPGA becomes an unmodulated time of 1.18µS or does it become 8 nonpulses for 9.44us
- *
- * FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead.
- *
- * Card sends data ub 847.e kHz subcarrier
- * subcar |duration| FC division
- * -------+--------+------------
- * 106kHz | 9.44µS | FC/128
- * 212kHz | 4.72µS | FC/64
- * 424kHz | 2.36µS | FC/32
- * 848kHz | 1.18µS | FC/16
- * -------+--------+------------
- *
- * Reader data transmission:
- * - no modulation ONES
- * - SOF
- * - Command, data and CRC_B
- * - EOF
- * - no modulation ONES
- *
- * Card data transmission
- * - TR1
- * - SOF
- * - data (each bytes is: 1startbit, 8bits, 1stopbit)
- * - CRC_B
- * - EOF
- *
- * FPGA implementation :
- * At this point only Type A is implemented. This means that we are using a
- * bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make
- * things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s)
- *
- */
-
- ToSendReset();
-
- // Transmit a burst of ones, as the initial thing that lets the
- // reader get phase sync.
- // This loop is TR1, per specification
- // TR1 minimum must be > 80/fs
- // TR1 maximum 200/fs
- // 80/fs < TR1 < 200/fs
- // 10 ETU < TR1 < 24 ETU
-
- // Send SOF.
- // 10-11 ETU * 4times samples ZEROS
- for (int i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
- //for(i = 0; i < 10; i++) { ToSendStuffBit(0); }
-
- // 2-3 ETU * 4times samples ONES
- for (int i = 0; i < 3; i++) { SEND4STUFFBIT(1); }
- //for(i = 0; i < 3; i++) { ToSendStuffBit(1); }
-
- // data
- for (int i = 0; i < len; ++i) {
-
- // Start bit
- SEND4STUFFBIT(0);
- //ToSendStuffBit(0);
-
- // Data bits
- uint8_t b = cmd[i];
- for (int j = 0; j < 8; ++j) {
- // if(b & 1) {
- // SEND4STUFFBIT(1);
- // //ToSendStuffBit(1);
- // } else {
- // SEND4STUFFBIT(0);
- // //ToSendStuffBit(0);
- // }
- SEND4STUFFBIT(b & 1);
- b >>= 1;
- }
-
- // Stop bit
- SEND4STUFFBIT(1);
- //ToSendStuffBit(1);
-
- // Extra Guard bit
- // For PICC it ranges 0-18us (1etu = 9us)
- SEND4STUFFBIT(1);
- //ToSendStuffBit(1);
- }
-
- // Send EOF.
- // 10-11 ETU * 4 sample rate = ZEROS
- for (int i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
- //for(i = 0; i < 10; i++) { ToSendStuffBit(0); }
-
- // why this?
- for (int i = 0; i < 40; i++) { SEND4STUFFBIT(1); }
- //for(i = 0; i < 40; i++) { ToSendStuffBit(1); }
-
- // Convert from last byte pos to length
- ++ToSendMax;
-}
-
-
-/* Receive & handle a bit coming from the reader.
- *
- * This function is called 4 times per bit (every 2 subcarrier cycles).
- * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us
- *
- * LED handling:
- * LED A -> ON once we have received the SOF and are expecting the rest.
- * LED A -> OFF once we have received EOF or are in error state or unsynced
- *
- * Returns: true if we received a EOF
- * false if we are still waiting for some more
- */
-static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
- switch (Uart.state) {
- case STATE_14B_UNSYNCD:
- if (!bit) {
- // we went low, so this could be the beginning of an SOF
- Uart.state = STATE_14B_GOT_FALLING_EDGE_OF_SOF;
- Uart.posCnt = 0;
- Uart.bitCnt = 0;
- }
- break;
-
- case STATE_14B_GOT_FALLING_EDGE_OF_SOF:
- Uart.posCnt++;
- if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit
- if (bit) {
- if (Uart.bitCnt > 9) {
- // we've seen enough consecutive
- // zeros that it's a valid SOF
- Uart.posCnt = 0;
- Uart.byteCnt = 0;
- Uart.state = STATE_14B_AWAITING_START_BIT;
- LED_A_ON(); // Indicate we got a valid SOF
- } else {
- // didn't stay down long enough before going high, error
- Uart.state = STATE_14B_UNSYNCD;
- }
- } else {
- // do nothing, keep waiting
- }
- Uart.bitCnt++;
- }
- if (Uart.posCnt >= 4) Uart.posCnt = 0;
- if (Uart.bitCnt > 12) {
- // Give up if we see too many zeros without a one, too.
- LED_A_OFF();
- Uart.state = STATE_14B_UNSYNCD;
- }
- break;
-
- case STATE_14B_AWAITING_START_BIT:
- Uart.posCnt++;
- if (bit) {
- if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
- // stayed high for too long between characters, error
- Uart.state = STATE_14B_UNSYNCD;
- }
- } else {
- // falling edge, this starts the data byte
- Uart.posCnt = 0;
- Uart.bitCnt = 0;
- Uart.shiftReg = 0;
- Uart.state = STATE_14B_RECEIVING_DATA;
- }
- break;
-
- case STATE_14B_RECEIVING_DATA:
- Uart.posCnt++;
- if (Uart.posCnt == 2) {
- // time to sample a bit
- Uart.shiftReg >>= 1;
- if (bit) {
- Uart.shiftReg |= 0x200;
- }
- Uart.bitCnt++;
- }
- if (Uart.posCnt >= 4) {
- Uart.posCnt = 0;
- }
- if (Uart.bitCnt == 10) {
- if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) {
- // this is a data byte, with correct
- // start and stop bits
- Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
- Uart.byteCnt++;
-
- if (Uart.byteCnt >= Uart.byteCntMax) {
- // Buffer overflowed, give up
- LED_A_OFF();
- Uart.state = STATE_14B_UNSYNCD;
- } else {
- // so get the next byte now
- Uart.posCnt = 0;
- Uart.state = STATE_14B_AWAITING_START_BIT;
- }
- } else if (Uart.shiftReg == 0x000) {
- // this is an EOF byte
- LED_A_OFF(); // Finished receiving
- Uart.state = STATE_14B_UNSYNCD;
- if (Uart.byteCnt != 0)
- return true;
-
- } else {
- // this is an error
- LED_A_OFF();
- Uart.state = STATE_14B_UNSYNCD;
- }
- }
- break;
-
- default:
- LED_A_OFF();
- Uart.state = STATE_14B_UNSYNCD;
- break;
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Receive a command (from the reader to us, where we are the simulated tag),
-// and store it in the given buffer, up to the given maximum length. Keeps
-// spinning, waiting for a well-framed command, until either we get one
-// (returns true) or someone presses the pushbutton on the board (false).
-//
-// Assume that we're called with the SSC (to the FPGA) and ADC path set
-// correctly.
-//-----------------------------------------------------------------------------
-static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
- // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
-
- StartCountSspClk();
-
- volatile uint8_t b;
-
- // clear receiving shift register and holding register
- // What does this loop do? Is it TR1?
- // loop is a wait/delay ?
- /*
- for(uint8_t c = 0; c < 10;) {
-
- // keep tx buffer in a defined state anyway.
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0xFF;
- ++c;
- }
- }
- */
- // Now run a `software UART' on the stream of incoming samples.
- Uart14bInit(received);
-
- uint8_t mask;
- while (!BUTTON_PRESS()) {
- WDT_HIT();
-
- // keep tx buffer in a defined state anyway.
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00;
- }
-
- // Wait for byte be become available in rx holding register
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
-
- b = (uint8_t) AT91C_BASE_SSC->SSC_RHR;
-
- for (mask = 0x80; mask != 0; mask >>= 1) {
- if (Handle14443bReaderUartBit(b & mask)) {
- *len = Uart.byteCnt;
- return true;
- }
- }
- }
- }
- return false;
-}
-
-void ClearFpgaShiftingRegisters(void) {
-
- volatile uint8_t b;
-
- // clear receiving shift register and holding register
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
-
- b = AT91C_BASE_SSC->SSC_RHR;
- (void) b;
-
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
-
- b = AT91C_BASE_SSC->SSC_RHR;
- (void) b;
-
- // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
- for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
- if (AT91C_BASE_SSC->SSC_RHR) break;
- }
-
- // Clear TXRDY:
- //AT91C_BASE_SSC->SSC_THR = 0xFF;
-}
-
-void WaitForFpgaDelayQueueIsEmpty(uint16_t delay) {
- // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
- uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3,
- for (uint8_t i = 0; i <= fpga_queued_bits / 8 + 1;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0xFF;
- i++;
- }
- }
-}
-
-static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) {
-
- volatile uint32_t b;
-
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- //uint16_t fpgasendQueueDelay = 0;
-
- // Modulate BPSK
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
- SpinDelay(40);
-
- ClearFpgaShiftingRegisters();
-
- FpgaSetupSsc();
-
- // Transmit the response.
- for (uint16_t i = 0; i < len;) {
-
- // Put byte into tx holding register as soon as it is ready
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
- AT91C_BASE_SSC->SSC_THR = response[++i];
- }
-
- // Prevent rx holding register from overflowing
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = AT91C_BASE_SSC->SSC_RHR;
- (void)b;
- }
- }
-
- //WaitForFpgaDelayQueueIsEmpty(fpgasendQueueDelay);
- AT91C_BASE_SSC->SSC_THR = 0xFF;
-}
-//-----------------------------------------------------------------------------
-// Main loop of simulated tag: read commands from reader, decide what
-// response to write, and write it.
-//-----------------------------------------------------------------------------
-void SimulateIso14443bTag(uint32_t pupi) {
-
- // setup devices.
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- // Set up the synchronous serial port
- FpgaSetupSsc();
-
- // allocate command read buffer
- BigBuf_free();
- BigBuf_Clear_ext(false);
-
- clear_trace(); //sim
- set_tracing(true);
-
- uint16_t len, cmdsReceived = 0;
- int cardSTATE = SIM_NOFIELD;
- int vHf = 0; // in mV
- // uint32_t time_0 = 0;
- // uint32_t t2r_time = 0;
- // uint32_t r2t_time = 0;
- uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
-
- // the only commands we understand is WUPB, AFI=0, Select All, N=1:
-// static const uint8_t cmdWUPB[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB
- // ... and REQB, AFI=0, Normal Request, N=1:
-// static const uint8_t cmdREQB[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xFF }; // REQB
- // ... and ATTRIB
-// static const uint8_t cmdATTRIB[] = { ISO14443B_ATTRIB, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB
-
- // ... if not PUPI/UID is supplied we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922,
- // supports only 106kBit/s in both directions, max frame size = 32Bytes,
- // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported:
- uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19,
- 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7
- };
-
- // response to HLTB and ATTRIB
- static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
-
- // ...PUPI/UID supplied from user. Adjust ATQB response accordingly
- if (pupi > 0) {
- num_to_bytes(pupi, 4, respATQB + 1);
- AddCrc14B(respATQB, 12);
- }
-
- // prepare "ATQB" tag answer (encoded):
- CodeIso14443bAsTag(respATQB, sizeof(respATQB));
- uint8_t *encodedATQB = BigBuf_malloc(ToSendMax);
- uint16_t encodedATQBLen = ToSendMax;
- memcpy(encodedATQB, ToSend, ToSendMax);
-
-
- // prepare "OK" tag answer (encoded):
- CodeIso14443bAsTag(respOK, sizeof(respOK));
- uint8_t *encodedOK = BigBuf_malloc(ToSendMax);
- uint16_t encodedOKLen = ToSendMax;
- memcpy(encodedOK, ToSend, ToSendMax);
-
- // Simulation loop
- while (!BUTTON_PRESS() && !data_available()) {
- WDT_HIT();
-
- // find reader field
- if (cardSTATE == SIM_NOFIELD) {
- vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
- if (vHf > MF_MINFIELDV) {
- cardSTATE = SIM_IDLE;
- LED_A_ON();
- }
- }
- if (cardSTATE == SIM_NOFIELD) continue;
-
- // Get reader command
- if (!GetIso14443bCommandFromReader(receivedCmd, &len)) {
- Dbprintf("button pressed, received %d commands", cmdsReceived);
- break;
- }
-
- // ISO14443-B protocol states:
- // REQ or WUP request in ANY state
- // WUP in HALTED state
- if (len == 5) {
- if ((receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8) == 0x8 && cardSTATE == SIM_HALTED) ||
- receivedCmd[0] == ISO14443B_REQB) {
- LogTrace(receivedCmd, len, 0, 0, NULL, true);
- cardSTATE = SIM_SELECTING;
- }
- }
-
- /*
- * How should this flow go?
- * REQB or WUPB
- * write response ( waiting for Attrib)
- * ATTRIB
- * write response ( waiting for commands 7816)
- * HALT
- write halt response ( waiting for wupb )
- */
-
- switch (cardSTATE) {
- //case SIM_NOFIELD:
- case SIM_HALTED:
- case SIM_IDLE: {
- LogTrace(receivedCmd, len, 0, 0, NULL, true);
- break;
- }
- case SIM_SELECTING: {
- TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
- LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
- cardSTATE = SIM_WORK;
- break;
- }
- case SIM_HALTING: {
- TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
- LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
- cardSTATE = SIM_HALTED;
- break;
- }
- case SIM_ACKNOWLEDGE: {
- TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
- LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
- cardSTATE = SIM_IDLE;
- break;
- }
- case SIM_WORK: {
- if (len == 7 && receivedCmd[0] == ISO14443B_HALT) {
- cardSTATE = SIM_HALTED;
- } else if (len == 11 && receivedCmd[0] == ISO14443B_ATTRIB) {
- cardSTATE = SIM_ACKNOWLEDGE;
- } else {
- // Todo:
- // - SLOT MARKER
- // - ISO7816
- // - emulate with a memory dump
- Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived);
-
- // CRC Check
- if (len >= 3) { // if crc exists
-
- if (!check_crc(CRC_14443_B, receivedCmd, len))
- DbpString("+++CRC fail");
- else
- DbpString("CRC passes");
- }
- cardSTATE = SIM_IDLE;
- }
- break;
- }
- default:
- break;
- }
-
- ++cmdsReceived;
- }
- if (DBGLEVEL >= 2)
- Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
- switch_off(); //simulate
-}
-
-//=============================================================================
-// An ISO 14443 Type B reader. We take layer two commands, code them
-// appropriately, and then write them to the tag. We then listen for the
-// tag's response, which we leave in the buffer to be demodulated on the
-// PC side.
-//=============================================================================
-
-/*
- * Handles reception of a bit from the tag
- *
- * This function is called 2 times per bit (every 4 subcarrier cycles).
- * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 4,72us
- *
- * LED handling:
- * LED C -> ON once we have received the SOF and are expecting the rest.
- * LED C -> OFF once we have received EOF or are unsynced
- *
- * Returns: true if we received a EOF
- * false if we are still waiting for some more
- *
- */
-static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
- int v = 0, myI = ABS(ci), myQ = ABS(cq);
-
-// The soft decision on the bit uses an estimate of just the
-// quadrant of the reference angle, not the exact angle.
-#define MAKE_SOFT_DECISION() { \
- if (Demod.sumI > 0) { \
- v = ci; \
- } else { \
- v = -ci; \
- } \
- if (Demod.sumQ > 0) { \
- v += cq; \
- } else { \
- v -= cq; \
- } \
- }
-
-// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq)
-// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
-#define CHECK_FOR_SUBCARRIER_old() { \
- if (ci < 0) { \
- if (cq < 0) { /* ci < 0, cq < 0 */ \
- if (cq < ci) { \
- v = -cq - (ci >> 1); \
- } else { \
- v = -ci - (cq >> 1); \
- } \
- } else { /* ci < 0, cq >= 0 */ \
- if (cq < -ci) { \
- v = -ci + (cq >> 1); \
- } else { \
- v = cq - (ci >> 1); \
- } \
- } \
- } else { \
- if (cq < 0) { /* ci >= 0, cq < 0 */ \
- if (-cq < ci) { \
- v = ci - (cq >> 1); \
- } else { \
- v = -cq + (ci >> 1); \
- } \
- } else { /* ci >= 0, cq >= 0 */ \
- if (cq < ci) { \
- v = ci + (cq >> 1); \
- } else { \
- v = cq + (ci >> 1); \
- } \
- } \
- } \
- }
-
-//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
-#define CHECK_FOR_SUBCARRIER() { v = MAX(myI, myQ) + (MIN(myI, myQ) >> 1); }
-
- switch (Demod.state) {
- case DEMOD_UNSYNCD:
-
- CHECK_FOR_SUBCARRIER();
-
- // subcarrier detected
-
- if (v > SUBCARRIER_DETECT_THRESHOLD) {
- Demod.state = DEMOD_PHASE_REF_TRAINING;
- Demod.sumI = ci;
- Demod.sumQ = cq;
- Demod.posCount = 1;
- }
- break;
-
- case DEMOD_PHASE_REF_TRAINING:
- if (Demod.posCount < 8) {
-
- CHECK_FOR_SUBCARRIER();
-
- if (v > SUBCARRIER_DETECT_THRESHOLD) {
- // set the reference phase (will code a logic '1') by averaging over 32 1/fs.
- // note: synchronization time > 80 1/fs
- Demod.sumI += ci;
- Demod.sumQ += cq;
- Demod.posCount++;
- } else {
- // subcarrier lost
- Demod.state = DEMOD_UNSYNCD;
- }
- } else {
- Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
- }
- break;
-
- case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
-
- MAKE_SOFT_DECISION();
-
- if (v < 0) { // logic '0' detected
- Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
- Demod.posCount = 0; // start of SOF sequence
- } else {
- // maximum length of TR1 = 200 1/fs
- if (Demod.posCount > 200 / 4) Demod.state = DEMOD_UNSYNCD;
- }
- Demod.posCount++;
- break;
-
- case DEMOD_GOT_FALLING_EDGE_OF_SOF:
- Demod.posCount++;
-
- MAKE_SOFT_DECISION();
-
- if (v > 0) {
- // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
- if (Demod.posCount < 9 * 2) {
- Demod.state = DEMOD_UNSYNCD;
- } else {
- LED_C_ON(); // Got SOF
- Demod.state = DEMOD_AWAITING_START_BIT;
- Demod.posCount = 0;
- Demod.len = 0;
- }
- } else {
- // low phase of SOF too long (> 12 etu)
- if (Demod.posCount > 14 * 2) {
- Demod.state = DEMOD_UNSYNCD;
- LED_C_OFF();
- }
- }
- break;
-
- case DEMOD_AWAITING_START_BIT:
- Demod.posCount++;
-
- MAKE_SOFT_DECISION();
-
- if (v > 0) {
- if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
- Demod.state = DEMOD_UNSYNCD;
- LED_C_OFF();
- }
- } else { // start bit detected
- Demod.bitCount = 0;
- Demod.posCount = 1; // this was the first half
- Demod.thisBit = v;
- Demod.shiftReg = 0;
- Demod.state = DEMOD_RECEIVING_DATA;
- }
- break;
-
- case DEMOD_RECEIVING_DATA:
-
- MAKE_SOFT_DECISION();
-
- if (Demod.posCount == 0) {
- // first half of bit
- Demod.thisBit = v;
- Demod.posCount = 1;
- } else {
- // second half of bit
- Demod.thisBit += v;
- Demod.shiftReg >>= 1;
-
- // OR in a logic '1'
- if (Demod.thisBit > 0)
- Demod.shiftReg |= 0x200;
-
- Demod.bitCount++;
-
- // 1 start 8 data 1 stop = 10
- if (Demod.bitCount == 10) {
-
- uint16_t s = Demod.shiftReg;
-
- // stop bit == '1', start bit == '0'
- if ((s & 0x200) && (s & 0x001) == 0) {
- // left shift to drop the startbit
- uint8_t b = (s >> 1);
- Demod.output[Demod.len] = b;
- ++Demod.len;
- Demod.state = DEMOD_AWAITING_START_BIT;
- } else {
- // this one is a bit hard, either its a correc byte or its unsynced.
- Demod.state = DEMOD_UNSYNCD;
- LED_C_OFF();
-
- // This is EOF (start, stop and all data bits == '0'
- if (s == 0) return true;
- }
- }
- Demod.posCount = 0;
- }
- break;
-
- default:
- Demod.state = DEMOD_UNSYNCD;
- LED_C_OFF();
- break;
- }
- return false;
-}
-
-
-/*
- * Demodulate the samples we received from the tag, also log to tracebuffer
- * quiet: set to 'TRUE' to disable debug output
- */
-static void GetTagSamplesFor14443bDemod() {
- bool finished = false;
-// int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
- uint32_t time_0 = 0, time_stop = 0;
-
- BigBuf_free();
-
- // Set up the demodulator for tag -> reader responses.
- Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
-
- // The DMA buffer, used to stream samples from the FPGA
- int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
- int8_t *upTo = dmaBuf;
-
- // Setup and start DMA.
- if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) {
- if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
- return;
- }
-
- // And put the FPGA in the appropriate mode
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
-
- // get current clock
- time_0 = GetCountSspClk();
-
- // rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read)
- while (!finished) {
-
- LED_A_INV();
- WDT_HIT();
-
- // LSB is a fpga signal bit.
- int ci = upTo[0];
- int cq = upTo[1];
- upTo += 2;
-// lastRxCounter -= 2;
-
- // restart DMA buffer to read again.
- if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
- upTo = dmaBuf;
-// lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
- AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
- }
-
- // https://github.com/Proxmark/proxmark3/issues/103
- bool gotFrame = Handle14443bTagSamplesDemod(ci, cq);
- time_stop = GetCountSspClk() - time_0;
-
- finished = (time_stop > iso14b_timeout || gotFrame);
- }
-
- FpgaDisableSscDma();
-
- if (upTo)
- upTo = NULL;
-
- if (Demod.len > 0)
- LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false);
-}
-
-//-----------------------------------------------------------------------------
-// Transmit the command (to the tag) that was placed in ToSend[].
-//-----------------------------------------------------------------------------
-static void TransmitFor14443b_AsReader(void) {
- int c;
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
- SpinDelay(60);
-
- // What does this loop do? Is it TR1?
- // 0xFF = 8 bits of 1. 1 bit == 1Etu,..
- // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why?
- // 80*9 = 720us.
-
- for (c = 0; c < 50;) {
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0xFF;
- c++;
- }
- }
-
- // Send frame loop
- for (c = 0; c < ToSendMax;) {
-
- // Put byte into tx holding register as soon as it is ready
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = ToSend[c++];
- }
- }
- WDT_HIT();
-}
-
-//-----------------------------------------------------------------------------
-// Code a layer 2 command (string of octets, including CRC) into ToSend[],
-// so that it is ready to transmit to the tag using TransmitFor14443b().
-//-----------------------------------------------------------------------------
-static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
- /*
- * Reader data transmission:
- * - no modulation ONES
- * - SOF
- * - Command, data and CRC_B
- * - EOF
- * - no modulation ONES
- *
- * 1 ETU == 1 BIT!
- * TR0 - 8 ETUS minimum.
- *
- * QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode?
- * 1 "stuffbit" = 1ETU (9us)
- */
-
- ToSendReset();
-
- // Send SOF
- // 10-11 ETUs of ZERO
- for (int i = 0; i < 10; ++i) ToSendStuffBit(0);
-
- // 2-3 ETUs of ONE
- ToSendStuffBit(1);
- ToSendStuffBit(1);
-// ToSendStuffBit(1);
-
- // Sending cmd, LSB
- // from here we add BITS
- for (int i = 0; i < len; ++i) {
- // Start bit
- ToSendStuffBit(0);
- // Data bits
- uint8_t b = cmd[i];
- // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>3) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
- // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
-
- ToSendStuffBit(b & 1);
- ToSendStuffBit((b >> 1) & 1);
- ToSendStuffBit((b >> 2) & 1);
- ToSendStuffBit((b >> 3) & 1);
- ToSendStuffBit((b >> 4) & 1);
- ToSendStuffBit((b >> 5) & 1);
- ToSendStuffBit((b >> 6) & 1);
- ToSendStuffBit((b >> 7) & 1);
-
- // Stop bit
- ToSendStuffBit(1);
- // EGT extra guard time
- // For PCD it ranges 0-57us (1etu = 9us)
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- }
-
- // Send EOF
- // 10-11 ETUs of ZERO
- for (int i = 0; i < 10; ++i) ToSendStuffBit(0);
-
- // Transition time. TR0 - guard time
- // 8ETUS minum?
- // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF.
- // I'm guessing this is for the FPGA to be able to write all bits before we switch to listening mode
- for (int i = 0; i < 24 ; ++i) ToSendStuffBit(1);
-
- // TR1 - Synchronization time
- // Convert from last character reference to length
- ToSendMax++;
-}
-
-/*
-* Convenience function to encode, transmit and trace iso 14443b comms
-*/
-static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) {
-
- uint32_t time_start = GetCountSspClk();
-
- CodeIso14443bAsReader(cmd, len);
-
- TransmitFor14443b_AsReader();
-
- if (trigger) LED_A_ON();
-
- LogTrace(cmd, len, time_start, GetCountSspClk() - time_start, NULL, true);
-}
-
-/* Sends an APDU to the tag
- * TODO: check CRC and preamble
- */
-uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) {
-
- uint8_t message_frame[message_length + 4];
- // PCB
- message_frame[0] = 0x0A | pcb_blocknum;
- pcb_blocknum ^= 1;
- // CID
- message_frame[1] = 0;
- // INF
- memcpy(message_frame + 2, message, message_length);
- // EDC (CRC)
- AddCrc14B(message_frame, message_length + 2);
- // write
- CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no
- // get response
- GetTagSamplesFor14443bDemod(); //no
-
- FpgaDisableTracing();
-
- if (Demod.len < 3)
- return 0;
-
- // VALIDATE CRC
- if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
- if (DBGLEVEL > 3) Dbprintf("crc fail ICE");
- return 0;
- }
- // copy response contents
- if (response != NULL)
- memcpy(response, Demod.output, Demod.len);
-
- return Demod.len;
-}
-
-/**
-* SRx Initialise.
-*/
-uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
- // INITIATE command: wake up the tag using the INITIATE
- static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b };
- // SELECT command (with space for CRC)
- uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00};
-
- CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx));
- GetTagSamplesFor14443bDemod(); //no
- FpgaDisableTracing();
-
- if (Demod.len == 0)
- return 2;
-
- // Randomly generated Chip ID
- if (card) card->chipid = Demod.output[0];
-
- select_srx[1] = Demod.output[0];
-
- AddCrc14B(select_srx, 2);
-
- CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx));
- GetTagSamplesFor14443bDemod(); //no
- FpgaDisableTracing();
-
- if (Demod.len != 3)
- return 2;
-
- // Check the CRC of the answer:
- if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
- return 3;
-
- // Check response from the tag: should be the same UID as the command we just sent:
- if (select_srx[1] != Demod.output[0])
- return 1;
-
- // First get the tag's UID:
- select_srx[0] = ISO14443B_GET_UID;
-
- AddCrc14B(select_srx, 1);
- CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one
- GetTagSamplesFor14443bDemod(); //no
- FpgaDisableTracing();
-
- if (Demod.len != 10)
- return 2;
-
- // The check the CRC of the answer
- if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
- return 3;
-
- if (card) {
- card->uidlen = 8;
- memcpy(card->uid, Demod.output, 8);
- }
-
- return 0;
-}
-/* Perform the ISO 14443 B Card Selection procedure
- * Currently does NOT do any collision handling.
- * It expects 0-1 cards in the devices's range.
- * TODO: Support multiple cards (perform anticollision)
- * TODO: Verify CRC checksums
- */
-uint8_t iso14443b_select_card(iso14b_card_select_t *card) {
- // WUPB command (including CRC)
- // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
- static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
- // ATTRIB command (with space for CRC)
- uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
-
- // first, wake up the tag
- CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
- GetTagSamplesFor14443bDemod(); //select_card
- FpgaDisableTracing();
-
- // ATQB too short?
- if (Demod.len < 14)
- return 2;
-
- // VALIDATE CRC
- if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
- return 3;
-
- if (card) {
- card->uidlen = 4;
- memcpy(card->uid, Demod.output + 1, 4);
- memcpy(card->atqb, Demod.output + 5, 7);
- }
-
- // copy the PUPI to ATTRIB ( PUPI == UID )
- memcpy(attrib + 1, Demod.output + 1, 4);
-
- // copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into ATTRIB (Param 3)
- attrib[7] = Demod.output[10] & 0x0F;
- AddCrc14B(attrib, 9);
-
- CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
- GetTagSamplesFor14443bDemod();//select_card
- FpgaDisableTracing();
-
- // Answer to ATTRIB too short?
- if (Demod.len < 3)
- return 2;
-
- // VALIDATE CRC
- if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
- return 3;
-
- if (card) {
-
- // CID
- card->cid = Demod.output[0];
-
- // MAX FRAME
- uint16_t maxFrame = card->atqb[5] >> 4;
- if (maxFrame < 5) maxFrame = 8 * maxFrame + 16;
- else if (maxFrame == 5) maxFrame = 64;
- else if (maxFrame == 6) maxFrame = 96;
- else if (maxFrame == 7) maxFrame = 128;
- else if (maxFrame == 8) maxFrame = 256;
- else maxFrame = 257;
- iso14b_set_maxframesize(maxFrame);
-
- // FWT
- uint8_t fwt = card->atqb[6] >> 4;
- if (fwt < 16) {
- uint32_t fwt_time = (302 << fwt);
- iso14b_set_timeout(fwt_time);
- }
- }
- // reset PCB block number
- pcb_blocknum = 0;
- return 0;
-}
-
-// Set up ISO 14443 Type B communication (similar to iso14443a_setup)
-// field is setup for "Sending as Reader"
-void iso14443b_setup() {
- LEDsoff();
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- // Initialize Demod and Uart structs
- Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
- Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
-
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Set up the synchronous serial port
- FpgaSetupSsc();
-
- // Signal field is on with the appropriate LED
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
- SpinDelay(100);
-
- // Start the timer
- StartCountSspClk();
-
- LED_D_ON();
-}
-
-//-----------------------------------------------------------------------------
-// Read a SRI512 ISO 14443B tag.
-//
-// SRI512 tags are just simple memory tags, here we're looking at making a dump
-// of the contents of the memory. No anticollision algorithm is done, we assume
-// we have a single tag in the field.
-//
-// I tried to be systematic and check every answer of the tag, every CRC, etc...
-//-----------------------------------------------------------------------------
-static bool ReadSTBlock(uint8_t block) {
- uint8_t cmd[] = {ISO14443B_READ_BLK, block, 0x00, 0x00};
- AddCrc14B(cmd, 2);
- CodeAndTransmit14443bAsReader(cmd, sizeof(cmd));
- GetTagSamplesFor14443bDemod();
- FpgaDisableTracing();
-
- // Check if we got an answer from the tag
- if (Demod.len != 6) {
- DbpString("[!] expected 6 bytes from tag, got less...");
- return false;
- }
- // The check the CRC of the answer
- if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
- DbpString("[!] CRC Error block!");
- return false;
- }
- return true;
-}
-void ReadSTMemoryIso14443b(uint8_t numofblocks) {
- // Make sure that we start from off, since the tags are stateful;
- // confusing things will happen if we don't reset them between reads.
- //switch_off();
-
- uint8_t i = 0x00;
- uint8_t *buf = BigBuf_malloc(sizeof(iso14b_card_select_t));
-
- iso14443b_setup();
-
- iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
- uint8_t res = iso14443b_select_srx_card(card);
-
- // 0: OK 2: attrib fail, 3:crc fail,
- if (res > 0) goto out;
-
- Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks);
-
- ++numofblocks;
-
- for (;;) {
- if (i == numofblocks) {
- DbpString("System area block (0xFF):");
- i = 0xff;
- }
-
- uint8_t retries = 3;
- do {
- res = ReadSTBlock(i);
- } while (!res && --retries);
-
- if (!res && !retries) {
- goto out;
- }
-
- // Now print out the memory location:
- Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
- (Demod.output[3] << 24) + (Demod.output[2] << 16) + (Demod.output[1] << 8) + Demod.output[0],
- (Demod.output[4] << 8) + Demod.output[5]);
-
- if (i == 0xff) break;
- ++i;
- }
-
-out:
- switch_off(); // disconnect raw
- SpinDelay(20);
-}
-
-static void iso1444b_setup_sniff(void) {
-
- LEDsoff();
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // Initialize Demod and Uart structs
- Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
- Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
-
- if (DBGLEVEL > 1) {
- // Print debug information about the buffer sizes
- Dbprintf("[+] Sniff buffers initialized:");
- Dbprintf("[+] trace: %i bytes", BigBuf_max_traceLen());
- Dbprintf("[+] reader -> tag: %i bytes", MAX_FRAME_SIZE);
- Dbprintf("[+] tag -> reader: %i bytes", MAX_FRAME_SIZE);
- Dbprintf("[+] DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE);
- }
-
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Setup for the DMA.
- FpgaSetupSsc();
-
- // Set FPGA in the appropriate mode
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
- SpinDelay(20);
-
- // Start the SSP timer
- StartCountSspClk();
-}
-
-//=============================================================================
-// Finally, the `sniffer' combines elements from both the reader and
-// simulated tag, to show both sides of the conversation.
-//=============================================================================
-
-//-----------------------------------------------------------------------------
-// Record the sequence of commands sent by the reader to the tag, with
-// triggering so that we start recording at the point that the tag is moved
-// near the reader.
-//-----------------------------------------------------------------------------
-/*
- * Memory usage for this function, (within BigBuf)
- * Last Received command (reader->tag) - MAX_FRAME_SIZE
- * Last Received command (tag->reader) - MAX_FRAME_SIZE
- * DMA Buffer - ISO14443B_DMA_BUFFER_SIZE
- * Demodulated samples received - all the rest
- */
-void RAMFUNC SniffIso14443b(void) {
-
- uint32_t time_0 = 0, time_start = 0, time_stop;
-
- // We won't start recording the frames that we acquire until we trigger;
- // a good trigger condition to get started is probably when we see a
- // response from the tag.
- bool TagIsActive = false;
- bool ReaderIsActive = false;
-
- iso1444b_setup_sniff();
-
- // The DMA buffer, used to stream samples from the FPGA
- int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
- int8_t *data = dmaBuf;
-
- // Setup and start DMA.
- if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) {
- if (DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
- BigBuf_free();
- return;
- }
-
- // time ZERO, the point from which it all is calculated.
- time_0 = GetCountSspClk();
-
- // loop and listen
- while (!BUTTON_PRESS()) {
- WDT_HIT();
-
- int ci = data[0];
- int cq = data[1];
- data += 2;
-
- if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
- data = dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
- }
-
- // no need to try decoding reader data if the tag is sending
- if (!TagIsActive) {
-
- LED_A_INV();
-
- if (Handle14443bReaderUartBit(ci & 0x01)) {
- time_stop = GetCountSspClk() - time_0;
- LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
- Uart14bReset();
- Demod14bReset();
- } else {
- time_start = GetCountSspClk() - time_0;
- }
-
- if (Handle14443bReaderUartBit(cq & 0x01)) {
- time_stop = GetCountSspClk() - time_0;
- LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
- Uart14bReset();
- Demod14bReset();
- } else {
- time_start = GetCountSspClk() - time_0;
- }
- ReaderIsActive = (Uart.state > STATE_14B_GOT_FALLING_EDGE_OF_SOF);
- }
-
- // no need to try decoding tag data if the reader is sending - and we cannot afford the time
- if (!ReaderIsActive) {
-
- // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103
- // LSB is a fpga signal bit.
- if (Handle14443bTagSamplesDemod(ci, cq)) {
- time_stop = GetCountSspClk() - time_0;
- LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
- Uart14bReset();
- Demod14bReset();
- } else {
- time_start = GetCountSspClk() - time_0;
- }
- TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF);
- }
- }
-
- if (DBGLEVEL >= 2) {
- DbpString("[+] Sniff statistics:");
- Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax);
- Dbprintf("[+] trace length: %i", BigBuf_get_traceLen());
- }
-
- switch_off();
-}
-
-void iso14b_set_trigger(bool enable) {
- trigger = enable;
-}
-
-/*
- * Send raw command to tag ISO14443B
- * @Input
- * param flags enum ISO14B_COMMAND. (mifare.h)
- * len len of buffer data
- * data buffer with bytes to write
- *
- * @Output
- * none
- *
- */
-void SendRawCommand14443B_Ex(PacketCommandNG *c) {
- iso14b_command_t param = c->oldarg[0];
- size_t len = c->oldarg[1] & 0xffff;
- uint32_t timeout = c->oldarg[2];
- uint8_t *cmd = c->data.asBytes;
- uint8_t status;
- uint32_t sendlen = sizeof(iso14b_card_select_t);
- uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00};
-
- if (DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param);
-
- // turn on trigger (LED_A)
- if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER)
- iso14b_set_trigger(true);
-
- if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) {
- iso14443b_setup();
- clear_trace();
- }
-
- if ((param & ISO14B_SET_TIMEOUT))
- iso14b_set_timeout(timeout);
-
- set_tracing(true);
-
- if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
- iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
- status = iso14443b_select_card(card);
- reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen);
- // 0: OK 2: attrib fail, 3:crc fail,
- if (status > 0) goto out;
- }
-
- if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
- iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
- status = iso14443b_select_srx_card(card);
- reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen);
- // 0: OK 2: demod fail, 3:crc fail,
- if (status > 0) goto out;
- }
-
- if ((param & ISO14B_APDU) == ISO14B_APDU) {
- status = iso14443b_apdu(cmd, len, buf);
- reply_mix(CMD_ACK, status, status, 0, buf, status);
- }
-
- if ((param & ISO14B_RAW) == ISO14B_RAW) {
- if ((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) {
- AddCrc14B(cmd, len);
- len += 2;
- }
-
- CodeAndTransmit14443bAsReader(cmd, len); // raw
- GetTagSamplesFor14443bDemod(); // raw
- FpgaDisableTracing();
-
- sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
- status = (Demod.len > 0) ? 0 : 1;
- reply_old(CMD_ACK, status, sendlen, 0, Demod.output, sendlen);
- }
-
-out:
- // turn off trigger (LED_A)
- if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER)
- iso14b_set_trigger(false);
-
- // turn off antenna et al
- // we don't write a HALT command.
- if ((param & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) {
- switch_off(); // disconnect raw
- SpinDelay(20);
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443b.h b/pm3rdv4rrg/src/main/cpp/armsrc/iso14443b.h
deleted file mode 100644
index 12ee316e..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iso14443b.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443 type B.
-//-----------------------------------------------------------------------------
-
-#ifndef __ISO14443B_H
-#define __ISO14443B_H
-
-#include "common.h"
-
-#include "mifare.h"
-#include "pm3_cmd.h"
-
-#ifndef AddCrc14A
-# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
-#endif
-
-#ifndef AddCrc14B
-# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
-#endif
-
-void iso14443b_setup();
-uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
-uint8_t iso14443b_select_card(iso14b_card_select_t *card);
-uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
-
-void SimulateIso14443bTag(uint32_t pupi);
-void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
-void ReadSTMemoryIso14443b(uint8_t numofblocks);
-void RAMFUNC SniffIso14443b(void);
-void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
-void SendRawCommand14443B_Ex(PacketCommandNG *c);
-
-// testfunctions
-void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
-void ClearFpgaShiftingRegisters(void);
-
-// States for 14B SIM command
-#define SIM_NOFIELD 0
-#define SIM_IDLE 1
-#define SIM_HALTED 2
-#define SIM_SELECTING 3
-#define SIM_HALTING 4
-#define SIM_ACKNOWLEDGE 5
-#define SIM_WORK 6
-
-#endif /* __ISO14443B_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iso15693.c b/pm3rdv4rrg/src/main/cpp/armsrc/iso15693.c
deleted file mode 100644
index 2bcba18f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iso15693.c
+++ /dev/null
@@ -1,1019 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, split Nov 2006
-// Modified by Greg Jones, Jan 2009
-// Modified by Adrian Dabrowski "atrox", Mar-Sept 2010,Oct 2011
-// Modified by Christian Herrmann "iceman", 2017
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 15693. This includes both the reader software and
-// the `fake tag' modes, but at the moment I've implemented only the reader
-// stuff, and that barely.
-// Modified to perform modulation onboard in arm rather than on PC
-// Also added additional reader commands (SELECT, READ etc.)
-//-----------------------------------------------------------------------------
-// The ISO 15693 describes two transmission modes from reader to tag, and 4
-// transmission modes from tag to reader. As of Mar 2010 this code only
-// supports one of each: "1of4" mode from reader to tag, and the highspeed
-// variant with one subcarrier from card to reader.
-// As long, as the card fully support ISO 15693 this is no problem, since the
-// reader chooses both data rates, but some non-standard tags do not. Further for
-// the simulation to work, we will need to support all data rates.
-//
-// VCD (reader) -> VICC (tag)
-// 1 out of 256:
-// data rate: 1,66 kbit/s (fc/8192)
-// used for long range
-// 1 out of 4:
-// data rate: 26,48 kbit/s (fc/512)
-// used for short range, high speed
-//
-// VICC (tag) -> VCD (reader)
-// Modulation:
-// ASK / one subcarrier (423,75 kHz)
-// FSK / two subcarriers (423,75 kHz && 484,28 kHz)
-// Data Rates / Modes:
-// low ASK: 6,62 kbit/s
-// low FSK: 6.67 kbit/s
-// high ASK: 26,48 kbit/s
-// high FSK: 26,69 kbit/s
-//-----------------------------------------------------------------------------
-// added "1 out of 256" mode (for VCD->PICC) - atrox 20100911
-
-
-// Random Remarks:
-// *) UID is always used "transmission order" (LSB), which is reverse to display order
-
-// TODO / BUGS / ISSUES:
-// *) writing to tags takes longer: we miss the answer from the tag in most cases
-// -> tweak the read-timeout times
-// *) signal decoding from the card is still a bit shaky.
-// *) signal decoding is unable to detect collissions.
-// *) add anti-collission support for inventory-commands
-// *) read security status of a block
-// *) sniffing and simulation do only support one transmission mode. need to support
-// all 8 transmission combinations
-// *) remove or refactor code under "depricated"
-// *) document all the functions
-
-#include "iso15693.h"
-
-#include "proxmark3_arm.h"
-#include "util.h"
-#include "string.h"
-#include "iso15693tools.h"
-#include "cmd.h"
-#include "appmain.h"
-#include "dbprint.h"
-#include "fpgaloader.h"
-#include "commonutil.h"
-#include "ticks.h"
-#include "BigBuf.h"
-#include "crc16.h"
-
-///////////////////////////////////////////////////////////////////////
-// ISO 15693 Part 2 - Air Interface
-// This section basicly contains transmission and receiving of bits
-///////////////////////////////////////////////////////////////////////
-
-// 32 + 2 crc + 1
-#define ISO15_MAX_FRAME 35
-#define CMD_ID_RESP 5
-#define CMD_READ_RESP 13
-#define CMD_INV_RESP 12
-
-#define FrameSOF Iso15693FrameSOF
-#define Logic0 Iso15693Logic0
-#define Logic1 Iso15693Logic1
-#define FrameEOF Iso15693FrameEOF
-
-//#define Crc(data, len) Crc(CRC_15693, (data), (len))
-#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
-#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
-
-#define sprintUID(target,uid) Iso15693sprintUID((target), (uid))
-
-static void BuildIdentifyRequest(uint8_t *cmdout);
-//static void BuildReadBlockRequest(uint8_t *cmdout, uint8_t *uid, uint8_t blockNumber );
-static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid);
-
-// ---------------------------
-// Signal Processing
-// ---------------------------
-
-// prepare data using "1 out of 4" code for later transmission
-// resulting data rate is 26,48 kbit/s (fc/512)
-// cmd ... data
-// n ... length of data
-static void CodeIso15693AsReader(uint8_t *cmd, int n) {
- int i, j;
-
- ToSendReset();
-
- // Give it a bit of slack at the beginning
- for (i = 0; i < 24; i++)
- ToSendStuffBit(1);
-
- // SOF for 1of4
- ToSendStuffBit(0);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- for (i = 0; i < n; i++) {
- for (j = 0; j < 8; j += 2) {
- int these = (cmd[i] >> j) & 3;
- switch (these) {
- case 0:
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- break;
- case 1:
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- break;
- case 2:
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- break;
- case 3:
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- break;
- }
- }
- }
- // EOF
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- ToSendStuffBit(1);
-
- // And slack at the end, too.
- for (i = 0; i < 24; i++)
- ToSendStuffBit(1);
-}
-
-// encode data using "1 out of 256" sheme
-// data rate is 1,66 kbit/s (fc/8192)
-// is designed for more robust communication over longer distances
-static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
- int i, j;
-
- ToSendReset();
-
- // Give it a bit of slack at the beginning
- for (i = 0; i < 24; i++)
- ToSendStuffBit(1);
-
- // SOF for 1of256
- ToSendStuffBit(0);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
-
- for (i = 0; i < n; i++) {
- for (j = 0; j <= 255; j++) {
- if (cmd[i] == j) {
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- } else {
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- }
- }
- }
- // EOF
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(0);
- ToSendStuffBit(1);
-
- // And slack at the end, too.
- for (i = 0; i < 24; i++)
- ToSendStuffBit(1);
-}
-
-// Transmit the command (to the tag) that was placed in ToSend[].
-static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait) {
-
- int c;
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
-
- if (wait) {
- for (c = 0; c < *wait;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
- ++c;
- }
- WDT_HIT();
- }
- }
-
- c = 0;
- for (;;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = cmd[c];
- if (++c >= len) break;
- }
- WDT_HIT();
- }
-
- if (samples) {
- if (wait)
- *samples = (c + *wait) << 3;
- else
- *samples = c << 3;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Transmit the command (to the reader) that was placed in ToSend[].
-//-----------------------------------------------------------------------------
-static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait) {
- int c = 0;
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K);
-
- if (wait) {
- for (c = 0; c < *wait;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
- ++c;
- }
- WDT_HIT();
- }
- }
-
- c = 0;
- for (;;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = cmd[c];
- if (++c >= len) break;
- }
- WDT_HIT();
- }
- if (samples) {
- if (wait)
- *samples = (c + *wait) << 3;
- else
- *samples = c << 3;
- }
-}
-
-//-----------------------------------------------------------------------------
-// DEMODULATE tag answer
-//-----------------------------------------------------------------------------
-static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
-
- int i, j;
- int max = 0, maxPos = 0, skip = 4;
- int k = 0; // this will be our return value
-
- // First, correlate for SOF
- for (i = 0; i < samplecount; i++) {
- int corr = 0;
- for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
- corr += FrameSOF[j] * dest[i + (j / skip)];
- }
- if (corr > max) {
- max = corr;
- maxPos = i;
- }
- }
- // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
-
- // greg - If correlation is less than 1 then there's little point in continuing
- if ((max / (ARRAYLEN(FrameSOF) / skip)) < 1)
- return k;
-
- i = maxPos + ARRAYLEN(FrameSOF) / skip;
-
- uint8_t outBuf[ISO15_MAX_FRAME];
- memset(outBuf, 0, sizeof(outBuf));
- uint8_t mask = 0x01;
- for (;;) {
- int corr0 = 0, corr1 = 0, corrEOF = 0;
- for (j = 0; j < ARRAYLEN(Logic0); j += skip) {
- corr0 += Logic0[j] * dest[i + (j / skip)];
- }
- for (j = 0; j < ARRAYLEN(Logic1); j += skip) {
- corr1 += Logic1[j] * dest[i + (j / skip)];
- }
- for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
- corrEOF += FrameEOF[j] * dest[i + (j / skip)];
- }
- // Even things out by the length of the target waveform.
- corr0 *= 4;
- corr1 *= 4;
- // if (DBGLEVEL >= DBG_EXTENDED)
- // Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF);
-
- if (corrEOF > corr1 && corrEOF > corr0)
- break;
-
- if (corr1 > corr0) {
- i += ARRAYLEN(Logic1) / skip;
- outBuf[k] |= mask;
- } else {
- i += ARRAYLEN(Logic0) / skip;
- }
-
- mask <<= 1;
-
- if (mask == 0) {
- k++;
- mask = 0x01;
- }
-
- if ((i + (int)ARRAYLEN(FrameEOF)) >= samplecount - 1) {
- //Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1);
- break;
- }
- }
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("ice: demod bytes %u", k);
-
- if (mask != 0x01) { // this happens, when we miss the EOF
-
- // TODO: for some reason this happens quite often
- if (DBGLEVEL >= DBG_ERROR && k != 0) Dbprintf("[!] error, uneven octet! (extra bits!) mask %02x", mask);
- //if (mask < 0x08) k--; // discard the last uneven octet;
- // 0x08 is an assumption - but works quite often
- }
-
- for (i = 0; i < k; i++)
- received[i] = outBuf[i];
-
- // return the number of bytes demodulated
- return k;
-}
-
-// Read from Tag
-// Parameters:
-// received
-// samples
-// elapsed
-// returns:
-// number of decoded bytes
-// logging enabled
-static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
-
-#define SIGNAL_BUFF_SIZE 15000
- // get current clock
- uint32_t time_0 = GetCountSspClk();
- uint32_t time_stop = 0;
- bool getNext = false;
- int counter = 0, ci, cq = 0;
- uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE);
-
- if (elapsed) *elapsed = 0;
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
-
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00; //0x43;
- // To make use of exact timing of next command from reader!!
- if (elapsed)(*elapsed)++;
- }
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-
- ci = (int8_t)AT91C_BASE_SSC->SSC_RHR;
- ci = ABS(ci);
-
- // The samples are correlations against I and Q versions of the
- // tone that the tag AM-modulates, so every other sample is I,
- // every other is Q. We just want power, so abs(I) + abs(Q) is
- // close to what we want.
- // iceman 2016, amplitude sqrt(abs(i) + abs(q))
- if (getNext) {
-
- buf[counter++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
-
- if (counter >= SIGNAL_BUFF_SIZE)
- break;
- } else {
- cq = ci;
- }
- getNext = !getNext;
- }
- }
- time_stop = GetCountSspClk() - time_0 ;
- int len = DemodAnswer(received, buf, counter);
- LogTrace(received, len, time_0 << 4, time_stop << 4, NULL, false);
- BigBuf_free();
- return len;
-}
-
-
-// Now the GetISO15693 message from sniffing command
-// logging enable,
-static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elapsed) {
-
- bool getNext = false;
- int counter = 0, ci, cq = 0;
- uint32_t time_0 = 0, time_stop = 0;
- uint8_t *buf = BigBuf_get_addr();
-
- // get current clock
- time_0 = GetCountSspClk();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
-
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-
- ci = (int8_t)AT91C_BASE_SSC->SSC_RHR;
- ci = ABS(ci);
-
- // The samples are correlations against I and Q versions of the
- // tone that the tag AM-modulates, so every other sample is I,
- // every other is Q. We just want power, so abs(I) + abs(Q) is
- // close to what we want.
- if (getNext) {
-
- buf[counter++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
-
- if (counter >= 20000)
- break;
- } else {
- cq = ci;
- }
- getNext = !getNext;
- }
- }
-
- time_stop = GetCountSspClk() - time_0;
- int k = DemodAnswer(received, buf, counter);
- LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false);
- return k;
-}
-
-//-----------------------------------------------------------------------------
-// Start to read an ISO 15693 tag. We write an identify request, then wait
-// for the response. The response is not demodulated, just left in the buffer
-// so that it can be downloaded to a PC and processed there.
-//-----------------------------------------------------------------------------
-void AcquireRawAdcSamplesIso15693(void) {
- int c = 0, getNext = false;
- int ci, cq = 0;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- FpgaSetupSsc();
-
- // Now write the command
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
- SpinDelay(200);
-
- uint8_t *buf = BigBuf_get_addr();
-
- uint32_t time_start = GetCountSspClk();
- uint8_t cmd[CMD_ID_RESP] = {0};
- BuildIdentifyRequest(cmd);
-
- // sending command
- c = 0;
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = ToSend[c];
- c++;
- if (c == ToSendMax + 3) {
- break;
- }
- }
- }
-
-
- LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
-
- c = 0;
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-
- ci = (int8_t)AT91C_BASE_SSC->SSC_RHR;
- ci = ABS(ci);
-
- // The samples are correlations against I and Q versions of the
- // tone that the tag AM-modulates, so every other sample is I,
- // every other is Q. We just want power, so abs(I) + abs(Q) is
- // close to what we want.
- // iceman 2016, amplitude sqrt(abs(i) + abs(q))
- if (getNext) {
-
- buf[c++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
-
- if (c >= 7000) break;
-
- } else {
- cq = ci;
- }
- getNext = !getNext;
- }
- }
-}
-
-// switch_off, initreader, no logging
-void RecordRawAdcSamplesIso15693(void) {
-
- int c = 0, getNext = false;
- int ci, cq = 0;
-
- Iso15693InitReader();
-
- uint8_t *buf = BigBuf_get_addr();
-
- for (;;) {
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-
- ci = (int8_t)AT91C_BASE_SSC->SSC_RHR;
- ci = ABS(ci);
- // The samples are correlations against I and Q versions of the
- // tone that the tag AM-modulates, so every other sample is I,
- // every other is Q. We just want power, so abs(I) + abs(Q) is
- // close to what we want.
- if (getNext) {
-
- buf[c++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
-
- if (c >= 7000)
- break;
- } else {
- cq = ci;
- }
-
- getNext = !getNext;
- }
- }
-
- Dbprintf("done");
- switch_off();
-}
-
-// Initialize the proxmark as iso15k reader
-// (this might produces glitches that confuse some tags
-void Iso15693InitReader(void) {
- LEDsoff();
- clear_trace();
- set_tracing(true);
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- // Start from off (no field generated)
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(10);
-
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- FpgaSetupSsc();
-
- // Give the tags time to energize
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
- SpinDelay(200);
-
- // Start the timer
- StartCountSspClk();
-
- LED_A_ON();
-}
-
-///////////////////////////////////////////////////////////////////////
-// ISO 15693 Part 3 - Air Interface
-// This section basicly contains transmission and receiving of bits
-///////////////////////////////////////////////////////////////////////
-
-// Encode (into the ToSend buffers) an identify request, which is the first
-// thing that you must write to a tag to get a response.
-// It expects "cmdout" to be at least CMD_ID_RESP large
-static void BuildIdentifyRequest(uint8_t *cmdout) {
- uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0};
- // flags
- cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
- // no mask
- cmd[2] = 0x00;
- // CRC
- AddCrc15(cmd, 3);
- // coding as high speed (1 out of 4)
- CodeIso15693AsReader(cmd, CMD_ID_RESP);
- memcpy(cmdout, cmd, CMD_ID_RESP);
-}
-
-// uid is in transmission order (which is reverse of display order)
-/*
-static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumber ) {
- uint8_t cmd[CMD_READ_RESP] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
- // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
- // followed by teh block data
- // one sub-carrier, inventory, 1 slot, fast rate
- cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit
- // READ BLOCK command code
- cmd[1] = 0x20;
- // UID may be optionally specified here
- // 64-bit UID
- cmd[2] = uid[0];
- cmd[3] = uid[1];
- cmd[4] = uid[2];
- cmd[5] = uid[3];
- cmd[6] = uid[4];
- cmd[7] = uid[5];
- cmd[8] = uid[6];
- cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
- // Block number to read
- cmd[10] = blockNumber;//0x00;
- // CRC
- AddCrc15(cmd, 11);
- CodeIso15693AsReader(cmd, CMD_READ_RESP);
- memcpy(out, cmd, CMD_ID_RESP);
-}
-*/
-
-// Now the VICC>VCD responses when we are simulating a tag
-// It expects "out" to be at least CMD_INV_RESP large
-static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid) {
-
- uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- // one sub-carrier, inventory, 1 slot, fast rate
- // AFI is at bit 5 (1<<4) when doing an INVENTORY
- //(1 << 2) | (1 << 5) | (1 << 1);
- cmd[0] = 0; //
- cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
- // 64-bit UID
- cmd[2] = uid[7]; //0x32;
- cmd[3] = uid[6]; //0x4b;
- cmd[4] = uid[5]; //0x03;
- cmd[5] = uid[4]; //0x01;
- cmd[6] = uid[3]; //0x00;
- cmd[7] = uid[2]; //0x10;
- cmd[8] = uid[1]; //0x05;
- cmd[9] = uid[0]; //0xe0;
- // CRC
- AddCrc15(cmd, 10);
- CodeIso15693AsReader(cmd, CMD_INV_RESP);
- memcpy(cmdout, cmd, CMD_INV_RESP);
-}
-
-// Universal Method for sending to and recv bytes from a tag
-// init ... should we initialize the reader?
-// speed ... 0 low speed, 1 hi speed
-// **recv will return you a pointer to the received data
-// If you do not need the answer use NULL for *recv[]
-// return: length of received data
-// logging enabled
-int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outdata) {
-
- int t_samples = 0, wait = 0, elapsed = 0, answer_len = 0;
-
- LEDsoff();
-
- if (init) Iso15693InitReader();
-
- LED_A_ON();
-
- if (!speed)
- CodeIso15693AsReader256(send, sendlen); // low speed (1 out of 256)
- else
- CodeIso15693AsReader(send, sendlen); // high speed (1 out of 4)
-
- LED_A_INV();
-
- uint32_t time_start = GetCountSspClk();
-
- TransmitTo15693Tag(ToSend, ToSendMax, &t_samples, &wait);
- LogTrace(send, sendlen, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
-
- // Now wait for a response
- if (outdata != NULL) {
- LED_B_INV();
- answer_len = GetIso15693AnswerFromTag(outdata, &elapsed);
- }
-
- LEDsoff();
- return answer_len;
-}
-
-// --------------------------------------------------------------------
-// Debug Functions
-// --------------------------------------------------------------------
-
-// Decodes a message from a tag and displays its metadata and content
-#define DBD15STATLEN 48
-void DbdecodeIso15693Answer(int len, uint8_t *d) {
-
- if (len > 3) {
- char status[DBD15STATLEN + 1] = {0};
- if (d[0] & (1 << 3))
- strncat(status, "ProtExt ", DBD15STATLEN - strlen(status));
- if (d[0] & 1) {
- // error
- strncat(status, "Error ", DBD15STATLEN - strlen(status));
- switch (d[1]) {
- case 0x01:
- strncat(status, "01: not supported", DBD15STATLEN - strlen(status));
- break;
- case 0x02:
- strncat(status, "02: not recognized", DBD15STATLEN - strlen(status));
- break;
- case 0x03:
- strncat(status, "03: opt not supported", DBD15STATLEN - strlen(status));
- break;
- case 0x0f:
- strncat(status, "0F: no info", DBD15STATLEN - strlen(status));
- break;
- case 0x10:
- strncat(status, "10: don't exist", DBD15STATLEN - strlen(status));
- break;
- case 0x11:
- strncat(status, "11: lock again", DBD15STATLEN - strlen(status));
- break;
- case 0x12:
- strncat(status, "12: locked", DBD15STATLEN - strlen(status));
- break;
- case 0x13:
- strncat(status, "13: program error", DBD15STATLEN - strlen(status));
- break;
- case 0x14:
- strncat(status, "14: lock error", DBD15STATLEN - strlen(status));
- break;
- default:
- strncat(status, "unknown error", DBD15STATLEN - strlen(status));
- }
- strncat(status, " ", DBD15STATLEN - strlen(status));
- } else {
- strncat(status, "No error ", DBD15STATLEN - strlen(status));
- }
-
- if (CheckCrc15(d, len))
- strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status));
- else
- strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status));
-
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("%s", status);
- }
-}
-
-///////////////////////////////////////////////////////////////////////
-// Functions called via USB/Client
-///////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// Act as ISO15693 reader, perform anti-collision and then attempt to read a sector
-// all demodulation performed in arm rather than host. - greg
-//-----------------------------------------------------------------------------
-// ok
-// parameter is unused !?!
-void ReaderIso15693(uint32_t parameter) {
- int answerLen1 = 0;
- int tsamples = 0, wait = 0, elapsed = 0;
- // set up devices/fpga
- Iso15693InitReader();
-
- uint8_t *answer1 = BigBuf_malloc(50);
- uint8_t *answer2 = BigBuf_malloc(50);
-
- // Blank arrays
- memset(answer1, 0x00, 50);
- memset(answer2, 0x00, 50);
-
- // Now write the IDENTIFY command
- // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
- // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
- uint32_t time_start = GetCountSspClk();
- uint8_t cmd[CMD_ID_RESP] = {0};
- BuildIdentifyRequest(cmd);
- TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait);
- LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
-
- // Now wait for a response
- answerLen1 = GetIso15693AnswerFromTag(answer1, &elapsed) ;
-
- // we should do a better check than this
- if (answerLen1 >= 12) {
- uint8_t uid[8];
- uid[0] = answer1[9]; // always E0
- uid[1] = answer1[8]; // IC Manufacturer code
- uid[2] = answer1[7];
- uid[3] = answer1[6];
- uid[4] = answer1[5];
- uid[5] = answer1[4];
- uid[6] = answer1[3];
- uid[7] = answer1[2];
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
- uid[0], uid[1], uid[2], uid[3],
- uid[4], uid[5], uid[5], uid[6]
- );
- }
- // write UID back to client.
- // arg0 = 1 = OK
- // arg1 = len of response (12 bytes)
- // arg2 = rtf
- // asbytes = uid.
- reply_old(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
- }
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1);
- DbdecodeIso15693Answer(answerLen1, answer1);
- Dbhexdump(answerLen1, answer1, true);
- }
-
- switch_off();
-}
-
-// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
-// all demodulation performed in arm rather than host. - greg
-void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
-
- LEDsoff();
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- FpgaSetupSsc();
- // Start from off (no field generated)
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(200);
-
- LED_A_ON();
-
- uint32_t time_start;
- int samples = 0, tsamples = 0;
- int wait = 0, elapsed = 0;
-
- Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
-
- uint8_t buf[ISO15_MAX_FRAME];
- memset(buf, 0x00, sizeof(buf));
-
- LED_C_ON();
-
- // Build a suitable reponse to the reader INVENTORY cocmmand
- // not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below.
- uint8_t cmd[CMD_INV_RESP] = {0};
- BuildInventoryResponse(cmd, uid);
-
- while (!BUTTON_PRESS() && !data_available()) {
- WDT_HIT();
-
- // Listen to reader
- int ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ;
-
- // we should do a better check than this
- if (ans >= 1) {
-
- time_start = GetCountSspClk();
- TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
- LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans,
- buf[0], buf[1], buf[2], buf[3],
- buf[4], buf[5], buf[6], buf[7]
- );
- }
- }
- }
- switch_off();
-}
-
-// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
-// (some manufactures offer a way to read the AFI, though)
-void BruteforceIso15693Afi(uint32_t speed) {
-
- uint8_t data[7] = {0, 0, 0, 0, 0, 0, 0};
- uint8_t buf[ISO15_MAX_FRAME];
- memset(buf, 0x00, sizeof(buf));
- int datalen = 0, recvlen = 0;
- bool aborted = false;
-
- Iso15693InitReader();
-
- // first without AFI
- // Tags should respond wihtout AFI and with AFI=0 even when AFI is active
-
- data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
- data[1] = ISO15_CMD_INVENTORY;
- data[2] = 0; // AFI
- AddCrc15(data, 3);
- datalen = 5;
- recvlen = SendDataTag(data, datalen, false, speed, buf);
-
- WDT_HIT();
-
- if (recvlen >= 12) {
- Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2));
- }
-
- // now with AFI
- data[0] |= ISO15_REQINV_AFI;
- //data[1] = ISO15_CMD_INVENTORY;
- data[2] = 0; // AFI
- data[3] = 0; // mask length
-
- // 4 + 2crc
- datalen = 6;
-
- for (uint16_t i = 0; i < 256; i++) {
- data[2] = i & 0xFF;
- AddCrc15(data, 4);
- recvlen = SendDataTag(data, datalen, false, speed, buf);
- WDT_HIT();
- if (recvlen >= 12) {
- Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2));
- }
-
- aborted = BUTTON_PRESS();
-
- if (aborted) {
- DbpString("button pressed, aborting..");
- break;
- }
- }
-
- DbpString("AFI Bruteforcing done.");
- switch_off();
-
- if (aborted) {
- reply_ng(CMD_ACK, PM3_EOPABORTED, NULL, 0);
- } else {
- reply_ng(CMD_ACK, PM3_SUCCESS, NULL, 0);
- }
-}
-
-// Allows to directly write commands to the tag via the client
-// Has to increase dialog between devices and client.
-void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data) {
-
- bool init = true;
- int buflen = 0;
- uint8_t buf[ISO15_MAX_FRAME];
- memset(buf, 0x00, sizeof(buf));
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- DbpString("[+] SEND");
- Dbhexdump(datalen, data, true);
- }
-
- buflen = SendDataTag(data, datalen, init, speed, (recv ? buf : NULL));
-
- if (recv) {
- buflen = (buflen > ISO15_MAX_FRAME) ? ISO15_MAX_FRAME : buflen;
-
- LED_B_ON();
- reply_old(CMD_ACK, buflen, 0, 0, buf, buflen);
- LED_B_OFF();
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- DbpString("[+] RECV");
- DbdecodeIso15693Answer(buflen, buf);
- Dbhexdump(buflen, buf, true);
- }
- } else {
- reply_old(CMD_ACK, 1, 0, 0, 0, 0);
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/iso15693.h b/pm3rdv4rrg/src/main/cpp/armsrc/iso15693.h
deleted file mode 100644
index ca0864e6..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/iso15693.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __ISO15693_H
-#define __ISO15693_H
-
-#include "common.h"
-
-#include "pm3_cmd.h" // struct
-
-void RecordRawAdcSamplesIso15693(void);
-void AcquireRawAdcSamplesIso15693(void);
-void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
-void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
-void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
-void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // write arbitrary commands from CLI - atrox
-void Iso15693InitReader(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/ldscript b/pm3rdv4rrg/src/main/cpp/armsrc/ldscript
deleted file mode 100644
index 4d48d994..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/ldscript
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
------------------------------------------------------------------------------
- This code is licensed to you under the terms of the GNU GPL, version 2 or,
- at your option, any later version. See the LICENSE.txt file for the text of
- the license.
------------------------------------------------------------------------------
- Linker script for the ARM binary
------------------------------------------------------------------------------
-*/
-INCLUDE ../common_arm/ldscript.common
-
-PHDRS
-{
- text PT_LOAD FLAGS(5);
- data PT_LOAD;
- bss PT_LOAD;
-}
-
-ENTRY(Vector)
-SECTIONS
-{
- .start : {
- *(.startos)
- } >osimage :text
-
- .text : {
- KEEP(*(stage1_image))
- *(.text)
- *(.text.*)
- *(.eh_frame)
- *(.glue_7)
- *(.glue_7t)
- } >osimage :text
-
- .rodata : {
- *(.rodata)
- *(.rodata.*)
- *(fpga_all_bit.data)
- KEEP(*(.version_information))
- . = ALIGN(8);
- } >osimage :text
-
- .data : {
- KEEP(*(compressed_data))
- *(.data)
- *(.data.*)
- *(.ramfunc)
- . = ALIGN(4);
- } >ram AT>osimage :data
-
- __data_src_start__ = LOADADDR(.data);
- __data_start__ = ADDR(.data);
- __data_end__ = __data_start__ + SIZEOF(.data);
- __os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata);
-
- .bss : {
- __bss_start__ = .;
- *(.bss)
- *(.bss.*)
- . = ALIGN(4);
- __bss_end__ = .;
- } >ram AT>ram :bss
-
- .commonarea (NOLOAD) : {
- *(.commonarea)
- } >commonarea :NONE
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/legicrf.c b/pm3rdv4rrg/src/main/cpp/armsrc/legicrf.c
deleted file mode 100644
index 77d9ca70..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/legicrf.c
+++ /dev/null
@@ -1,514 +0,0 @@
-//-----------------------------------------------------------------------------
-// (c) 2009 Henryk Plötz
-// 2016 Iceman
-// 2018 AntiCat
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LEGIC RF simulation code
-//-----------------------------------------------------------------------------
-#include "legicrf.h"
-
-#include "crc.h" /* legic crc-4 */
-#include "legic_prng.h" /* legic PRNG impl */
-#include "legic.h" /* legic_card_select_t struct */
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "string.h"
-#include "protocols.h"
-
-static uint8_t *legic_mem; /* card memory, used for read, write */
-static legic_card_select_t card;/* metadata of currently selected card */
-static crc_t legic_crc;
-
-//-----------------------------------------------------------------------------
-// Frame timing and pseudorandom number generator
-//
-// The Prng is forwarded every 100us (TAG_BIT_PERIOD), except when the reader is
-// transmitting. In that case the prng has to be forwarded every bit transmitted:
-// - 60us for a 0 (RWD_TIME_0)
-// - 100us for a 1 (RWD_TIME_1)
-//
-// The data dependent timing makes writing comprehensible code significantly
-// harder. The current aproach forwards the prng data based if there is data on
-// air and time based, using GET_TICKS, during computational and wait periodes.
-//
-// To not have the necessity to calculate/guess exection time dependend timeouts
-// tx_frame and rx_frame use a shared timestamp to coordinate tx and rx timeslots.
-//-----------------------------------------------------------------------------
-
-static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
-
-#define RWD_TIME_PAUSE 30 /* 20us */
-#define RWD_TIME_1 150 /* READER_TIME_PAUSE 20us off + 80us on = 100us */
-#define RWD_TIME_0 90 /* READER_TIME_PAUSE 20us off + 40us on = 60us */
-#define RWD_FRAME_WAIT 330 /* 220us from TAG frame end to READER frame start */
-#define TAG_FRAME_WAIT 495 /* 330us from READER frame end to TAG frame start */
-#define TAG_BIT_PERIOD 150 /* 100us */
-#define TAG_WRITE_TIMEOUT 60 /* 40 * 100us (write should take at most 3.6ms) */
-
-#define LEGIC_CARD_MEMSIZE 1024 /* The largest Legic Prime card is 1k */
-#define WRITE_LOWERLIMIT 4 /* UID and MCC are not writable */
-
-#define INPUT_THRESHOLD 8 /* heuristically determined, lower values */
-/* lead to detecting false ack during write */
-
-//-----------------------------------------------------------------------------
-// I/O interface abstraction (FPGA -> ARM)
-//-----------------------------------------------------------------------------
-
-static inline uint8_t rx_byte_from_fpga() {
- for (;;) {
- WDT_HIT();
-
- // wait for byte be become available in rx holding register
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- return AT91C_BASE_SSC->SSC_RHR;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Demodulation
-//-----------------------------------------------------------------------------
-
-// Returns am aproximated power measurement
-//
-// The FPGA running on the xcorrelation kernel samples the subcarrier at ~3 MHz.
-// The kernel was initialy designed to read BSPK/2-PSK. Hance, it reports an
-// I/Q pair every 18.9us (8 bits i and 8 bits q).
-//
-// The subcarrier amplitude can be calculated using Pythagoras sqrt(i^2 + q^2).
-// To reduce CPU time the amplitude is approximated by using linear functions:
-// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
-//
-// Note: The SSC receiver is never synchronized the calculation may be performed
-// on a i/q pair from two subsequent correlations, but does not matter.
-static inline int32_t sample_power() {
- int32_t q = (int8_t)rx_byte_from_fpga();
- q = ABS(q);
- int32_t i = (int8_t)rx_byte_from_fpga();
- i = ABS(i);
-
- return MAX(i, q) + (MIN(i, q) >> 1);
-}
-
-// Returns a demedulated bit
-//
-// An aproximated power measurement is available every 18.9us. The bit time
-// is 100us. The code samples 5 times and uses the last (most stable) sample.
-//
-// Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame
-// has a delay loop that aligns rx_bit calls to the TAG tx timeslots.
-static inline bool rx_bit() {
- int32_t power;
-
- for (size_t i = 0; i < 5; ++i) {
- power = sample_power();
- }
-
- return (power > INPUT_THRESHOLD);
-}
-
-//-----------------------------------------------------------------------------
-// Modulation
-//
-// I've tried to modulate the Legic specific pause-puls using ssc and the default
-// ssc clock of 105.4 kHz (bit periode of 9.4us) - previous commit. However,
-// the timing was not precise enough. By increasing the ssc clock this could
-// be circumvented, but the adventage over bitbang would be little.
-//-----------------------------------------------------------------------------
-
-static inline void tx_bit(bool bit) {
- // insert pause
- LOW(GPIO_SSC_DOUT);
- last_frame_end += RWD_TIME_PAUSE;
- while (GET_TICKS < last_frame_end) { };
- HIGH(GPIO_SSC_DOUT);
-
- // return to high, wait for bit periode to end
- last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
- while (GET_TICKS < last_frame_end) { };
-}
-
-//-----------------------------------------------------------------------------
-// Frame Handling
-//
-// The LEGIC RF protocol from card to reader does not include explicit frame
-// start/stop information or length information. The reader must know beforehand
-// how many bits it wants to read.
-// Notably: a card sending a stream of 0-bits is indistinguishable from no card
-// present.
-//-----------------------------------------------------------------------------
-
-static void tx_frame(uint32_t frame, uint8_t len) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
-
- // wait for next tx timeslot
- last_frame_end += RWD_FRAME_WAIT;
- while (GET_TICKS < last_frame_end) { };
-
- // backup ts for trace log
- uint32_t last_frame_start = last_frame_end;
-
- // transmit frame, MSB first
- for (uint8_t i = 0; i < len; ++i) {
- bool bit = (frame >> i) & 0x01;
- tx_bit(bit ^ legic_prng_get_bit());
- legic_prng_forward(1);
- };
-
- // add pause to mark end of the frame
- LOW(GPIO_SSC_DOUT);
- last_frame_end += RWD_TIME_PAUSE;
- while (GET_TICKS < last_frame_end) { };
- HIGH(GPIO_SSC_DOUT);
-
- // log
- uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
- LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
-}
-
-static uint32_t rx_frame(uint8_t len) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
- | FPGA_HF_READER_RX_XCORR_848_KHZ
- | FPGA_HF_READER_RX_XCORR_QUARTER);
-
- // hold sampling until card is expected to respond
- last_frame_end += TAG_FRAME_WAIT;
- while (GET_TICKS < last_frame_end) { };
-
- // backup ts for trace log
- uint32_t last_frame_start = last_frame_end;
-
- uint32_t frame = 0;
- for (uint8_t i = 0; i < len; ++i) {
- frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
- legic_prng_forward(1);
-
- // rx_bit runs only 95us, resync to TAG_BIT_PERIOD
- last_frame_end += TAG_BIT_PERIOD;
- while (GET_TICKS < last_frame_end) { };
- }
-
- // log
- uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
- LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
-
- return frame;
-}
-
-static bool rx_ack() {
- // change fpga into rx mode
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
- | FPGA_HF_READER_RX_XCORR_848_KHZ
- | FPGA_HF_READER_RX_XCORR_QUARTER);
-
- // hold sampling until card is expected to respond
- last_frame_end += TAG_FRAME_WAIT;
- while (GET_TICKS < last_frame_end) { };
-
- // backup ts for trace log
- uint32_t last_frame_start = last_frame_end;
-
- uint32_t ack = 0;
- for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
- // sample bit
- ack = rx_bit();
- legic_prng_forward(1);
-
- // rx_bit runs only 95us, resync to TAG_BIT_PERIOD
- last_frame_end += TAG_BIT_PERIOD;
- while (GET_TICKS < last_frame_end) { };
-
- // check if it was an ACK
- if (ack) {
- break;
- }
- }
-
- // log
- uint8_t cmdbytes[] = {1, BYTEx(ack, 0)};
- LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
-
- return ack;
-}
-
-//-----------------------------------------------------------------------------
-// Legic Reader
-//-----------------------------------------------------------------------------
-
-static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
- p_card->tagtype = cardtype;
-
- switch (p_card->tagtype) {
- case 0x0d:
- p_card->cmdsize = 6;
- p_card->addrsize = 5;
- p_card->cardsize = 22;
- break;
- case 0x1d:
- p_card->cmdsize = 9;
- p_card->addrsize = 8;
- p_card->cardsize = 256;
- break;
- case 0x3d:
- p_card->cmdsize = 11;
- p_card->addrsize = 10;
- p_card->cardsize = 1024;
- break;
- default:
- p_card->cmdsize = 0;
- p_card->addrsize = 0;
- p_card->cardsize = 0;
- return 2;
- }
- return 0;
-}
-
-static void init_reader(bool clear_mem) {
- // configure FPGA
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
- | FPGA_HF_READER_RX_XCORR_848_KHZ
- | FPGA_HF_READER_RX_XCORR_QUARTER);
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- LED_A_ON();
-
- // configure SSC with defaults
- FpgaSetupSsc();
-
- // re-claim GPIO_SSC_DOUT as GPIO and enable output
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
- HIGH(GPIO_SSC_DOUT);
-
- // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
- legic_mem = BigBuf_get_EM_addr();
- if (legic_mem) {
- memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE);
- }
-
- // start trace
- clear_trace();
- set_tracing(true);
-
- // init crc calculator
- crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
-
- // start us timer
- StartTicks();
-}
-
-// Setup reader to card connection
-//
-// The setup consists of a three way handshake:
-// - Transmit initialisation vector 7 bits
-// - Receive card type 6 bits
-// - Transmit Acknowledge 6 bits
-static uint32_t setup_phase(uint8_t iv) {
- // init coordination timestamp
- last_frame_end = GET_TICKS;
-
- // Switch on carrier and let the card charge for 5ms.
- last_frame_end += 7500;
- while (GET_TICKS < last_frame_end) { };
-
- legic_prng_init(0);
- tx_frame(iv, 7);
-
- // configure prng
- legic_prng_init(iv);
- legic_prng_forward(2);
-
- // read card type
- int32_t card_type = rx_frame(6);
- legic_prng_forward(3);
-
- // write obsfuscated acknowledgment frame
- switch (card_type) {
- case 0x0D:
- tx_frame(0x19, 6); // MIM22 | READCMD = 0x18 | 0x01
- break;
- case 0x1D:
- case 0x3D:
- tx_frame(0x39, 6); // MIM256 | READCMD = 0x38 | 0x01
- break;
- }
-
- return card_type;
-}
-
-static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
- crc_clear(&legic_crc);
- crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz);
- return crc_finish(&legic_crc);
-}
-
-static int16_t read_byte(uint16_t index, uint8_t cmd_sz) {
- uint16_t cmd = (index << 1) | LEGIC_READ;
-
- // read one byte
- LED_B_ON();
- legic_prng_forward(2);
- tx_frame(cmd, cmd_sz);
- legic_prng_forward(2);
- uint32_t frame = rx_frame(12);
- LED_B_OFF();
-
- // split frame into data and crc
- uint8_t byte = BYTEx(frame, 0);
- uint8_t crc = BYTEx(frame, 1);
-
- // check received against calculated crc
- uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte);
- if (calc_crc != crc) {
- Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
- return -1;
- }
-
- legic_prng_forward(1);
-
- return byte;
-}
-
-// Transmit write command, wait until (3.6ms) the tag sends back an unencrypted
-// ACK ('1' bit) and forward the prng time based.
-bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
- uint32_t cmd = index << 1 | LEGIC_WRITE; // prepare command
- uint8_t crc = calc_crc4(cmd, addr_sz + 1, byte); // calculate crc
- cmd |= byte << (addr_sz + 1); // append value
- cmd |= (crc & 0xF) << (addr_sz + 1 + 8); // and crc
-
- // write write command
- LED_C_ON();
- legic_prng_forward(2);
- tx_frame(cmd, addr_sz + 1 + 8 + 4); // cmd_sz = addr_sz + cmd + data + crc
- legic_prng_forward(3);
- LED_C_OFF();
-
- // wait for ack
- return rx_ack();
-}
-
-//-----------------------------------------------------------------------------
-// Command Line Interface
-//
-// Only this functions are public / called from appmain.c
-//-----------------------------------------------------------------------------
-void LegicRfInfo(void) {
- // configure ARM and FPGA
- init_reader(false);
-
- // establish shared secret and detect card type
- uint8_t card_type = setup_phase(0x01);
- if (init_card(card_type, &card) != 0) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
-
- // read UID
- for (uint8_t i = 0; i < sizeof(card.uid); ++i) {
- int16_t byte = read_byte(i, card.cmdsize);
- if (byte == -1) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
- card.uid[i] = byte & 0xFF;
- }
-
- // read MCC and check against UID
- int16_t mcc = read_byte(4, card.cmdsize);
- int16_t calc_mcc = CRC8Legic(card.uid, 4);;
- if (mcc != calc_mcc) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
-
- // OK
- reply_old(CMD_ACK, 1, 0, 0, (uint8_t *)&card, sizeof(legic_card_select_t));
-
-OUT:
- switch_off();
- StopTicks();
-}
-
-void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
- // configure ARM and FPGA
- init_reader(false);
-
- // establish shared secret and detect card type
- uint8_t card_type = setup_phase(iv);
- if (init_card(card_type, &card) != 0) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
-
- // do not read beyond card memory
- if (len + offset > card.cardsize) {
- len = card.cardsize - offset;
- }
-
- for (uint16_t i = 0; i < len; ++i) {
- int16_t byte = read_byte(offset + i, card.cmdsize);
- if (byte == -1) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
- legic_mem[i] = byte;
- }
-
- // OK
- reply_old(CMD_ACK, 1, len, 0, legic_mem, len);
-
-OUT:
- switch_off();
- StopTicks();
-}
-
-void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
- // configure ARM and FPGA
- init_reader(false);
-
- // uid is not writeable
- if (offset <= WRITE_LOWERLIMIT) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
-
- // establish shared secret and detect card type
- uint8_t card_type = setup_phase(iv);
- if (init_card(card_type, &card) != 0) {
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
-
- // do not write beyond card memory
- if (len + offset > card.cardsize) {
- len = card.cardsize - offset;
- }
-
- // write in reverse order, only then is DCF (decremental field) writable
- while (len-- > 0 && !BUTTON_PRESS()) {
- if (!write_byte(len + offset, data[len], card.addrsize)) {
- Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
- goto OUT;
- }
- }
-
- // OK
- reply_old(CMD_ACK, 1, len, 0, legic_mem, len);
-
-OUT:
- switch_off();
- StopTicks();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/legicrf.h b/pm3rdv4rrg/src/main/cpp/armsrc/legicrf.h
deleted file mode 100644
index 47a7f89d..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/legicrf.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//-----------------------------------------------------------------------------
-// (c) 2009 Henryk Plötz
-// 2018 AntiCat
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LEGIC RF emulation public interface
-//-----------------------------------------------------------------------------
-
-#ifndef __LEGICRF_H
-#define __LEGICRF_H
-
-#include "common.h"
-
-void LegicRfInfo(void);
-void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
-void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data);
-
-#endif /* __LEGICRF_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/legicrfsim.c b/pm3rdv4rrg/src/main/cpp/armsrc/legicrfsim.c
deleted file mode 100644
index e7475ac4..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/legicrfsim.c
+++ /dev/null
@@ -1,492 +0,0 @@
-//-----------------------------------------------------------------------------
-// (c) 2009 Henryk Plötz
-// 2016 Iceman
-// 2018 AntiCat
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LEGIC RF simulation code
-//-----------------------------------------------------------------------------
-#include "legicrfsim.h"
-#include "legicrf.h"
-
-#include "crc.h" /* legic crc-4 */
-#include "legic_prng.h" /* legic PRNG impl */
-#include "legic.h" /* legic_card_select_t struct */
-
-#include "proxmark3_arm.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-
-static uint8_t *legic_mem; /* card memory, used for sim */
-static legic_card_select_t card;/* metadata of currently selected card */
-static crc_t legic_crc;
-
-//-----------------------------------------------------------------------------
-// Frame timing and pseudorandom number generator
-//
-// The Prng is forwarded every 99.1us (TAG_BIT_PERIOD), except when the reader is
-// transmitting. In that case the prng has to be forwarded every bit transmitted:
-// - 31.3us for a 0 (RWD_TIME_0)
-// - 99.1us for a 1 (RWD_TIME_1)
-//
-// The data dependent timing makes writing comprehensible code significantly
-// harder. The current aproach forwards the prng data based if there is data on
-// air and time based, using GetCountSspClk(), during computational and wait
-// periodes. SSP Clock is clocked by the FPGA at 212 kHz (subcarrier frequency).
-//
-// To not have the necessity to calculate/guess exection time dependend timeouts
-// tx_frame and rx_frame use a shared timestamp to coordinate tx and rx timeslots.
-//-----------------------------------------------------------------------------
-
-static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
-
-#define TAG_FRAME_WAIT 70 /* 330us from READER frame end to TAG frame start */
-#define TAG_ACK_WAIT 758 /* 3.57ms from READER frame end to TAG write ACK */
-#define TAG_BIT_PERIOD 21 /* 99.1us */
-
-#define RWD_TIME_PAUSE 4 /* 18.9us */
-#define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */
-#define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */
-#define RWD_CMD_TIMEOUT 120 /* 120 * 99.1us (arbitrary value) */
-#define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */
-#define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */
-
-#define RWD_PULSE 1 /* Pulse is signaled with GPIO_SSC_DIN high */
-#define RWD_PAUSE 0 /* Pause is signaled with GPIO_SSC_DIN low */
-
-//-----------------------------------------------------------------------------
-// Demodulation
-//-----------------------------------------------------------------------------
-
-// Returns true if a pulse/pause is received within timeout
-static inline bool wait_for(bool value, const uint32_t timeout) {
- while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
- if (GetCountSspClk() > timeout) {
- return false;
- }
- }
- return true;
-}
-
-// Returns a demedulated bit or -1 on code violation
-//
-// rx_bit decodes bits using a thresholds. rx_bit has to be called by as soon as
-// a frame starts (first pause is received). rx_bit checks for a pause up to
-// 18.9us followed by a pulse of 80.2us or 42.4us:
-// - A bit length <18.9us is a code violation
-// - A bit length >80.2us is a 1
-// - A bit length <80.2us is a 0
-// - A bit length >148.6us is a code violation
-static inline int8_t rx_bit() {
- // backup ts for threshold calculation
- uint32_t bit_start = last_frame_end;
-
- // wait for pause to end
- if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2)) {
- return -1;
- }
-
- // wait for next pause
- if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2)) {
- return -1;
- }
-
- // update bit and frame end
- last_frame_end = GetCountSspClk();
-
- // check for code violation (bit to short)
- if (last_frame_end - bit_start < RWD_TIME_PAUSE) {
- return -1;
- }
-
- // apply threshold (average of RWD_TIME_0 and )
- return (last_frame_end - bit_start > (RWD_TIME_0 + RWD_TIME_1) / 2);
-}
-
-//-----------------------------------------------------------------------------
-// Modulation
-//
-// LEGIC RF uses a very basic load modulation from card to reader:
-// - Subcarrier on for a 1
-// - Subcarrier off for for a 0
-//
-// The 212kHz subcarrier is generated by the FPGA as well as a mathcing ssp clk.
-// Each bit is transfered in a 99.1us slot and the first timeslot starts 330us
-// after the final 20us pause generated by the reader.
-//-----------------------------------------------------------------------------
-
-// Transmits a bit
-//
-// Note: The Subcarrier is not disabled during bits to prevent glitches. This is
-// not mandatory but results in a cleaner signal. tx_frame will disable
-// the subcarrier when the frame is done.
-static inline void tx_bit(bool bit) {
- LED_C_ON();
-
- if (bit) {
- // modulate subcarrier
- HIGH(GPIO_SSC_DOUT);
- } else {
- // do not modulate subcarrier
- LOW(GPIO_SSC_DOUT);
- }
-
- // wait for tx timeslot to end
- last_frame_end += TAG_BIT_PERIOD;
- while (GetCountSspClk() < last_frame_end) { };
- LED_C_OFF();
-}
-
-//-----------------------------------------------------------------------------
-// Frame Handling
-//
-// The LEGIC RF protocol from reader to card does not include explicit frame
-// start/stop information or length information. The tag detects end of frame
-// trough an extended pulse (>99.1us) without a pause.
-// In reverse direction (card to reader) the number of bites is well known
-// and depends only the command received (IV, ACK, READ or WRITE).
-//-----------------------------------------------------------------------------
-
-static void tx_frame(uint32_t frame, uint8_t len) {
- // wait for next tx timeslot
- last_frame_end += TAG_FRAME_WAIT;
- legic_prng_forward(TAG_FRAME_WAIT / TAG_BIT_PERIOD - 1);
- while (GetCountSspClk() < last_frame_end) { };
-
- // backup ts for trace log
- uint32_t last_frame_start = last_frame_end;
-
- // transmit frame, MSB first
- for (uint8_t i = 0; i < len; ++i) {
- bool bit = (frame >> i) & 0x01;
- tx_bit(bit ^ legic_prng_get_bit());
- legic_prng_forward(1);
- };
-
- // disable subcarrier
- LOW(GPIO_SSC_DOUT);
-
- // log
- uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
- LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
-}
-
-static void tx_ack() {
- // wait for ack timeslot
- last_frame_end += TAG_ACK_WAIT;
- legic_prng_forward(TAG_ACK_WAIT / TAG_BIT_PERIOD - 1);
- while (GetCountSspClk() < last_frame_end) { };
-
- // backup ts for trace log
- uint32_t last_frame_start = last_frame_end;
-
- // transmit ack (ack is not encrypted)
- tx_bit(true);
- legic_prng_forward(1);
-
- // disable subcarrier
- LOW(GPIO_SSC_DOUT);
-
- // log
- uint8_t cmdbytes[] = {1, 1};
- LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
-}
-
-// Returns a demedulated frame or -1 on code violation
-//
-// Since TX to RX delay is arbitrary rx_frame has to:
-// - detect start of frame (first pause)
-// - forward prng based on ts/TAG_BIT_PERIOD
-// - read the frame
-// - detect end of frame (last pause)
-static int32_t rx_frame(uint8_t *len) {
- int32_t frame = 0;
-
- // add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay)
- // those will be substracted at the end of the rx phase
- last_frame_end -= 2;
-
- // wait for first pause (start of frame)
- for (uint8_t i = 0; true; ++i) {
- // increment prng every TAG_BIT_PERIOD
- last_frame_end += TAG_BIT_PERIOD;
- legic_prng_forward(1);
-
- // if start of frame was received exit delay loop
- if (wait_for(RWD_PAUSE, last_frame_end)) {
- last_frame_end = GetCountSspClk();
- break;
- }
-
- // check for code violation
- if (i > RWD_CMD_TIMEOUT) {
- return -1;
- }
- }
-
- // backup ts for trace log
- uint32_t last_frame_start = last_frame_end;
-
- // read frame
- for (*len = 0; true; ++(*len)) {
- // read next bit
- LED_B_ON();
- int8_t bit = rx_bit();
- LED_B_OFF();
-
- // check for code violation and to short / long frame
- if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) {
- return -1;
- }
-
- // check for code violation caused by end of frame
- if (bit < 0) {
- break;
- }
-
- // append bit
- frame |= (bit ^ legic_prng_get_bit()) << (*len);
- legic_prng_forward(1);
- }
-
- // rx_bit sets coordination timestamp to start of pause, append pause duration
- // and substract 2 SSP clock cycles (1 for rx and 1 for tx pipeline delay) to
- // obtain exact end of frame.
- last_frame_end += RWD_TIME_PAUSE - 2;
-
- // log
- uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
- LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
- return frame;
-}
-
-//-----------------------------------------------------------------------------
-// Legic Simulator
-//-----------------------------------------------------------------------------
-
-static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
- p_card->tagtype = cardtype;
-
- switch (p_card->tagtype) {
- case 0:
- p_card->cmdsize = 6;
- p_card->addrsize = 5;
- p_card->cardsize = 22;
- break;
- case 1:
- p_card->cmdsize = 9;
- p_card->addrsize = 8;
- p_card->cardsize = 256;
- break;
- case 2:
- p_card->cmdsize = 11;
- p_card->addrsize = 10;
- p_card->cardsize = 1024;
- break;
- default:
- p_card->cmdsize = 0;
- p_card->addrsize = 0;
- p_card->cardsize = 0;
- return 2;
- }
- return 0;
-}
-
-static void init_tag() {
- // configure FPGA
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
- | FPGA_HF_SIMULATOR_MODULATE_212K);
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // configure SSC with defaults
- FpgaSetupSsc();
-
- // first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT
- LOW(GPIO_SSC_DOUT);
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
-
- // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
- legic_mem = BigBuf_get_EM_addr();
-
- // start trace
- clear_trace();
- set_tracing(true);
-
- // init crc calculator
- crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
-
- // start 212kHz timer (running from SSP Clock)
- StartCountSspClk();
-}
-
-// Setup reader to card connection
-//
-// The setup consists of a three way handshake:
-// - Receive initialisation vector 7 bits
-// - Transmit card type 6 bits
-// - Receive Acknowledge 6 bits
-static int32_t setup_phase(legic_card_select_t *p_card) {
- uint8_t len = 0;
-
- // init coordination timestamp
- last_frame_end = GetCountSspClk();
-
- // reset prng
- legic_prng_init(0);
-
- // wait for iv
- int32_t iv = rx_frame(&len);
- if ((len != 7) || (iv < 0)) {
- return -1;
- }
-
- // configure prng
- legic_prng_init(iv);
-
- // reply with card type
- switch (p_card->tagtype) {
- case 0:
- tx_frame(0x0D, 6);
- break;
- case 1:
- tx_frame(0x1D, 6);
- break;
- case 2:
- tx_frame(0x3D, 6);
- break;
- }
-
- // wait for ack
- int32_t ack = rx_frame(&len);
- if ((len != 6) || (ack < 0)) {
- return -1;
- }
-
- // validate data
- switch (p_card->tagtype) {
- case 0:
- if (ack != 0x19) return -1;
- break;
- case 1:
- if (ack != 0x39) return -1;
- break;
- case 2:
- if (ack != 0x39) return -1;
- break;
- }
-
- // During rx the prng is clocked using the variable reader period.
- // Since rx_frame detects end of frame by detecting a code violation,
- // the prng is off by one bit period after each rx phase. Hence, tx
- // code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1).
- // This is not possible for back to back rx, so this quirk reduces
- // the gap by one period.
- last_frame_end += TAG_BIT_PERIOD;
-
- return 0;
-}
-
-static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
- crc_clear(&legic_crc);
- crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz);
- return crc_finish(&legic_crc);
-}
-
-static int32_t connected_phase(legic_card_select_t *p_card) {
- uint8_t len = 0;
-
- // wait for command
- int32_t cmd = rx_frame(&len);
- if (cmd < 0) {
- return -1;
- }
-
- // check if command is LEGIC_READ
- if (len == p_card->cmdsize) {
- // prepare data
- uint8_t byte = legic_mem[cmd >> 1];
- uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);
-
- // transmit data
- tx_frame((crc << 8) | byte, 12);
-
- return 0;
- }
-
- // check if command is LEGIC_WRITE
- if (len == p_card->cmdsize + 8 + 4) {
- // decode data
- uint16_t mask = (1 << p_card->addrsize) - 1;
- uint16_t addr = (cmd >> 1) & mask;
- uint8_t byte = (cmd >> p_card->cmdsize) & 0xff;
- uint8_t crc = (cmd >> (p_card->cmdsize + 8)) & 0xf;
-
- // check received against calculated crc
- uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
- if (calc_crc != crc) {
- Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
- return -1;
- }
-
- // store data
- legic_mem[addr] = byte;
-
- // transmit ack
- tx_ack();
-
- return 0;
- }
-
- return -1;
-}
-
-//-----------------------------------------------------------------------------
-// Command Line Interface
-//
-// Only this function is public / called from appmain.c
-//-----------------------------------------------------------------------------
-
-void LegicRfSimulate(uint8_t cardtype) {
- // configure ARM and FPGA
- init_tag();
-
- // verify command line input
- if (init_card(cardtype, &card) != 0) {
- DbpString("Unknown tagtype.");
- goto OUT;
- }
-
- LED_A_ON();
- DbpString("Starting Legic emulator, press button to end");
- while (!BUTTON_PRESS() && !data_available()) {
- WDT_HIT();
-
- // wait for carrier, restart after timeout
- if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
- continue;
- }
-
- // wait for connection, restart on error
- if (setup_phase(&card)) {
- continue;
- }
-
- // conection is established, process commands until one fails
- while (!connected_phase(&card)) {
- WDT_HIT();
- }
- }
-
-OUT:
- DbpString("Stopped");
- switch_off();
- StopTicks();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/legicrfsim.h b/pm3rdv4rrg/src/main/cpp/armsrc/legicrfsim.h
deleted file mode 100644
index f7be9416..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/legicrfsim.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//-----------------------------------------------------------------------------
-// (c) 2009 Henryk Plötz
-// 2018 AntiCat
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LEGIC RF emulation public interface
-//-----------------------------------------------------------------------------
-
-#ifndef __LEGICRFSIM_H
-#define __LEGICRFSIM_H
-
-#include "common.h"
-
-void LegicRfSimulate(uint8_t cardtype);
-
-#endif /* __LEGICRFSIM_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/lfadc.c b/pm3rdv4rrg/src/main/cpp/armsrc/lfadc.c
deleted file mode 100644
index 04f293e1..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/lfadc.c
+++ /dev/null
@@ -1,299 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LF ADC read/write implementation
-//-----------------------------------------------------------------------------
-
-#include "lfadc.h"
-#include "lfsampling.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-
-// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
-// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
-// Carrier periods (T0) have duration of 8 microseconds (us), which is 1/125000 per second
-// T0 = TIMER_CLOCK1 / 125000 = 192
-//#define T0 192
-
-// Sam7s has three counters, we will use the first TIMER_COUNTER_0 (aka TC0)
-// using TIMER_CLOCK3 (aka AT91C_TC_CLKS_TIMER_DIV3_CLOCK)
-// as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz
-// Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency)
-// T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6
-//#define HITAG_T0 3
-
-//////////////////////////////////////////////////////////////////////////////
-// Global variables
-//////////////////////////////////////////////////////////////////////////////
-
-bool rising_edge = false;
-bool logging = true;
-bool reader_mode = false;
-
-//////////////////////////////////////////////////////////////////////////////
-// Auxiliary functions
-//////////////////////////////////////////////////////////////////////////////
-
-bool lf_test_periods(size_t expected, size_t count) {
- // Compute 10% deviation (integer operation, so rounded down)
- size_t diviation = expected / 10;
- return ((count > (expected - diviation)) && (count < (expected + diviation)));
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Low frequency (LF) adc passthrough functionality
-//////////////////////////////////////////////////////////////////////////////
-uint8_t previous_adc_val = 0;
-
-size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
- size_t periods = 0;
- volatile uint8_t adc_val;
- //uint8_t avg_peak = 140, avg_through = 96;
- // 140 - 127 - 114
- uint8_t avg_peak = 140, avg_through = 106;
- int16_t checked = 0;
-
- while (!BUTTON_PRESS()) {
-
- // only every 100th times, in order to save time when collecting samples.
- if (checked == 1000) {
- if (data_available()) {
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- adc_val = AT91C_BASE_SSC->SSC_RHR;
- periods++;
-
- if (logging) logSampleSimple(adc_val);
-
- // Only test field changes if state of adc values matter
- if (wait == false) {
- // Test if we are locating a field modulation (100% ASK = complete field drop)
- if (detect_gap) {
- // Only return when the field completely dissapeared
- if (adc_val == 0) {
- return periods;
- }
- } else {
- // Trigger on a modulation swap by observing an edge change
- if (rising_edge) {
- if ((previous_adc_val > avg_peak) && (adc_val <= previous_adc_val)) {
- rising_edge = false;
- return periods;
- }
- } else {
- if ((previous_adc_val < avg_through) && (adc_val >= previous_adc_val)) {
- rising_edge = true;
- return periods;
- }
- }
- }
- }
-
- previous_adc_val = adc_val;
- if (periods >= max) return 0;
- }
- }
- if (logging) logSampleSimple(0xFF);
- return 0;
-}
-
-size_t lf_count_edge_periods(size_t max) {
- return lf_count_edge_periods_ex(max, false, false);
-}
-
-size_t lf_detect_gap(size_t max) {
- return lf_count_edge_periods_ex(max, false, true);
-}
-
-void lf_reset_counter() {
- // TODO: find out the correct reset settings for tag and reader mode
- if (reader_mode) {
- // Reset values for reader mode
- rising_edge = false;
- previous_adc_val = 0xFF;
- } else {
- // Reset values for tag/transponder mode
- rising_edge = false;
- previous_adc_val = 0xFF;
- }
-}
-
-bool lf_get_tag_modulation() {
- return (rising_edge == false);
-}
-bool lf_get_reader_modulation() {
- return rising_edge;
-}
-
-void lf_wait_periods(size_t periods) {
- lf_count_edge_periods_ex(periods, true, false);
-}
-
-void lf_init(bool reader, bool simulate) {
-
- StopTicks();
-
- reader_mode = reader;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- if (reader) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
- } else {
- if (simulate)
-// FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
- else
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
-
- }
-
- // Connect the A/D to the peak-detected low-frequency path.
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-
- // Now set up the SSC to get the ADC samples that are now streaming at us.
- FpgaSetupSsc();
-
- // When in reader mode, give the field a bit of time to settle.
- // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered.
- if (reader) {
- // 50 ms
- SpinDelay(50);
- }
-
- // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- LOW(GPIO_SSC_DOUT);
-
- // Enable peripheral Clock for TIMER_CLOCK 0
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
-
- // Enable peripheral Clock for TIMER_CLOCK 1
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
-
- // Clear all leds
- LEDsoff();
-
- // Reset and enable timers
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-
- // Prepare data trace
- uint32_t bufsize = 20000;
-
- // use malloc
- if (logging) initSampleBufferEx(&bufsize, true);
-
- sample_config *sc = getSamplingConfig();
- sc->decimation = 1;
- sc->averaging = 0;
-}
-
-void lf_finalize() {
- // Disable timers
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // return stolen pin to SSP
- AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- LEDsoff();
-
- sample_config *sc = getSamplingConfig();
- sc->decimation = 1;
- sc->averaging = 0;
-
- StartTicks();
-}
-
-size_t lf_detect_field_drop(size_t max) {
- size_t periods = 0;
- volatile uint8_t adc_val;
- int16_t checked = 0;
-
- while (!BUTTON_PRESS()) {
-
- // only every 1000th times, in order to save time when collecting samples.
- if (checked == 1000) {
- if (data_available()) {
- checked = -1;
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- periods++;
- adc_val = AT91C_BASE_SSC->SSC_RHR;
-
- if (logging) logSampleSimple(adc_val);
-
- if (adc_val == 0) {
- rising_edge = false;
- return periods;
- }
-
- if (periods == max) return 0;
- }
- }
- return 0;
-}
-
-void lf_modulation(bool modulation) {
- if (modulation) {
- HIGH(GPIO_SSC_DOUT);
- } else {
- LOW(GPIO_SSC_DOUT);
- }
-}
-
-// simulation
-static void lf_manchester_send_bit(uint8_t bit) {
- lf_modulation(bit != 0);
- lf_wait_periods(16);
- lf_modulation(bit == 0);
- lf_wait_periods(16);
-}
-
-// simulation
-bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len) {
-
- LED_B_ON();
-
- lf_manchester_send_bit(1);
- lf_manchester_send_bit(1);
- lf_manchester_send_bit(1);
- lf_manchester_send_bit(1);
- lf_manchester_send_bit(1);
-
- // Send the content of the frame
- for (size_t i = 0; i < frame_len; i++) {
- lf_manchester_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
- }
-
- LED_B_OFF();
- return true;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/lfadc.h b/pm3rdv4rrg/src/main/cpp/armsrc/lfadc.h
deleted file mode 100644
index 8c33aa77..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/lfadc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// LF ADC read/write implementation
-//-----------------------------------------------------------------------------
-
-#ifndef __LFADC_H__
-#define __LFADC_H__
-
-#include "proxmark3_arm.h"
-#include "common.h"
-#include "cmd.h"
-#include "util.h"
-#include "string.h"
-
-extern bool logging;
-
-bool lf_test_periods(size_t expected, size_t count);
-size_t lf_count_edge_periods(size_t max);
-size_t lf_detect_gap(size_t max);
-void lf_reset_counter();
-
-bool lf_get_tag_modulation();
-bool lf_get_reader_modulation();
-
-void lf_wait_periods(size_t periods);
-//void lf_init(bool reader);
-void lf_init(bool reader, bool simulate);
-void lf_finalize();
-size_t lf_detect_field_drop(size_t max);
-bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len);
-void lf_modulation(bool modulation);
-
-#endif // __LFADC_H__
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/lfops.c b/pm3rdv4rrg/src/main/cpp/armsrc/lfops.c
deleted file mode 100644
index 6a3c2fef..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/lfops.c
+++ /dev/null
@@ -1,2565 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Miscellaneous routines for low frequency tag operations.
-// Tags supported here so far are Texas Instruments (TI), HID, EM4x05, EM410x
-// Also routines for raw mode reading/simulating of LF waveform
-//-----------------------------------------------------------------------------
-
-#include "lfops.h"
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "commonutil.h"
-
-#include "crc16.h"
-#include "string.h"
-#include "printf.h"
-#include "lfdemod.h"
-#include "lfsampling.h"
-#include "protocols.h"
-#include "pmflash.h"
-#include "flashmem.h" // persistence on flash
-
-/*
-Notes about EM4xxx timings.
-
-The timing values differs between cards, we got EM410x, EM43x5, EM445x etc.
-We are trying to unify and enable the Proxmark to easily detect and select correct timings automatic.
-The measures from datasheets doesn't always match correct the hardware features of RDV4 antenans and we still wanted to let other devices with other custom antennas
-still benefit from this repo. This is why its configurable and we use to set these dynamic settings in device external flash memory.
-
-
-// VALUES TAKEN FROM EM4x function: SendForward
-// START_GAP = 440; (55*8) cycles at 125kHz (8us = 1cycle)
-// WRITE_GAP = 128; (16*8)
-// WRITE_1 = 256 32*8; (32*8)
-
-// These timings work for 4469/4269/4305 (with the 55*8 above)
-// WRITE_0 = 23*8 , 9*8
-
-Not about ARM TIMERS
-Short note about timers on Proxmark device ARM. They are a bit differently implemented and gives decent correctness.
-
-SAM7S has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
- TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
-
-New timer implemenation in ticks.c, which is used in LFOPS.c
- 1 μs = 1.5 ticks
- 1 fc = 8 μs = 12 ticks
-
-Terms you find in different datasheets and how they match.
-1 Cycle = 8 microseconds (μs) == 1 field clock (fc)
-
-Note about HITAG timing
-Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
- T0 = TIMER_CLOCK1 / 125000 = 192
-
-
- ==========================================================================================================
- T55x7 Timing
- ==========================================================================================================
-
- ATA5577 Downlink Protocol Timings.
- Note: All absolute times assume TC = 1 / fC = 8 μs (fC = 125 kHz)
-
- Note: These timings are from the datasheet and doesn't map the best to the features of the RVD4 LF antenna.
- RDV4 LF antenna has high voltage and the drop of power when turning off the rf field takes about 1-2 TC longer.
-
- -----------------------------------------------------------------------
- Fixed-bit-length Protocol | Normal Downlink | Fast Downlink |
- ------------------------------+-----------------------------------+-----------------------------------+------
-| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
-|------------+--------+--------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Start gap | | Sgap | 8 | 15 | 50 | 8 | 15 | 50 | Tc |
-| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
-|------------+--------+--------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| coding | 0 data | d0 | 16 | 24 | 32 | 8 | 12 | 16 | Tc |
-| | 1 data | d1 | 48 | 56 | 64 | 24 | 28 | 32 | Tc |
- -------------------------------------------------------------------------------------------------------------
-
- -----------------------------------------------------------------------
- Long Leading Reference | Normal Downlink | Fast Downlink |
- ------------------------------+-----------------------------------+-----------------------------------+------
-| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
-|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Start gap | | Sgap | 8 | 10 | 50 | 8 | 10 | 50 | Tc |
-| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
-|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Write | Ref | | 152 | 160 | 168 | 140 | 144 | 148 | Tc |
-| data | Pulse | dref | 136 clocks + 0 data bit | 132 clocks + 0 data bit | Tc |
-| coding |--------+---------+-----------------------------------+-----------------------------------+------|
-| | 0 data | d0 |dref – 143 |dref – 136 |dref – 128 |dref – 135 |dref – 132 |dref – 124 | Tc |
-| | 1 data | d1 |dref – 111 |dref – 104 |dref – 96 |dref – 119 |dref – 116 |dref – 112 | Tc |
- -------------------------------------------------------------------------------------------------------------
-
- -----------------------------------------------------------------------
- Leading-zero Reference | Normal Downlink | Fast Downlink |
- ------------------------------+-----------------------------------+-----------------------------------+------
-| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
-|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Start gap | | Sgap | 8 | 10 | 50 | 8 | 10 | 50 | Tc |
-| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
-|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Write | Ref | dref | 12 | – | 72 | 8 | – | 68 | Tc |
-| data | 0 data | d0 | dref – 7 | dref | dref + 8 | dref – 3 | dref | dref + 4 | Tc |
-| coding | 1 data | d1 | dref + 9 | dref + 16 | dref + 24 | dref + 5 | dref + 8 | dref + 12 | Tc |
- -------------------------------------------------------------------------------------------------------------
-
- -----------------------------------------------------------------------
- 1-of-4 Coding | Normal Downlink | Fast Downlink |
- ------------------------------+-----------------------------------+-----------------------------------+------
-| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
-|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Start gap | | Sgap | 8 | 10 | 50 | 8 | 10 | 50 | Tc |
-| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
-|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
-| Write | Ref 00 | dref | 8 | – | 68 | 12 | – | 72 | Tc |
-| data |00 data | d00 | dref – 7 | dref | dref + 8 | dref – 3 | dref | dref+ 4 | Tc |
-| coding |01 data | d01 | dref + 9 | dref + 16 | dref + 24 | dref + 5 | dref + 8 | dref + 12 | Tc |
-| |10 data | d10 | dref + 25 | dref + 32 | dref + 40 | dref + 13 | dref + 16 | dref + 20 | Tc |
-| |11 data | d11 | dref + 41 | dref + 48 | dref + 56 | dref + 21 | dref + 24 | dref + 28 | Tc |
- -------------------------------------------------------------------------------------------------------------
-
-Initial values if not in flash
-
- SG = Start gap
- WG = Write gap
- RG = Read gap
-
- Explainations for array T55xx_Timing below
-
- 0 1 2 3
- SG WG Bit 00 Bit 01 Bit 10 Bit 11 RG
- --------------------------------------------------------------------
- { 29 , 17 , 15 , 47 , 0 , 0 , 15 }, // Default Fixed
- { 29 , 17 , 15 , 50 , 0 , 0 , 15 }, // Long Leading Ref.
- { 29 , 17 , 15 , 40 , 0 , 0 , 15 }, // Leading 0
- { 29 , 17 , 15 , 31 , 47 , 63 , 15 } // 1 of 4
-*/
-t55xx_configurations_t T55xx_Timing = {
- {
-#ifdef WITH_FLASH
-// PM3RDV4
- { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Default Fixed
- { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Long Leading Ref.
- { 29 * 8, 17 * 8, 15 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
- { 29 * 8, 17 * 8, 15 * 8, 31 * 8, 15 * 8, 47 * 8, 63 * 8 } // 1 of 4
-#else
-// PM3OTHER or like offical repo
- { 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Default Fixed
- { 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref.
- { 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
- { 31 * 8, 20 * 8, 18 * 8, 34 * 8, 15 * 8, 50 * 8, 66 * 8 } // 1 of 4
-#endif
- }
-};
-
-
-// Some defines for readability
-#define T55XX_DLMODE_FIXED 0 // Default Mode
-#define T55XX_DLMODE_LLR 1 // Long Leading Reference
-#define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero
-#define T55XX_DLMODE_1OF4 3 // 1 of 4
-#define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference
-
-// ATA55xx shared presets & routines
-static uint32_t GetT55xxClockBit(uint32_t clock) {
- switch (clock) {
- case 128:
- return T55x7_BITRATE_RF_128;
- case 100:
- return T55x7_BITRATE_RF_100;
- case 64:
- return T55x7_BITRATE_RF_64;
- case 50:
- return T55x7_BITRATE_RF_50;
- case 40:
- return T55x7_BITRATE_RF_40;
- case 32:
- return T55x7_BITRATE_RF_32;
- case 16:
- return T55x7_BITRATE_RF_16;
- case 8:
- return T55x7_BITRATE_RF_8;
- default :
- return 0;
- }
-}
-
-void printT55xxConfig(void) {
-
-#define PRN_NA sprintf(s + strlen(s), _RED_("N/A") "| ");
-
- DbpString(_BLUE_("LF T55XX config"));
- Dbprintf(" [r] [a] [b] [c] [d] [e] [f] [g]");
- Dbprintf(" mode |start|write|write|write| read|write|write");
- Dbprintf(" | gap | gap | 0 | 1 | gap | 2 | 3");
- Dbprintf("---------------------------+-----+-----+-----+-----+-----+-----+------");
-
- for (uint8_t i = 0; i < 4; i++) {
-
- char s[160];
- memset(s, 0, sizeof(s));
-
- switch (i) {
- case T55XX_DLMODE_FIXED :
- sprintf(s, _YELLOW_("fixed bit length") _GREEN_("(default)") "|");
- break;
- case T55XX_DLMODE_LLR :
- sprintf(s, _YELLOW_(" long leading reference") "|");
- break;
- case T55XX_DLMODE_LEADING_ZERO :
- sprintf(s, _YELLOW_(" leading zero") "|");
- break;
- case T55XX_DLMODE_1OF4 :
- sprintf(s, _YELLOW_(" 1 of 4 coding reference") "|");
- break;
- default:
- break;
- }
-
- if (T55xx_Timing.m[i].start_gap != 0xFFFF)
- sprintf(s + strlen(s), " %3d | ", T55xx_Timing.m[i].start_gap / 8);
- else
- PRN_NA;
-
- if (T55xx_Timing.m[i].write_gap != 0xFFFF)
- sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_gap / 8);
- else
- PRN_NA;
-
- if (T55xx_Timing.m[i].write_0 != 0xFFFF)
- sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_0 / 8);
- else
- PRN_NA;
-
- if (T55xx_Timing.m[i].write_1 != 0xFFFF)
- sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_1 / 8);
- else
- PRN_NA;
-
- if (T55xx_Timing.m[i].read_gap != 0xFFFF)
- sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].read_gap / 8);
- else
- PRN_NA;
-
- if (T55xx_Timing.m[i].write_2 != 0xFFFF && i == T55XX_DLMODE_1OF4)
- sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_2 / 8);
- else
- PRN_NA
-
- if (T55xx_Timing.m[i].write_3 != 0xFFFF && i == T55XX_DLMODE_1OF4)
- sprintf(s + strlen(s), "%3d | ", T55xx_Timing.m[i].write_3 / 8);
- else
- PRN_NA;
-
- s[strlen(s)] = 0;
- DbpString(s);
- }
- DbpString("");
-}
-
-void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c) {
- for (uint8_t i = 0; i < 4; i++) {
- if (c->m[i].start_gap != 0)
- T55xx_Timing.m[i].start_gap = c->m[i].start_gap;
-
- if (c->m[i].write_gap != 0)
- T55xx_Timing.m[i].write_gap = c->m[i].write_gap;
-
- if (c->m[i].write_0 != 0)
- T55xx_Timing.m[i].write_0 = c->m[i].write_0;
-
- if (c->m[i].write_1 != 0)
- T55xx_Timing.m[i].write_1 = c->m[i].write_1;
-
- if (i == T55XX_DLMODE_1OF4) {
- if (c->m[i].write_2 != 0)
- T55xx_Timing.m[i].write_2 = c->m[i].write_2;
-
- if (c->m[i].write_3 != 0)
- T55xx_Timing.m[i].write_3 = c->m[i].write_3;
-
- } else {
- T55xx_Timing.m[i].write_2 = 0x00;
- T55xx_Timing.m[i].write_3 = 0x00;
- }
- if (c->m[i].read_gap != 0)
- T55xx_Timing.m[i].read_gap = c->m[i].read_gap;
- }
-
- printT55xxConfig();
-
-#ifdef WITH_FLASH
- // shall persist to flashmem
- if (arg0 == 0) {
- BigBuf_free();
- return;
- }
-
- if (!FlashInit()) {
- BigBuf_free();
- return;
- }
-
- uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
- Flash_CheckBusy(BUSY_TIMEOUT);
- uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
- if (res == 0) {
- FlashStop();
- BigBuf_free();
- return;
- }
-
- memcpy(buf, &T55xx_Timing, T55XX_CONFIG_LEN);
-
- // delete old configuration
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- Flash_Erase4k(3, 0xD);
-
- // write new
- res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
-
- if (res == T55XX_CONFIG_LEN && DBGLEVEL > 1) {
- DbpString("T55XX Config save " _GREEN_("success"));
- }
-
- BigBuf_free();
-#endif
-}
-
-t55xx_configurations_t *getT55xxConfig(void) {
- return &T55xx_Timing;//_FixedBit;
-}
-
-void loadT55xxConfig(void) {
-#ifdef WITH_FLASH
-
- if (!FlashInit()) {
- return;
- }
-
- uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
-
- Flash_CheckBusy(BUSY_TIMEOUT);
- uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
- FlashStop();
-
- // verify read mem is actual data.
- uint8_t cntA = T55XX_CONFIG_LEN, cntB = T55XX_CONFIG_LEN;
- for (int i = 0; i < T55XX_CONFIG_LEN; i++) {
- if (buf[i] == 0xFF) cntA--;
- if (buf[i] == 0x00) cntB--;
- }
- if (!cntA || !cntB) {
- BigBuf_free();
- return;
- }
-
- if (buf[0] != 0xFF) // if not set for clear
- memcpy((uint8_t *)&T55xx_Timing, buf, T55XX_CONFIG_LEN);
-
- if (isok == T55XX_CONFIG_LEN) {
- if (DBGLEVEL > 1) DbpString("T55XX Config load success");
- }
-#endif
-}
-
-/**
- * Function to do a modulation and then get samples.
- * @param delay_off
- * @param period_0
- * @param period_1
- * @param command (in binary char array)
- */
-void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) {
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- // use lf config settings
- sample_config *sc = getSamplingConfig();
-
-
- // Make sure the tag is reset
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- // start timer
- StartTicks();
-
- WaitMS(100);
-
- // clear read buffer
- BigBuf_Clear_keep_EM();
-
- LFSetupFPGAForADC(sc->divisor, true);
-
- // little more time for the tag to fully power up
- WaitMS(20);
-
- // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods.
- bool bitbang = (delay_off == 0);
- // now modulate the reader field
- if (bitbang) {
- // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly...
- uint8_t hack_cnt = 7;
- if (period_0 < hack_cnt || period_1 < hack_cnt) {
- DbpString("[!] Warning periods cannot be less than 7us in bit bang mode");
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
- reply_ng(CMD_LF_MOD_THEN_ACQ_RAW_ADC, PM3_EINVARG, NULL, 0);
- return;
- }
-
- // hack2 needed--- it appears to take about 8-16us to turn the antenna back on
- // leading to ~ 1 to 2 125kHz samples extra in every off period
- // so we should test for last 0 before next 1 and reduce period_0 by this extra amount...
- // but is this time different for every antenna or other hw builds??? more testing needed
-
- // prime cmd_len to save time comparing strings while modulating
- int cmd_len = 0;
- while (command[cmd_len] != '\0' && command[cmd_len] != ' ')
- cmd_len++;
-
- int counter = 0;
- bool off = false;
- for (counter = 0; counter < cmd_len; counter++) {
- // if cmd = 0 then turn field off
- if (command[counter] == '0') {
- // if field already off leave alone (affects timing otherwise)
- if (off == false) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
- off = true;
- }
- // note we appear to take about 7us to switch over (or run the if statements/loop...)
- WaitUS(period_0 - hack_cnt);
- // else if cmd = 1 then turn field on
- } else {
- // if field already on leave alone (affects timing otherwise)
- if (off) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
- LED_D_ON();
- off = false;
- }
- // note we appear to take about 7us to switch over (or run the if statements/loop...)
- WaitUS(period_1 - hack_cnt);
- }
- }
- } else { // old mode of cmd read using delay as off period
- while (*command != '\0' && *command != ' ') {
- LED_D_ON();
- if (*(command++) == '0')
- TurnReadLFOn(period_0);
- else
- TurnReadLFOn(period_1);
-
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- WaitUS(delay_off);
- }
-
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
-
- // now do the read
- DoAcquisition_config(true, 0);
-
- // Turn off antenna
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- // tell client we are done
- reply_ng(CMD_LF_MOD_THEN_ACQ_RAW_ADC, PM3_SUCCESS, NULL, 0);
-}
-
-/* blank r/w tag data stream
-...0000000000000000 01111111
-1010101010101010101010101010101010101010101010101010101010101010
-0011010010100001
-01111111
-101010101010101[0]000...
-
-[5555fe852c5555555555555555fe0000]
-*/
-void ReadTItag(void) {
- StartTicks();
- // some hardcoded initial params
- // when we read a TI tag we sample the zerocross line at 2MHz
- // TI tags modulate a 1 as 16 cycles of 123.2kHz
- // TI tags modulate a 0 as 16 cycles of 134.2kHz
-#define FSAMPLE 2000000
-#define FREQLO 123200
-#define FREQHI 134200
-
- signed char *dest = (signed char *)BigBuf_get_addr();
- uint16_t n = BigBuf_max_traceLen();
- // 128 bit shift register [shift3:shift2:shift1:shift0]
- uint32_t shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;
-
- int i, cycles = 0, samples = 0;
- // how many sample points fit in 16 cycles of each frequency
- uint32_t sampleslo = (FSAMPLE << 4) / FREQLO, sampleshi = (FSAMPLE << 4) / FREQHI;
- // when to tell if we're close enough to one freq or another
- uint32_t threshold = (sampleslo - sampleshi + 1) >> 1;
-
- // TI tags charge at 134.2kHz
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz
-
- // Place FPGA in passthrough mode, in this mode the CROSS_LO line
- // connects to SSP_DIN and the SSP_DOUT logic level controls
- // whether we're modulating the antenna (high)
- // or listening to the antenna (low)
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
-
- // get TI tag data into the buffer
- AcquireTiType();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- for (i = 0; i < n - 1; i++) {
- // count cycles by looking for lo to hi zero crossings
- if ((dest[i] < 0) && (dest[i + 1] > 0)) {
- cycles++;
- // after 16 cycles, measure the frequency
- if (cycles > 15) {
- cycles = 0;
- samples = i - samples; // number of samples in these 16 cycles
-
- // TI bits are coming to us lsb first so shift them
- // right through our 128 bit right shift register
- shift0 = (shift0 >> 1) | (shift1 << 31);
- shift1 = (shift1 >> 1) | (shift2 << 31);
- shift2 = (shift2 >> 1) | (shift3 << 31);
- shift3 >>= 1;
-
- // check if the cycles fall close to the number
- // expected for either the low or high frequency
- if ((samples > (sampleslo - threshold)) && (samples < (sampleslo + threshold))) {
- // low frequency represents a 1
- shift3 |= (1u << 31);
- } else if ((samples > (sampleshi - threshold)) && (samples < (sampleshi + threshold))) {
- // high frequency represents a 0
- } else {
- // probably detected a gay waveform or noise
- // use this as gaydar or discard shift register and start again
- shift3 = shift2 = shift1 = shift0 = 0;
- }
- samples = i;
-
- // for each bit we read, test if we've detected a valid tag
-
- // if we see 17 zeroes followed by 6 ones, we might have a tag
- // remember the bits are backwards
- if (((shift0 & 0x7fffff) == 0x7e0000)) {
- // if start and end bytes match, we have a tag so break out of the loop
- if (((shift0 >> 16) & 0xff) == ((shift3 >> 8) & 0xff)) {
- cycles = 0xF0B; //use this as a flag (ugly but whatever)
- break;
- }
- }
- }
- }
- }
-
- // if flag is set we have a tag
- if (cycles != 0xF0B) {
- DbpString("Info: No valid tag detected.");
- } else {
- // put 64 bit data into shift1 and shift0
- shift0 = (shift0 >> 24) | (shift1 << 8);
- shift1 = (shift1 >> 24) | (shift2 << 8);
-
- // align 16 bit crc into lower half of shift2
- shift2 = ((shift2 >> 24) | (shift3 << 8)) & 0x0ffff;
-
- // if r/w tag, check ident match
- if (shift3 & (1 << 15)) {
- DbpString("Info: TI tag is rewriteable");
- // only 15 bits compare, last bit of ident is not valid
- if (((shift3 >> 16) ^ shift0) & 0x7fff) {
- DbpString("Error: Ident mismatch!");
- } else {
- DbpString("Info: TI tag ident is valid");
- }
- } else {
- DbpString("Info: TI tag is readonly");
- }
-
- // WARNING the order of the bytes in which we calc crc below needs checking
- // i'm 99% sure the crc algorithm is correct, but it may need to eat the
- // bytes in reverse or something
- // calculate CRC
- uint32_t crc = 0;
-
- crc = update_crc16(crc, (shift0) & 0xff);
- crc = update_crc16(crc, (shift0 >> 8) & 0xff);
- crc = update_crc16(crc, (shift0 >> 16) & 0xff);
- crc = update_crc16(crc, (shift0 >> 24) & 0xff);
- crc = update_crc16(crc, (shift1) & 0xff);
- crc = update_crc16(crc, (shift1 >> 8) & 0xff);
- crc = update_crc16(crc, (shift1 >> 16) & 0xff);
- crc = update_crc16(crc, (shift1 >> 24) & 0xff);
-
- Dbprintf("Info: Tag data: %x%08x, crc=%x", (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF);
- if (crc != (shift2 & 0xffff)) {
- Dbprintf("Error: CRC mismatch, expected %x", (unsigned int)crc);
- } else {
- DbpString("Info: CRC is good");
- }
- }
- StopTicks();
-}
-
-void WriteTIbyte(uint8_t b) {
- int i = 0;
-
- // modulate 8 bits out to the antenna
- for (i = 0; i < 8; i++) {
- if (b & (1 << i)) {
- // stop modulating antenna 1ms
- LOW(GPIO_SSC_DOUT);
- WaitUS(1000);
- // modulate antenna 1ms
- HIGH(GPIO_SSC_DOUT);
- WaitUS(1000);
- } else {
- // stop modulating antenna 0.3ms
- LOW(GPIO_SSC_DOUT);
- WaitUS(300);
- // modulate antenna 1.7ms
- HIGH(GPIO_SSC_DOUT);
- WaitUS(1700);
- }
- }
-}
-
-void AcquireTiType(void) {
- int i, j, n;
- // tag transmission is <20ms, sampling at 2M gives us 40K samples max
- // each sample is 1 bit stuffed into a uint32_t so we need 1250 uint32_t
-#define TIBUFLEN 1250
-
- // clear buffer
- uint32_t *buf = (uint32_t *)BigBuf_get_addr();
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_ext(false);
-
- // Set up the synchronous serial port
- AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;
- AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN;
-
- // steal this pin from the SSP and use it to control the modulation
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
-
- AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
- AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;
-
- // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long
- // 48/2 = 24 MHz clock must be divided by 12
- AT91C_BASE_SSC->SSC_CMR = 12;
-
- AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(0);
- AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(32) | AT91C_SSC_MSBF;
- // Transmit Clock Mode Register
- AT91C_BASE_SSC->SSC_TCMR = 0;
- // Transmit Frame Mode Register
- AT91C_BASE_SSC->SSC_TFMR = 0;
- // iceman, FpgaSetupSsc() ?? the code above? can it be replaced?
- LED_D_ON();
-
- // modulate antenna
- HIGH(GPIO_SSC_DOUT);
-
- // Charge TI tag for 50ms.
- WaitMS(50);
-
- // stop modulating antenna and listen
- LOW(GPIO_SSC_DOUT);
-
- LED_D_OFF();
-
- i = 0;
- for (;;) {
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- buf[i] = AT91C_BASE_SSC->SSC_RHR; // store 32 bit values in buffer
- i++;
- if (i >= TIBUFLEN) break;
- }
- WDT_HIT();
- }
-
- // return stolen pin to SSP
- AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
-
- char *dest = (char *)BigBuf_get_addr();
- n = TIBUFLEN * 32;
-
- // unpack buffer
- for (i = TIBUFLEN - 1; i >= 0; i--) {
- for (j = 0; j < 32; j++) {
- if (buf[i] & (1u << j)) {
- dest[--n] = 1;
- } else {
- dest[--n] = -1;
- }
- }
- }
-
- // reset SSC
- FpgaSetupSsc();
-}
-
-// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc
-// if crc provided, it will be written with the data verbatim (even if bogus)
-// if not provided a valid crc will be computed from the data and written.
-void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- if (crc == 0) {
- crc = update_crc16(crc, (idlo) & 0xff);
- crc = update_crc16(crc, (idlo >> 8) & 0xff);
- crc = update_crc16(crc, (idlo >> 16) & 0xff);
- crc = update_crc16(crc, (idlo >> 24) & 0xff);
- crc = update_crc16(crc, (idhi) & 0xff);
- crc = update_crc16(crc, (idhi >> 8) & 0xff);
- crc = update_crc16(crc, (idhi >> 16) & 0xff);
- crc = update_crc16(crc, (idhi >> 24) & 0xff);
- }
- Dbprintf("Writing to tag: %x%08x, crc=%x", idhi, idlo, crc);
-
- // TI tags charge at 134.2kHz
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz
- // Place FPGA in passthrough mode, in this mode the CROSS_LO line
- // connects to SSP_DIN and the SSP_DOUT logic level controls
- // whether we're modulating the antenna (high)
- // or listening to the antenna (low)
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
- StartTicks();
-
- LED_A_ON();
-
- // steal this pin from the SSP and use it to control the modulation
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
-
- // writing algorithm:
- // a high bit consists of a field off for 1ms and field on for 1ms
- // a low bit consists of a field off for 0.3ms and field on for 1.7ms
- // initiate a charge time of 50ms (field on) then immediately start writing bits
- // start by writing 0xBB (keyword) and 0xEB (password)
- // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)
- // finally end with 0x0300 (write frame)
- // all data is sent lsb first
- // finish with 50ms programming time
-
- // modulate antenna
- HIGH(GPIO_SSC_DOUT);
- WaitMS(50); // charge time
-
- WriteTIbyte(0xbb); // keyword
- WriteTIbyte(0xeb); // password
- WriteTIbyte((idlo) & 0xff);
- WriteTIbyte((idlo >> 8) & 0xff);
- WriteTIbyte((idlo >> 16) & 0xff);
- WriteTIbyte((idlo >> 24) & 0xff);
- WriteTIbyte((idhi) & 0xff);
- WriteTIbyte((idhi >> 8) & 0xff);
- WriteTIbyte((idhi >> 16) & 0xff);
- WriteTIbyte((idhi >> 24) & 0xff); // data hi to lo
- WriteTIbyte((crc) & 0xff); // crc lo
- WriteTIbyte((crc >> 8) & 0xff); // crc hi
- WriteTIbyte(0x00); // write frame lo
- WriteTIbyte(0x03); // write frame hi
- HIGH(GPIO_SSC_DOUT);
- WaitMS(50); // programming time
-
- LED_A_OFF();
-
- // get TI tag data into the buffer
- AcquireTiType();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("Now use `lf ti read` to check");
- StopTicks();
-}
-
-// note: a call to FpgaDownloadAndGo(FPGA_BITSTREAM_LF) must be done before, but
-// this may destroy the bigbuf so be sure this is called before calling SimulateTagLowFrequencyEx
-void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles) {
-
- // start us timer
- StartTicks();
-
- //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE );
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
- WaitMS(20);
-
- int i = 0, x = 0;
- uint8_t *buf = BigBuf_get_addr();
-
- // set frequency, get values from 'lf config' command
- sample_config *sc = getSamplingConfig();
-
- if ((sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255))
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz
- else if (sc->divisor == 0)
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- else
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
-
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
-
- uint16_t check = 0;
-
- for (;;) {
-
- if (numcycles > -1) {
- if (x != numcycles) {
- ++x;
- } else {
- // exit without turning off field
- return;
- }
- }
-
- if (ledcontrol) LED_D_ON();
-
- // wait until SSC_CLK goes HIGH
- // used as a simple detection of a reader field?
- while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
- WDT_HIT();
- if (check == 1000) {
- if (data_available() || BUTTON_PRESS())
- goto OUT;
- check = 0;
- }
- ++check;
- }
-
- if (ledcontrol) LED_D_OFF();
-
- if (buf[i])
- OPEN_COIL();
- else
- SHORT_COIL();
-
- check = 0;
-
- //wait until SSC_CLK goes LOW
- while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
- WDT_HIT();
- if (check == 1000) {
- if (data_available() || BUTTON_PRESS())
- goto OUT;
- check = 0;
- }
- ++check;
- }
-
- i++;
- if (i == period) {
- i = 0;
- if (gap) {
- SHORT_COIL();
- WaitUS(gap);
- }
- }
- }
-OUT:
- StopTicks();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
-}
-
-void SimulateTagLowFrequency(int period, int gap, bool ledcontrol) {
- SimulateTagLowFrequencyEx(period, gap, ledcontrol, -1);
-}
-
-
-#define DEBUG_FRAME_CONTENTS 1
-void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen) {
-}
-
-// compose fc/X fc/Y waveform (FSKx)
-static void fcAll(uint8_t fc, int *n, uint8_t clock, int16_t *remainder) {
- uint8_t *dest = BigBuf_get_addr();
- uint8_t halfFC = fc >> 1;
- uint8_t wavesPerClock = (clock + *remainder) / fc;
- // loop through clock - step field clock
- for (uint8_t idx = 0; idx < wavesPerClock; idx++) {
- // put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave)
- memset(dest + (*n), 0, fc - halfFC); //in case of odd number use extra here
- memset(dest + (*n) + (fc - halfFC), 1, halfFC);
- *n += fc;
- }
- *remainder = (clock + *remainder) % fc;
- // if we've room for more than a half wave, add a full wave and use negative remainder
- if (*remainder > halfFC) {
- memset(dest + (*n), 0, fc - halfFC); //in case of odd number use extra here
- memset(dest + (*n) + (fc - halfFC), 1, halfFC);
- *n += fc;
- *remainder -= fc;
- }
-}
-
-// prepare a waveform pattern in the buffer based on the ID given then
-// simulate a HID tag until the button is pressed
-void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol, int numcycles) {
-
- /*
- HID tag bitstream format
- The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits
- A 1 bit is represented as 6 fc8 and 5 fc10 patterns (manchester 10) during 2 clock periods. (1bit = 1clock period)
- A 0 bit is represented as 5 fc10 and 6 fc8 patterns (manchester 01)
- A fc8 is inserted before every 4 bits
- A special start of frame pattern is used consisting a0b0 where a and b are neither 0
- nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)
-
- FSK2a
- bit 1 = fc10
- bit 0 = fc8
- */
-
- // special start of frame marker containing invalid Manchester bit sequences
- uint8_t bits[8 + 8 * 2 + 84 * 2] = { 0, 0, 0, 1, 1, 1, 0, 1 };
- uint8_t bitlen = 0;
- uint16_t n = 8;
-
- if (longFMT) {
- // Ensure no more than 84 bits supplied
- if (hi2 > 0xFFFFF) {
- DbpString("Tags can only have 84 bits.");
- return;
- }
- bitlen = 8 + 8 * 2 + 84 * 2;
- hi2 |= 0x9E00000; // 9E: long format identifier
- manchesterEncodeUint32(hi2, 16 + 12, bits, &n);
- manchesterEncodeUint32(hi, 32, bits, &n);
- manchesterEncodeUint32(lo, 32, bits, &n);
- } else {
-
- if (hi > 0xFFF) {
- DbpString("[!] tags can only have 44 bits. - USE lf simfsk for larger tags");
- return;
- }
- bitlen = 8 + 44 * 2;
- manchesterEncodeUint32(hi, 12, bits, &n);
- manchesterEncodeUint32(lo, 32, bits, &n);
- }
- CmdFSKsimTAGEx(10, 8, 0, 50, bitlen, bits, ledcontrol, numcycles);
-}
-
-void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol) {
- CmdHIDsimTAGEx(hi2, hi, lo, longFMT, ledcontrol, -1);
- reply_ng(CMD_LF_HID_SIMULATE, PM3_EOPABORTED, NULL, 0);
-}
-
-// prepare a waveform pattern in the buffer based on the ID given then
-// simulate a FSK tag until the button is pressed
-// arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock
-void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol, int numcycles) {
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(false);
-
- int n = 0, i = 0;
- int16_t remainder = 0;
-
- if (separator) {
- //int fsktype = ( fchigh == 8 && fclow == 5) ? 1 : 2;
- //fcSTT(&n);
- }
- for (i = 0; i < bitslen; i++) {
- if (bits[i])
- fcAll(fchigh, &n, clk, &remainder);
- else
- fcAll(fclow, &n, clk, &remainder);
- }
-
- WDT_HIT();
-
- Dbprintf("Simulating with fcHigh: %d, fcLow: %d, clk: %d, STT: %d, n: %d", fchigh, fclow, clk, separator, n);
-
- if (ledcontrol) LED_A_ON();
- SimulateTagLowFrequencyEx(n, 0, ledcontrol, numcycles);
- if (ledcontrol) LED_A_OFF();
-}
-
-// prepare a waveform pattern in the buffer based on the ID given then
-// simulate a FSK tag until the button is pressed
-// arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock
-void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol) {
- CmdFSKsimTAGEx(fchigh, fclow, separator, clk, bitslen, bits, ledcontrol, -1);
- reply_ng(CMD_LF_FSK_SIMULATE, PM3_EOPABORTED, NULL, 0);
-}
-
-// compose ask waveform for one bit(ASK)
-static void askSimBit(uint8_t c, int *n, uint8_t clock, uint8_t manchester) {
- uint8_t *dest = BigBuf_get_addr();
- uint8_t halfClk = clock / 2;
- // c = current bit 1 or 0
- if (manchester == 1) {
- memset(dest + (*n), c, halfClk);
- memset(dest + (*n) + halfClk, c ^ 1, halfClk);
- } else {
- memset(dest + (*n), c, clock);
- }
- *n += clock;
-}
-
-static void biphaseSimBit(uint8_t c, int *n, uint8_t clock, uint8_t *phase) {
- uint8_t *dest = BigBuf_get_addr();
- uint8_t halfClk = clock / 2;
- if (c) {
- memset(dest + (*n), c ^ 1 ^ *phase, halfClk);
- memset(dest + (*n) + halfClk, c ^ *phase, halfClk);
- } else {
- memset(dest + (*n), c ^ *phase, clock);
- *phase ^= 1;
- }
- *n += clock;
-}
-
-static void stAskSimBit(int *n, uint8_t clock) {
- uint8_t *dest = BigBuf_get_addr();
- uint8_t halfClk = clock / 2;
- //ST = .5 high .5 low 1.5 high .5 low 1 high
- memset(dest + (*n), 1, halfClk);
- memset(dest + (*n) + halfClk, 0, halfClk);
- memset(dest + (*n) + clock, 1, clock + halfClk);
- memset(dest + (*n) + clock * 2 + halfClk, 0, halfClk);
- memset(dest + (*n) + clock * 3, 1, clock);
- *n += clock * 4;
-}
-static void leadingZeroAskSimBits(int *n, uint8_t clock) {
- uint8_t *dest = BigBuf_get_addr();
- memset(dest + (*n), 0, clock * 8);
- *n += clock * 8;
-}
-/*
-static void leadingZeroBiphaseSimBits(int *n, uint8_t clock, uint8_t *phase) {
- uint8_t *dest = BigBuf_get_addr();
- for (uint8_t i = 0; i < 8; i++) {
- memset(dest + (*n), 0 ^ *phase, clock);
- *phase ^= 1;
- *n += clock;
- }
-}
-*/
-
-
-// args clock, ask/man or askraw, invert, transmission separator
-void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- set_tracing(false);
-
- int n = 0, i = 0;
-
- if (encoding == 2) { //biphase
- uint8_t phase = 0;
-
-// iceman, if I add this, the demod includes these extra zero and detection fails.
-// now, I only need to figure out just to add carrier without modulation
-// the old bug, with adding ask zeros messed up the phase variable and deteion failed because of it in LF FDX
-// leadingZeroBiphaseSimBits(&n, clk, &phase);
-
- for (i = 0; i < size; i++) {
- biphaseSimBit(bits[i] ^ invert, &n, clk, &phase);
- }
- if (phase == 1) { //run a second set inverted to keep phase in check
- for (i = 0; i < size; i++) {
- biphaseSimBit(bits[i] ^ invert, &n, clk, &phase);
- }
- }
- } else { // ask/manchester || ask/raw
-
- leadingZeroAskSimBits(&n, clk);
-
- for (i = 0; i < size; i++) {
- askSimBit(bits[i] ^ invert, &n, clk, encoding);
- }
- if (encoding == 0 && bits[0] == bits[size - 1]) { //run a second set inverted (for ask/raw || biphase phase)
- for (i = 0; i < size; i++) {
- askSimBit(bits[i] ^ invert ^ 1, &n, clk, encoding);
- }
- }
- }
- if (separator == 1 && encoding == 1)
- stAskSimBit(&n, clk);
- else if (separator == 1)
- Dbprintf("sorry but separator option not yet available");
-
- WDT_HIT();
-
- Dbprintf("Simulating with clk: %d, invert: %d, encoding: %s (%d), separator: %d, n: %d"
- , clk
- , invert
- , (encoding == 2) ? "BI" : (encoding == 1) ? "ASK" : "RAW"
- , encoding
- , separator
- , n
- );
-
- if (ledcontrol) LED_A_ON();
- SimulateTagLowFrequency(n, 0, ledcontrol);
- if (ledcontrol) LED_A_OFF();
- reply_ng(CMD_LF_ASK_SIMULATE, PM3_EOPABORTED, NULL, 0);
-}
-
-//carrier can be 2,4 or 8
-static void pskSimBit(uint8_t waveLen, int *n, uint8_t clk, uint8_t *curPhase, bool phaseChg) {
- uint8_t *dest = BigBuf_get_addr();
- uint8_t halfWave = waveLen / 2;
- //uint8_t idx;
- int i = 0;
- if (phaseChg) {
- // write phase change
- memset(dest + (*n), *curPhase ^ 1, halfWave);
- memset(dest + (*n) + halfWave, *curPhase, halfWave);
- *n += waveLen;
- *curPhase ^= 1;
- i += waveLen;
- }
- //write each normal clock wave for the clock duration
- for (; i < clk; i += waveLen) {
- memset(dest + (*n), *curPhase, halfWave);
- memset(dest + (*n) + halfWave, *curPhase ^ 1, halfWave);
- *n += waveLen;
- }
-}
-
-// args clock, carrier, invert,
-void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- set_tracing(false);
-
- int n = 0, i = 0;
- uint8_t curPhase = 0;
- for (i = 0; i < size; i++) {
- if (bits[i] == curPhase) {
- pskSimBit(carrier, &n, clk, &curPhase, false);
- } else {
- pskSimBit(carrier, &n, clk, &curPhase, true);
- }
- }
-
- WDT_HIT();
-
- Dbprintf("Simulating with Carrier: %d, clk: %d, invert: %d, n: %d", carrier, clk, invert, n);
-
- if (ledcontrol) LED_A_ON();
- SimulateTagLowFrequency(n, 0, ledcontrol);
- if (ledcontrol) LED_A_OFF();
- reply_ng(CMD_LF_PSK_SIMULATE, PM3_EOPABORTED, NULL, 0);
-}
-
-// compose nrz waveform for one bit(NRZ)
-static void nrzSimBit(uint8_t c, int *n, uint8_t clock) {
- uint8_t *dest = BigBuf_get_addr();
-// uint8_t halfClk = clock / 2;
- // c = current bit 1 or 0
- memset(dest + (*n), c, clock);
- *n += clock;
-}
-
-// args clock,
-void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) {
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- set_tracing(false);
-
- int n = 0, i = 0;
-
- // NRZ
-
- leadingZeroAskSimBits(&n, clk);
-
- for (i = 0; i < size; i++) {
- nrzSimBit(bits[i] ^ invert, &n, clk);
- }
-
- if (bits[0] == bits[size - 1]) {
- for (i = 0; i < size; i++) {
- nrzSimBit(bits[i] ^ invert ^ 1, &n, clk);
- }
- }
-
- if (separator == 1)
- Dbprintf("sorry but separator option not yet available");
-
- WDT_HIT();
-
- Dbprintf("Simulating with clk: %d, invert: %d, separator: %d, n: %d"
- , clk
- , invert
- , separator
- , n
- );
-
- if (ledcontrol) LED_A_ON();
- SimulateTagLowFrequency(n, 0, ledcontrol);
- if (ledcontrol) LED_A_OFF();
- reply_ng(CMD_LF_NRZ_SIMULATE, PM3_EOPABORTED, NULL, 0);
-}
-
-// loop to get raw HID waveform then FSK demodulate the TAG ID from it
-void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) {
- uint8_t *dest = BigBuf_get_addr();
- size_t size;
- uint32_t hi2 = 0, hi = 0, lo = 0;
- int dummyIdx = 0;
- // Configure to go in 125kHz listen mode
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
-
- //clear read buffer
- BigBuf_Clear_keep_EM();
-
- while (!BUTTON_PRESS() && !data_available()) {
-
- WDT_HIT();
- if (ledcontrol) LED_A_ON();
-
- DoAcquisition_default(-1, false);
- // FSK demodulator
- size = 50 * 128 * 2; //big enough to catch 2 sequences of largest format
- int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx);
- if (idx < 0) continue;
-
- if (idx > 0 && lo > 0 && (size == 96 || size == 192)) {
- // go over previously decoded manchester data and decode into usable tag ID
- if (hi2 != 0) { //extra large HID tags 88/192 bits
- Dbprintf("TAG ID: %x%08x%08x (%d)",
- hi2,
- hi,
- lo,
- (lo >> 1) & 0xFFFF
- );
- } else { //standard HID tags 44/96 bits
- uint8_t bitlen = 0;
- uint32_t fac = 0;
- uint32_t cardnum = 0;
-
- if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used
- uint32_t lo2 = 0;
- lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit
- uint8_t idx3 = 1;
- while (lo2 > 1) { //find last bit set to 1 (format len bit)
- lo2 >>= 1;
- idx3++;
- }
- bitlen = idx3 + 19;
- fac = 0;
- cardnum = 0;
- if (bitlen == 26) {
- cardnum = (lo >> 1) & 0xFFFF;
- fac = (lo >> 17) & 0xFF;
- }
- if (bitlen == 37) {
- cardnum = (lo >> 1) & 0x7FFFF;
- fac = ((hi & 0xF) << 12) | (lo >> 20);
- }
- if (bitlen == 34) {
- cardnum = (lo >> 1) & 0xFFFF;
- fac = ((hi & 1) << 15) | (lo >> 17);
- }
- if (bitlen == 35) {
- cardnum = (lo >> 1) & 0xFFFFF;
- fac = ((hi & 1) << 11) | (lo >> 21);
- }
- } else { //if bit 38 is not set then 37 bit format is used
- bitlen = 37;
- cardnum = (lo >> 1) & 0x7FFFF;
- fac = ((hi & 0xF) << 12) | (lo >> 20);
- }
- Dbprintf("TAG ID: " _YELLOW_("%x%08x (%d)") "- Format Len: " _YELLOW_("%d") "bit - FC: " _YELLOW_("%d") "- Card: "_YELLOW_("%d"),
- hi,
- lo,
- (lo >> 1) & 0xFFFF,
- bitlen,
- fac,
- cardnum
- );
- }
- if (findone) {
- *high = hi;
- *low = lo;
- break;
- }
- // reset
- }
- hi2 = hi = lo = idx = 0;
- }
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("HID fsk demod stopped");
- if (ledcontrol) LED_A_OFF();
-}
-
-// loop to get raw HID waveform then FSK demodulate the TAG ID from it
-void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) {
-
- uint8_t *dest = BigBuf_get_addr();
- size_t size;
- int dummyIdx = 0;
-
- BigBuf_Clear_keep_EM();
-
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
-
- while (!BUTTON_PRESS() && !data_available()) {
-
- WDT_HIT();
- if (ledcontrol) LED_A_ON();
-
- DoAcquisition_default(-1, false);
- // FSK demodulator
-
- size = MIN(12800, BigBuf_max_traceLen());
-
- //askdemod and manchester decode
- int idx = detectAWID(dest, &size, &dummyIdx);
-
- if (idx <= 0 || size != 96) continue;
- // Index maps
- // 0 10 20 30 40 50 60
- // | | | | | | |
- // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96
- // -----------------------------------------------------------------------------
- // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1
- // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96
- // |---26 bit---| |-----117----||-------------142-------------|
- // b = format bit len, o = odd parity of last 3 bits
- // f = facility code, c = card number
- // w = wiegand parity
- // (26 bit format shown)
-
- //get raw ID before removing parities
- uint32_t rawLo = bytebits_to_byte(dest + idx + 64, 32);
- uint32_t rawHi = bytebits_to_byte(dest + idx + 32, 32);
- uint32_t rawHi2 = bytebits_to_byte(dest + idx, 32);
-
- size = removeParity(dest, idx + 8, 4, 1, 88);
- if (size != 66) continue;
- // ok valid card found!
-
- // Index maps
- // 0 10 20 30 40 50 60
- // | | | | | | |
- // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456
- // -----------------------------------------------------------------------------
- // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000
- // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- // |26 bit| |-117--| |-----142------|
- // b = format bit len, o = odd parity of last 3 bits
- // f = facility code, c = card number
- // w = wiegand parity
- // (26 bit format shown)
-
- uint8_t fmtLen = bytebits_to_byte(dest, 8);
- if (fmtLen == 26) {
- uint32_t fac = bytebits_to_byte(dest + 9, 8);
- uint32_t cardnum = bytebits_to_byte(dest + 17, 16);
- uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
- Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo);
- } else {
- uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16);
- if (fmtLen > 32) {
- uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32);
- uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32);
- Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
- } else {
- uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
- Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
- }
- }
- if (findone) {
- if (ledcontrol) LED_A_OFF();
- *high = rawHi;
- *low = rawLo;
- break;
- }
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("AWID fsk demod stopped");
- if (ledcontrol) LED_A_OFF();
-}
-
-void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) {
- uint8_t *dest = BigBuf_get_addr();
-
- size_t size, idx = 0;
- int clk = 0, invert = 0, maxErr = 20;
- uint32_t hi = 0;
- uint64_t lo = 0;
-
- BigBuf_Clear_keep_EM();
-
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
-
- while (!BUTTON_PRESS() && !data_available()) {
-
- WDT_HIT();
- if (ledcontrol) LED_A_ON();
-
- DoAcquisition_default(-1, false);
-
- size = MIN(16385, BigBuf_max_traceLen());
-
- //askdemod and manchester decode
- int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1);
- WDT_HIT();
-
- if (errCnt > 50) continue;
-
- errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
- if (errCnt == 1) {
- if (size == 128) {
- Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)",
- hi,
- (uint32_t)(lo >> 32),
- (uint32_t)lo,
- (uint32_t)(lo & 0xFFFF),
- (uint32_t)((lo >> 16LL) & 0xFF),
- (uint32_t)(lo & 0xFFFFFF));
- } else {
- Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
- (uint32_t)(lo >> 32),
- (uint32_t)lo,
- (uint32_t)(lo & 0xFFFF),
- (uint32_t)((lo >> 16LL) & 0xFF),
- (uint32_t)(lo & 0xFFFFFF));
- }
-
- if (findone) {
- if (ledcontrol) LED_A_OFF();
- *high = hi;
- *low = lo;
- break;
- }
- }
- hi = lo = size = idx = 0;
- clk = invert = 0;
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("EM man/ask demod stopped");
- if (ledcontrol) LED_A_OFF();
-}
-
-void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) {
-
- uint8_t *dest = BigBuf_get_addr();
-
- int dummyIdx = 0;
- uint32_t code = 0, code2 = 0;
- uint8_t version = 0, facilitycode = 0, crc = 0;
- uint16_t number = 0, calccrc = 0;
-
- size_t size = BigBuf_max_traceLen();
-
- BigBuf_Clear_keep_EM();
-
- // Configure to go in 125kHz listen mode
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
-
- while (!BUTTON_PRESS() && !data_available()) {
- WDT_HIT();
- if (ledcontrol) LED_A_ON();
-
- DoAcquisition_default(-1, false);
-
- size = MIN(12000, BigBuf_max_traceLen());
-
- //fskdemod and get start index
- int idx = detectIOProx(dest, &size, &dummyIdx);
- if (idx < 0) continue;
- //valid tag found
-
- //Index maps
- //0 10 20 30 40 50 60
- //| | | | | | |
- //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
- //-----------------------------------------------------------------------------
- //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11
- //
- //Checksum:
- //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11
- //preamble F0 E0 01 03 B6 75
- // How to calc checksum,
- // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6
- // F0 + E0 + 01 + 03 + B6 = 28A
- // 28A & FF = 8A
- // FF - 8A = 75
- // Checksum: 0x75
- //XSF(version)facility:codeone+codetwo
- //Handle the data
- // if(findone){ //only print binary if we are doing one
- // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
- // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
- // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
- // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
- // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
- // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
- // Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
- // }
- code = bytebits_to_byte(dest + idx, 32);
- code2 = bytebits_to_byte(dest + idx + 32, 32);
- version = bytebits_to_byte(dest + idx + 27, 8); //14,4
- facilitycode = bytebits_to_byte(dest + idx + 18, 8);
- number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9
-
- crc = bytebits_to_byte(dest + idx + 54, 8);
- for (uint8_t i = 1; i < 6; ++i)
- calccrc += bytebits_to_byte(dest + idx + 9 * i, 8);
- calccrc &= 0xff;
- calccrc = 0xff - calccrc;
-
- char *crcStr = (crc == calccrc) ? "ok" : "!crc";
-
- Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]", version, facilitycode, number, code, code2, crc, crcStr);
- // if we're only looking for one tag
- if (findone) {
- if (ledcontrol) LED_A_OFF();
- *high = code;
- *low = code2;
- break;
- }
- code = code2 = 0;
- version = facilitycode = 0;
- number = 0;
- calccrc = 0;
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("IOProx fsk demod stopped");
- if (ledcontrol) LED_A_OFF();
-}
-
-/*------------------------------
- * T5555/T5557/T5567/T5577 routines
- *------------------------------
- * NOTE: T55x7/T5555 configuration register definitions moved to protocols.h
- *
- * Relevant communication times in microsecond
- * To compensate antenna falling times shorten the write times
- * and enlarge the gap ones.
- * Q5 tags seems to have issues when these values changes.
- */
-
-void TurnReadLFOn(uint32_t delay) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
-
- // measure antenna strength.
- //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
- WaitUS(delay);
-}
-void TurnReadLF_off(uint32_t delay) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- WaitUS(delay);
-}
-
-// Macro for code readability
-#define BITSTREAM_BYTE(x) ((x) >> 3) // iceman note: isn't this NIBBLE???
-#define BITSTREAM_BIT(x) ((x) & 7)
-
-#define T55_LLR_REF (136 * 8)
-
-// Write one bit to chip
-void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) {
-
- switch (bit) {
- case 0 :
- // write bit 0/00
- TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0);
- break;
- case 1 :
- // write bit 1/01
- TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_1);
- break;
- case 2 :
- // write bits 10 (1 of 4)
- TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_2);
- break;
- case 3 :
- // write bits 11 (1 of 4)
- TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_3);
- break;
- case 4 :
- // write Long Leading Reference
- TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 + T55_LLR_REF);
- break;
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- WaitUS(T55xx_Timing.m[downlink_idx].write_gap);
-}
-
-// Function to abstract an Arbitrary length byte array to store bit pattern.
-// bit_array - Array to hold data/bit pattern
-// start_offset - bit location to start storing new bits.
-// data - upto 32 bits of data to store
-// num_bits - how many bits (low x bits of data) Max 32 bits at a time
-// max_len - how many bytes can the bit_array hold (ensure no buffer overflow)
-// returns "Next" bit offset / bits stored (for next store)
-uint8_t T55xx_SetBits(uint8_t *bs, uint8_t start_offset, uint32_t data, uint8_t num_bits, uint8_t max_len) {
- int8_t next_offset = start_offset;
-
- // Check if data will fit.
- if ((start_offset + num_bits) <= (max_len * 8)) {
- // Loop through the data and store
- for (int8_t offset = (num_bits - 1); offset >= 0; offset--) {
-
- if ((data >> offset) & 1)
- bs[BITSTREAM_BYTE(next_offset)] |= (1 << BITSTREAM_BIT(next_offset)); // Set 1
- else
- bs[BITSTREAM_BYTE(next_offset)] &= (0xff ^ (1 << BITSTREAM_BIT(next_offset))); // Set 0
-
- next_offset++;
- }
- } else {
- // Note: This should never happen unless some code changes cause it.
- // So short message for coders when testing.
- Dbprintf(_RED_("T55 too many bits"));
- }
- return next_offset;
-}
-
-// Send one downlink command to the card
-void T55xx_SendCMD(uint32_t data, uint32_t pwd, uint16_t arg) {
-
- /*
- arg bits
- xxxx xxxxxxx1 0x001 password mode (Y/N)
- xxxx xxxxxx1x 0x002 page (0|1)
- xxxx xxxxx1xx 0x004 test mode (Y/N)
- xxxx xxx11xxx 0x018 selected downlink mode (0|1|2|3|)
- xxxx xx1xxxxx 0x020 !reg_readmode (ICEMAN ?? Why use negative in the bool ??)
- xxxx x1xxxxxx 0x040 called for a read, so no data packet (Y/N)
- xxxx 1xxxxxxx 0x080 reset (Y/N)
- xxx1 xxxxxxxx 0x100 brute force (Y/N)
- 111x xxxxxxxx 0xE00 block to write (0-7)
- */
- bool t55_send_pwdmode = (arg & 0x1);
- bool t55_send_page = ((arg >> 1) & 0x1);
- bool t55_send_testmode = ((arg >> 2) & 0x1);
- bool t55_send_regreadmode = ((arg >> 5) & 0x1);
- bool t55_send_readcmd = ((arg >> 6) & 0x1);
- bool t55_send_reset = ((arg >> 7) & 0x1);
- bool t55_brute_mem = ((arg >> 8) & 0x1);
-
- uint8_t downlink_mode = (arg >> 3) & 0x03;
- uint8_t block_no = (arg >> 9) & 0x07;
-
- // no startup delay when in bruteforce command
- uint8_t start_wait = (t55_brute_mem) ? 0 : 4;
-
- // Max Downlink Command size ~74 bits, so 10 bytes (80 bits)
- uint8_t bs[10];
- memset(bs, 0x00, sizeof(bs));
-
- uint8_t len = 0;
-
- // build bit stream to write.
-
- // add Leading 0
- if (downlink_mode == T55XX_DLMODE_LEADING_ZERO)
- len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
-
- // add 1 of 4 reference bit
- if (downlink_mode == T55XX_DLMODE_1OF4) {
- len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
- // add extra zero
- len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
- }
-
- // add Opcode
- if (t55_send_reset) {
- // reset : r*) 00
- len = T55xx_SetBits(bs, len, 0, 2, sizeof(bs));
- } else {
-
- if (t55_send_testmode)
- Dbprintf(_YELLOW_("Using Test Mode"));
-
- len = T55xx_SetBits(bs, len, t55_send_testmode ? 0 : 1, 1, sizeof(bs));
-
- len = T55xx_SetBits(bs, len, t55_send_testmode ? 1 : t55_send_page, 1, sizeof(bs));
-
- if (t55_send_pwdmode) {
- // Leading 0 and 1 of 4 00 fixed bits if passsword used
- if ((downlink_mode == T55XX_DLMODE_LEADING_ZERO) || (downlink_mode == T55XX_DLMODE_1OF4)) {
- len = T55xx_SetBits(bs, len, 0, 2, sizeof(bs));
- }
- len = T55xx_SetBits(bs, len, pwd, 32, sizeof(bs));
- }
-
- // Add Lock bit 0
- if (t55_send_regreadmode == false)
- len = T55xx_SetBits(bs, len, 0, 1, sizeof(bs));
-
- // Add Data if a write command
- if (t55_send_readcmd == false)
- len = T55xx_SetBits(bs, len, data, 32, sizeof(bs));
-
- // Add Address
- if (t55_send_regreadmode == false)
- len = T55xx_SetBits(bs, len, block_no, 3, sizeof(bs));
- }
-
- // Send Bits to T55xx
- // Set up FPGA, 125kHz
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
-
- // make sure tag is fully powered up...
- WaitMS(start_wait);
-
- // Trigger T55x7 in mode.
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- WaitUS(T55xx_Timing.m[downlink_mode].start_gap);
-
- // If long leading 0 write long reference pulse
- if (downlink_mode == T55XX_DLMODE_LLR)
- T55xxWriteBit(T55XX_LONGLEADINGREFERENCE, downlink_mode);//Timing); // Send Long Leading Start Reference
-
- uint8_t sendbits;
- if ((downlink_mode == T55XX_DLMODE_1OF4) && (len > 0)) { // 1 of 4 need to write 2 bits at a time
- for (uint8_t i = 0; i < len - 1; i += 2) {
- sendbits = (bs[BITSTREAM_BYTE(i)] >> (BITSTREAM_BIT(i)) & 1) << 1; // Bit i
- sendbits += (bs[BITSTREAM_BYTE(i + 1)] >> (BITSTREAM_BIT(i + 1)) & 1); // Bit i+1;
- T55xxWriteBit(sendbits & 3, downlink_mode);
- }
- } else {
- for (uint8_t i = 0; i < len; i++) {
- sendbits = (bs[BITSTREAM_BYTE(i)] >> BITSTREAM_BIT(i));
- T55xxWriteBit(sendbits & 1, downlink_mode);
- }
- }
-}
-
-// Send T5577 reset command then read stream (see if we can identify the start of the stream)
-void T55xxResetRead(uint8_t flags) {
-
- uint8_t downlink_mode = ((flags >> 3) & 3);
- uint8_t arg = 0x80 | downlink_mode;
-
- LED_A_ON();
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_keep_EM();
-
- T55xx_SendCMD(0, 0, arg);
-
- TurnReadLFOn(T55xx_Timing.m[downlink_mode].read_gap);
-
- // Acquisition
- DoPartialAcquisition(0, false, BigBuf_max_traceLen(), 0);
-
- // Turn the field off
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_LF_T55XX_RESET_READ, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
-}
-
-void T55xxDangerousRawTest(uint8_t *data) {
- // supports only default downlink mode
- t55xx_test_block_t *c = (t55xx_test_block_t *)data;
-
- uint8_t start_wait = 4;
- uint8_t bs[128 / 8];
- memset(bs, 0x00, sizeof(bs));
- uint8_t len = 0;
- if (c->bitlen == 0 || c->bitlen > 128 || c->time == 0)
- reply_ng(CMD_LF_T55XX_DANGERRAW, PM3_EINVARG, NULL, 0);
- for (uint8_t i = 0; i < c->bitlen; i++)
- len = T55xx_SetBits(bs, len, c->data[i], 1, sizeof(bs));
-
- if (DBGLEVEL > 1) {
- Dbprintf("LEN %i, TIMING %i", len, c->time);
- for (uint8_t i = 0; i < len; i++) {
- uint8_t sendbits = (bs[BITSTREAM_BYTE(i)] >> BITSTREAM_BIT(i));
- Dbprintf("%02i: %i", i, sendbits & 1);
- }
- }
-
- LED_A_ON();
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
- // make sure tag is fully powered up...
- WaitMS(start_wait);
- // Trigger T55x7 in mode.
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- WaitUS(T55xx_Timing.m[0].start_gap);
- uint8_t sendbits;
- for (uint8_t i = 0; i < len; i++) {
- sendbits = (bs[BITSTREAM_BYTE(i)] >> BITSTREAM_BIT(i));
- T55xxWriteBit(sendbits & 1, 0);
- }
- TurnReadLFOn(c->time);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_LF_T55XX_DANGERRAW, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
-}
-
-// Write one card block in page 0, no lock
-//void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags) {
-void T55xxWriteBlock(uint8_t *data) {
-
- /*
- flag bits
- xxxxxxx1 0x01 PwdMode
- xxxxxx1x 0x02 Page
- xxxxx1xx 0x04 testMode
- xxx11xxx 0x18 downlink mode
- xx1xxxxx 0x20 !reg_readmode
- x1xxxxxx 0x40 called for a read, so no data packet
- 1xxxxxxx 0x80 reset
- */
-
- t55xx_write_block_t *c = (t55xx_write_block_t *)data;
- // c->data, c->blockno, c->pwd, c->flags
-
- bool testMode = ((c->flags & 0x04) == 0x04);
-
- c->flags &= (0xff ^ 0x40); // Called for a write, so ensure it is clear/0
-
- LED_A_ON();
- T55xx_SendCMD(c->data, c->pwd, c->flags | (c->blockno << 9));
-
- // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550,
- // so wait a little more)
-
- // "there is a clock delay before programming"
- // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567
- // so we should wait 1 clock + 5.6ms then read response?
- // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow...
- if (testMode) {
- //TESTMODE TIMING TESTS:
- // <566us does nothing
- // 566-568 switches between wiping to 0s and doing nothing
- // 5184 wipes and allows 1 block to be programmed.
- // indefinite power on wipes and then programs all blocks with bitshifted data sent.
- TurnReadLFOn(5184);
-
- } else {
- TurnReadLFOn(20 * 1000);
- //could attempt to do a read to confirm write took
- // as the tag should repeat back the new block
- // until it is reset, but to confirm it we would
- // need to know the current block 0 config mode for
- // modulation clock an other details to demod the response...
- // response should be (for t55x7) a 0 bit then (ST if on)
- // block data written in on repeat until reset.
-
- //DoPartialAcquisition(20, false, 12000);
- }
- // turn field off
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
-}
-
-/*
-// uses NG format
-void T55xxWriteBlock(uint8_t *data) {
- t55xx_write_block_t *c = (t55xx_write_block_t *)data;
- T55xxWriteBlockExt(c->data, c->blockno, c->pwd, c->flags);
- // reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0);
-}
-*/
-/*
-// Read one card block in page [page]
-void T55xxReadBlockExt(uint16_t flags, uint8_t block, uint32_t pwd) {
- / *
- flag bits
- xxxx xxxxxxx1 0x0001 PwdMode
- xxxx xxxxxx1x 0x0002 Page
- xxxx xxxxx1xx 0x0004 testMode
- xxxx xxx11xxx 0x0018 downlink mode
- xxxx xx1xxxxx 0x0020 !reg_readmode
- xxxx x1xxxxxx 0x0040 called for a read, so no data packet
- xxxx 1xxxxxxx 0x0080 reset
- xxx1 xxxxxxxx 0x0100 brute / leave field on
- * /
- size_t samples = 12000;
-bool brute_mem = (flags & 0x0100) >> 8;
-
- LED_A_ON();
-
- if (brute_mem) samples = 1024;
-
- // Set Read Flag to ensure SendCMD does not add "data" to the packet
- flags |= 0x40;
-
- // RegRead Mode true block = 0xff, so read without an address
- if (block == 0xff) flags |= 0x20;
-
- //make sure block is at max 7
- block &= 0x7;
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_keep_EM();
-
- T55xx_SendCMD(0, pwd, flags | (block << 9)); //, true);
-
- // Turn field on to read the response
- // 137*8 seems to get to the start of data pretty well...
- // but we want to go past the start and let the repeating data settle in...
-
- // TurnReadLFOn(210*8); // issues with block 1 reads so dropping down seemed to help
- TurnReadLFOn(137 * 8);
-
- // Acquisition
- // Now do the acquisition
- DoPartialAcquisition(0, false, samples, 0);
-
- // Turn the field off
- if (!brute_mem) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_LF_T55XX_READBL, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
- }
-}
-*/
-// Read one card block in page [page]
-void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode) {
- /*
- flag bits
- xxxx xxxxxxx1 0x0001 PwdMode
- xxxx xxxxxx1x 0x0002 Page
- xxxx xxxxx1xx 0x0004 testMode
- xxxx xxx11xxx 0x0018 downlink mode
- xxxx xx1xxxxx 0x0020 !reg_readmode
- xxxx x1xxxxxx 0x0040 called for a read, so no data packet
- xxxx 1xxxxxxx 0x0080 reset
- xxx1 xxxxxxxx 0x0100 brute / leave field on
- */
- uint16_t flags = 0x0040; // read packet
- if (pwd_mode) flags |= 0x0001;
- if (page) flags |= 0x0002;
- flags |= (downlink_mode & 3) << 3;
- if (brute_mem) flags |= 0x0100;
-
-// T55xxReadBlockExt (flags,block,pwd);
- size_t samples = 12000;
- // bool brute_mem = (flags & 0x0100) >> 8;
-
- LED_A_ON();
-
- if (brute_mem) samples = 1024;
-
- //-- Set Read Flag to ensure SendCMD does not add "data" to the packet
- //-- flags |= 0x40;
-
- // RegRead Mode true block = 0xff, so read without an address
- if (block == 0xff) flags |= 0x20;
-
- //make sure block is at max 7
- block &= 0x7;
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_keep_EM();
-
- T55xx_SendCMD(0, pwd, flags | (block << 9)); //, true);
-
- // Turn field on to read the response
- // 137*8 seems to get to the start of data pretty well...
- // but we want to go past the start and let the repeating data settle in...
-
- // TurnReadLFOn(210*8); // issues with block 1 reads so dropping down seemed to help
- TurnReadLFOn(137 * 8);
-
- // Acquisition
- // Now do the acquisition
- DoPartialAcquisition(0, false, samples, 0);
-
- // Turn the field off
- if (!brute_mem) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_LF_T55XX_READBL, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
- }
-
-}
-
-void T55xx_ChkPwds(uint8_t flags) {
-
- DbpString("[+] T55XX Check pwds using flashmemory starting");
-
- uint8_t ret = 0;
- // First get baseline and setup LF mode.
- // tends to mess up BigBuf
- uint8_t *buf = BigBuf_get_addr();
- uint32_t b1, baseline = 0;
- uint8_t downlink_mode = (flags >> 3) & 0x03;
-
- // collect baseline for failed attempt
- uint8_t x = 32;
- while (x--) {
- b1 = 0;
- T55xxReadBlock(0, 0, true, 1, 0, downlink_mode);
- for (uint16_t j = 0; j < 1024; ++j)
- b1 += buf[j];
-
- b1 *= b1;
- b1 >>= 8;
- baseline += b1;
- }
-
- baseline >>= 5;
- Dbprintf("[=] Baseline determined [%u]", baseline);
-
- uint8_t *pwds = BigBuf_get_EM_addr();
- uint16_t pwdCount = 0;
- uint32_t candidate = 0;
-#ifdef WITH_FLASH
-
- BigBuf_Clear_EM();
- uint16_t isok = 0;
- uint8_t counter[2] = {0x00, 0x00};
- isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter));
- if (isok != sizeof(counter))
- goto OUT;
-
- pwdCount = counter[1] << 8 | counter[0];
-
- if (pwdCount == 0 || pwdCount == 0xFFFF)
- goto OUT;
-
- isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4);
- if (isok != pwdCount * 4)
- goto OUT;
-
- Dbprintf("[=] Password dictionary count %d ", pwdCount);
-#endif
-
- uint32_t pwd = 0, curr = 0, prev = 0;
- for (uint16_t i = 0; i < pwdCount; ++i) {
-
- if (BUTTON_PRESS() && !data_available()) {
- goto OUT;
- }
-
- pwd = bytes_to_num(pwds + i * 4, 4);
-
- T55xxReadBlock(0, true, true, 0, pwd, downlink_mode);
-
- // calc mean of BigBuf 1024 samples.
- uint32_t sum = 0;
- for (uint16_t j = 0; j < 1024; ++j) {
- sum += buf[j];
- }
-
- sum *= sum;
- sum >>= 8;
-
- int32_t tmp = (sum - baseline);
- curr = ABS(tmp);
-
- Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr);
-
- if (curr > prev) {
- Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd);
- candidate = pwd;
- prev = curr;
- }
- }
-
- if (candidate)
- ret = 1;
-
-OUT:
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_mix(CMD_ACK, ret, candidate, 0, 0, 0);
- LEDsoff();
-}
-
-void T55xxWakeUp(uint32_t pwd, uint8_t flags) {
-
- flags |= 0x01 | 0x40 | 0x20; //Password | Read Call (no data) | reg_read no block
- LED_B_ON();
-
- T55xx_SendCMD(0, pwd, flags);
-
- //-- Turn and leave field on to let the begin repeating transmission
- TurnReadLFOn(20 * 1000);
- reply_ng(CMD_LF_T55XX_WAKEUP, PM3_SUCCESS, NULL, 0);
-}
-
-
-/*-------------- Cloning routines -----------*/
-void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) {
-
- t55xx_write_block_t cmd;
- cmd.pwd = 0;
- cmd.flags = 0;
-
- for (uint8_t i = numblocks + startblock; i > startblock; i--) {
- cmd.data = blockdata[i - 1];
- cmd.blockno = i - 1;
- T55xxWriteBlock((uint8_t *)&cmd);
- }
-
-}
-
-// Copy HID id to card and setup block 0 config
-void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) {
- uint32_t data[] = {0, 0, 0, 0, 0, 0, 0};
- uint8_t last_block = 0;
-
- if (longFMT) {
- // Ensure no more than 84 bits supplied
- if (hi2 > 0xFFFFF) {
- DbpString("Tags can only have 84 bits.");
- return;
- }
- // Build the 6 data blocks for supplied 84bit ID
- last_block = 6;
- // load preamble (1D) & long format identifier (9E manchester encoded)
- data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF);
- // load raw id from hi2, hi, lo to data blocks (manchester encoded)
- data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF);
- data[3] = manchesterEncode2Bytes(hi >> 16);
- data[4] = manchesterEncode2Bytes(hi & 0xFFFF);
- data[5] = manchesterEncode2Bytes(lo >> 16);
- data[6] = manchesterEncode2Bytes(lo & 0xFFFF);
- } else {
- // Ensure no more than 44 bits supplied
- if (hi > 0xFFF) {
- DbpString("Tags can only have 44 bits.");
- return;
- }
- // Build the 3 data blocks for supplied 44bit ID
- last_block = 3;
- // load preamble
- data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF);
- data[2] = manchesterEncode2Bytes(lo >> 16);
- data[3] = manchesterEncode2Bytes(lo & 0xFFFF);
- }
- // load chip config block
- data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT;
-
- //TODO add selection of chip for Q5 or T55x7
- // data[0] = T5555_SET_BITRATE(50) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT;
-
- LED_D_ON();
- WriteT55xx(data, 0, last_block + 1);
- LED_D_OFF();
-}
-
-// clone viking tag to T55xx
-void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5) {
-
- uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), 0, 0};
- if (Q5)
- data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
-
- data[1] = bytes_to_num(blocks, 4);
- data[2] = bytes_to_num(blocks + 4, 4);
-
- // Program the data blocks for supplied ID and the block 0 config
- WriteT55xx(data, 0, 3);
- LED_D_OFF();
- reply_ng(CMD_LF_VIKING_CLONE, PM3_SUCCESS, NULL, 0);
-}
-
-// Define 9bit header for EM410x tags
-#define EM410X_HEADER 0x1FF
-#define EM410X_ID_LENGTH 40
-
-void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) {
- int i;
- uint64_t id = EM410X_HEADER;
- uint64_t rev_id = 0; // reversed ID
- int c_parity[4]; // column parity
- int r_parity = 0; // row parity
- uint32_t clock = 0;
-
- // Reverse ID bits given as parameter (for simpler operations)
- for (i = 0; i < EM410X_ID_LENGTH; ++i) {
- if (i < 32) {
- rev_id = (rev_id << 1) | (id_lo & 1);
- id_lo >>= 1;
- } else {
- rev_id = (rev_id << 1) | (id_hi & 1);
- id_hi >>= 1;
- }
- }
-
- for (i = 0; i < EM410X_ID_LENGTH; ++i) {
- int id_bit = rev_id & 1;
-
- if (i % 4 == 0) {
- // Don't write row parity bit at start of parsing
- if (i)
- id = (id << 1) | r_parity;
- // Start counting parity for new row
- r_parity = id_bit;
- } else {
- // Count row parity
- r_parity ^= id_bit;
- }
-
- // First elements in column?
- if (i < 4)
- // Fill out first elements
- c_parity[i] = id_bit;
- else
- // Count column parity
- c_parity[i % 4] ^= id_bit;
-
- // Insert ID bit
- id = (id << 1) | id_bit;
- rev_id >>= 1;
- }
-
- // Insert parity bit of last row
- id = (id << 1) | r_parity;
-
- // Fill out column parity at the end of tag
- for (i = 0; i < 4; ++i)
- id = (id << 1) | c_parity[i];
-
- // Add stop bit
- id <<= 1;
-
- Dbprintf("Started writing %s tag ...", card ? "T55x7" : "T5555");
- LED_D_ON();
-
- // Write EM410x ID
- uint32_t data[] = {0, (uint32_t)(id >> 32), (uint32_t)(id & 0xFFFFFFFF)};
-
- clock = (card & 0xFF00) >> 8;
- clock = (clock == 0) ? 64 : clock;
- Dbprintf("Clock rate: %d", clock);
- if (card & 0xFF) { //t55x7
- clock = GetT55xxClockBit(clock);
- if (clock == 0) {
- Dbprintf("Invalid clock rate: %d", clock);
- return;
- }
- data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT);
- } else { //t5555 (Q5)
- data[0] = T5555_SET_BITRATE(clock) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT);
- }
-
- WriteT55xx(data, 0, 3);
-
- LED_D_OFF();
- Dbprintf("Tag %s written with 0x%08x%08x\n",
- card ? "T55x7" : "T5555",
- (uint32_t)(id >> 32),
- (uint32_t)id);
-}
-
-//-----------------------------------
-// EM4469 / EM4305 routines
-//-----------------------------------
-// Below given command set.
-// Commands are including the even parity, binary mirrored
-#define FWD_CMD_LOGIN 0xC
-#define FWD_CMD_WRITE 0xA
-#define FWD_CMD_READ 0x9
-#define FWD_CMD_DISABLE 0x5
-
-uint8_t forwardLink_data[64]; //array of forwarded bits
-uint8_t *forward_ptr; //ptr for forward message preparation
-uint8_t fwd_bit_sz; //forwardlink bit counter
-uint8_t *fwd_write_ptr; //forwardlink bit pointer
-
-//====================================================================
-// prepares command bits
-// see EM4469 spec
-//====================================================================
-//--------------------------------------------------------------------
-// VALUES TAKEN FROM EM4x function: SendForward
-// START_GAP = 440; (55*8) cycles at 125kHz (8us = 1cycle)
-// WRITE_GAP = 128; (16*8)
-// WRITE_1 = 256 32*8; (32*8)
-
-// These timings work for 4469/4269/4305 (with the 55*8 above)
-// WRITE_0 = 23*8 , 9*8
-
-uint8_t Prepare_Cmd(uint8_t cmd) {
-
- *forward_ptr++ = 0; //start bit
- *forward_ptr++ = 0; //second pause for 4050 code
-
- *forward_ptr++ = cmd;
- cmd >>= 1;
- *forward_ptr++ = cmd;
- cmd >>= 1;
- *forward_ptr++ = cmd;
- cmd >>= 1;
- *forward_ptr++ = cmd;
-
- return 6; //return number of emited bits
-}
-
-//====================================================================
-// prepares address bits
-// see EM4469 spec
-//====================================================================
-uint8_t Prepare_Addr(uint8_t addr) {
-
- register uint8_t line_parity;
-
- uint8_t i;
- line_parity = 0;
- for (i = 0; i < 6; i++) {
- *forward_ptr++ = addr;
- line_parity ^= addr;
- addr >>= 1;
- }
-
- *forward_ptr++ = (line_parity & 1);
-
- return 7; //return number of emited bits
-}
-
-//====================================================================
-// prepares data bits intreleaved with parity bits
-// see EM4469 spec
-//====================================================================
-uint8_t Prepare_Data(uint16_t data_low, uint16_t data_hi) {
-
- register uint8_t column_parity;
- register uint8_t i, j;
- register uint16_t data;
-
- data = data_low;
- column_parity = 0;
-
- for (i = 0; i < 4; i++) {
- register uint8_t line_parity = 0;
- for (j = 0; j < 8; j++) {
- line_parity ^= data;
- column_parity ^= (data & 1) << j;
- *forward_ptr++ = data;
- data >>= 1;
- }
- *forward_ptr++ = line_parity;
- if (i == 1)
- data = data_hi;
- }
-
- for (j = 0; j < 8; j++) {
- *forward_ptr++ = column_parity;
- column_parity >>= 1;
- }
- *forward_ptr = 0;
-
- return 45; //return number of emited bits
-}
-
-//====================================================================
-// Forward Link write function
-// Requires: forwarLink_data filled with valid bits (1 bit per byte)
-// fwd_bit_count set with number of bits to be sent
-//====================================================================
-void SendForward(uint8_t fwd_bit_count) {
-
-// iceman, 21.3us increments for the USclock verification.
-// 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead
-// 32FC * 8us == 256us / 21.3 == 12.018 steps. ok
-// 16FC * 8us == 128us / 21.3 == 6.009 steps. ok
-#ifndef EM_START_GAP
-#define EM_START_GAP 55*8
-#endif
-
- fwd_write_ptr = forwardLink_data;
- fwd_bit_sz = fwd_bit_count;
-
- // Set up FPGA, 125kHz or 95 divisor
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
-
- // force 1st mod pulse (start gap must be longer for 4305)
- fwd_bit_sz--; //prepare next bit modulation
- fwd_write_ptr++;
-
- TurnReadLF_off(EM_START_GAP);
- TurnReadLFOn(18 * 8);
-
- // now start writting with bitbanging the antenna.
- while (fwd_bit_sz-- > 0) { //prepare next bit modulation
- if (((*fwd_write_ptr++) & 1) == 1) {
- WaitUS(32 * 8);
- } else {
- TurnReadLF_off(23 * 8);
- TurnReadLFOn(18 * 8);
- }
- }
-}
-
-void EM4xLogin(uint32_t pwd) {
- uint8_t len;
- forward_ptr = forwardLink_data;
- len = Prepare_Cmd(FWD_CMD_LOGIN);
- len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
- SendForward(len);
- //WaitUS(20); // no wait for login command.
- // should read
- // 0000 1010 ok.
- // 0000 0001 fail
-}
-
-void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
-
- LED_A_ON();
- uint8_t len;
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_ext(false);
-
- StartTicks();
- /* should we read answer from Logincommand?
- *
- * should read
- * 0000 1010 ok.
- * 0000 0001 fail
- **/
- if (usepwd) EM4xLogin(pwd);
-
- forward_ptr = forwardLink_data;
- len = Prepare_Cmd(FWD_CMD_READ);
- len += Prepare_Addr(addr);
-
- SendForward(len);
-
- WaitUS(400);
-
- DoPartialAcquisition(20, false, 6000, 1000);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
-}
-
-void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
-
- LED_A_ON();
- uint8_t len;
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_ext(false);
- StartTicks();
- /* should we read answer from Logincommand?
- *
- * should read
- * 0000 1010 ok.
- * 0000 0001 fail
- **/
- if (usepwd) EM4xLogin(pwd);
-
- forward_ptr = forwardLink_data;
- len = Prepare_Cmd(FWD_CMD_WRITE);
- len += Prepare_Addr(addr);
- len += Prepare_Data(data & 0xFFFF, data >> 16);
-
- SendForward(len);
-
- //Wait 20ms for write to complete?
- WaitMS(7);
-
- DoPartialAcquisition(20, false, 6000, 1000);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
- LED_A_OFF();
-}
-
-/*
-Reading COTAG.
-
-COTAG needs the reader to write a startsequence and the card has an extreme slow datarate.
-because of this, we can "sample" the data signal but we interpreate it to Manchester direct.
-
-This behavior looks very similar to old ancient Motorola Flexpass
-
------------------------------------------------------------------------
-According to patent EP0040544B1:
-Operating freq
- reader 132 kHz
- tag 66 kHz
-
-Divide by 384 counter
-
-PULSE repetition 5.82ms
-LOW 2.91 ms
-HIGH 2.91 ms
-
-Also references to a half-bit format and leading zero.
------------------------------------------------------------------------
-
-READER START SEQUENCE:
-
-burst 800 us gap 2.2 ms
-burst 3.6 ms gap 2.2 ms
-burst 800 us gap 2.2 ms
-pulse 3.6 ms
-
-This triggers COTAG tag to response
-
-*/
-void Cotag(uint32_t arg0) {
-#ifndef OFF
-# define OFF(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS((x)); }
-#endif
-#ifndef ON
-# define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
-#endif
- uint8_t rawsignal = arg0 & 0xF;
-
- LED_A_ON();
-
- LFSetupFPGAForADC(LF_FREQ2DIV(132), true);
-
- //clear buffer now so it does not interfere with timing later
- BigBuf_Clear_ext(false);
-
- //write COTAG start pulse
- ON(740) OFF(2035)
- ON(3330) OFF(2035)
- ON(740) OFF(2035)
- ON(1000)
-
- switch (rawsignal) {
- case 0:
- doCotagAcquisition(40000);
- break;
- case 1:
- doCotagAcquisitionManchester();
- break;
- case 2:
- DoAcquisition_config(false, 0);
- break;
- }
-
- // Turn the field off
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
- reply_ng(CMD_LF_COTAG_READ, PM3_SUCCESS, NULL, 0);
- LEDsoff();
-}
-
-/*
-* EM4305 support
-*/
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/lfops.h b/pm3rdv4rrg/src/main/cpp/armsrc/lfops.h
deleted file mode 100644
index b697cffd..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/lfops.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __LFOPS_H
-#define __LFOPS_H
-
-#include "common.h"
-
-#include "pm3_cmd.h" // struct
-
-extern uint8_t decimation;
-extern uint8_t bits_per_sample ;
-extern bool averaging;
-
-void AcquireRawAdcSamples125k(int divisor);
-void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
-void ReadTItag(void);
-void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
-
-void AcquireTiType(void);
-void AcquireRawBitsTI(void);
-void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles);
-void SimulateTagLowFrequency(int period, int gap, bool ledcontrol);
-void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
-
-void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol, int numcycles);
-void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol);
-
-void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol, int numcycles);
-void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol);
-void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
-void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
-void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
-
-void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
-void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
-void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
-void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
-void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
-void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5);
-void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
-void T55xxResetRead(uint8_t flags);
-//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
-void T55xxWriteBlock(uint8_t *data);
-// void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
-void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode);
-void T55xxWakeUp(uint32_t pwd, uint8_t flags);
-void T55xx_ChkPwds(uint8_t flags);
-void T55xxDangerousRawTest(uint8_t *data);
-
-void TurnReadLFOn(uint32_t delay);
-
-void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
-void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
-
-void Cotag(uint32_t arg0);
-void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c);
-t55xx_configurations_t *getT55xxConfig(void);
-void printT55xxConfig(void);
-void loadT55xxConfig(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/lfsampling.c b/pm3rdv4rrg/src/main/cpp/armsrc/lfsampling.c
deleted file mode 100644
index c492a4ed..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/lfsampling.c
+++ /dev/null
@@ -1,601 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Miscellaneous routines for low frequency sampling.
-//-----------------------------------------------------------------------------
-
-#include "lfsampling.h"
-
-#include "proxmark3_arm.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "lfdemod.h"
-#include "string.h" // memset
-
-/*
-Default LF config is set to:
- decimation = 1 (we keep 1 out of 1 samples)
- bits_per_sample = 8
- averaging = YES
- divisor = 95 (125kHz)
- trigger_threshold = 0
- samples_to_skip = 0
- verbose = YES
- */
-sample_config config = { 1, 8, 1, LF_DIVISOR_125, 0, 0, 1} ;
-
-void printConfig() {
- uint32_t d = config.divisor;
- DbpString(_BLUE_("LF Sampling config"));
- Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d.%02d kHz")")", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
- Dbprintf(" [b] bits per sample.....%d", config.bits_per_sample);
- Dbprintf(" [d] decimation..........%d", config.decimation);
- Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No");
- Dbprintf(" [t] trigger threshold...%d", config.trigger_threshold);
- Dbprintf(" [s] samples to skip.....%d ", config.samples_to_skip);
-}
-
-/**
- * Called from the USB-handler to set the sampling configuration
- * The sampling config is used for standard reading and sniffing.
- *
- * Other functions may read samples and ignore the sampling config,
- * such as functions to read the UID from a prox tag or similar.
- *
- * Values set to '-1' implies no change
- * @brief setSamplingConfig
- * @param sc
- */
-void setSamplingConfig(sample_config *sc) {
-
- // decimation (1-8) how many bits of adc sample value to save
- if (sc->decimation > 0 && sc->decimation < 8)
- config.decimation = sc->decimation;
-
- // bits per sample (1-8)
- if (sc->bits_per_sample > 0 && sc->bits_per_sample < 8)
- config.bits_per_sample = sc->bits_per_sample;
-
- //
- if (sc->averaging > -1)
- config.averaging = (sc->averaging > 0) ? 1 : 0;
-
- // Frequency divisor (19 - 255)
- if (sc->divisor > 18 && sc->divisor < 256)
- config.divisor = sc->divisor;
-
- // Start saving samples when adc value larger than trigger_threshold
- if (sc->trigger_threshold > -1)
- config.trigger_threshold = sc->trigger_threshold;
-
- // Skip n adc samples before saving
- if (sc->samples_to_skip > -1)
- config.samples_to_skip = sc->samples_to_skip;
-
- if (sc->verbose)
- printConfig();
-}
-
-sample_config *getSamplingConfig() {
- return &config;
-}
-
-/**
- * @brief Pushes bit onto the stream
- * @param stream
- * @param bit
- */
-void pushBit(BitstreamOut *stream, uint8_t bit) {
- int bytepos = stream->position >> 3; // divide by 8
- int bitpos = stream->position & 7;
- *(stream->buffer + bytepos) &= ~(1 << (7 - bitpos));
- *(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos);
- stream->position++;
- stream->numbits++;
-}
-
-// Holds bit packed struct of samples.
-BitstreamOut data = {0, 0, 0};
-
-// internal struct to keep track of samples gathered
-sampling_t samples = {0, 0, 0, 0};
-
-void initSampleBuffer(uint32_t *sample_size) {
- initSampleBufferEx(sample_size, false);
-}
-
-void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
-
- BigBuf_free();
-
- // We can't erase the buffer now, it would drastically delay the acquisition
-
- if (use_malloc) {
-
- if (sample_size == NULL || *sample_size == 0 ) {
- *sample_size = BigBuf_max_traceLen();
- data.buffer = BigBuf_get_addr();
- } else {
- *sample_size = MIN(*sample_size, BigBuf_max_traceLen());
- data.buffer = BigBuf_malloc(*sample_size);
-
- }
-
- } else {
- if (sample_size == NULL || *sample_size == 0 ) {
- *sample_size = BigBuf_max_traceLen();
- }
- data.buffer = BigBuf_get_addr();
- }
-
- //
- samples.dec_counter = 0;
- samples.sum = 0;
- samples.counter = 0;
- samples.total_saved = 0;
-}
-
-uint32_t getSampleCounter() {
- return samples.total_saved;
-}
-
-void logSampleSimple(uint8_t sample) {
- logSample(sample, config.decimation, config.bits_per_sample, config.averaging);
-}
-
-void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) {
-
- if (!data.buffer) return;
-
- if (bits_per_sample == 0) bits_per_sample = 1;
- if (bits_per_sample > 8) bits_per_sample = 8;
- if (decimation == 0) decimation = 1;
-
- // keep track of total gather samples regardless how many was discarded.
- samples.counter++;
-
- if (avg) {
- samples.sum += sample;
- }
-
- // check decimation
- if (decimation > 1) {
- samples.dec_counter++;
-
- if (samples.dec_counter < decimation) return;
-
- samples.dec_counter = 0;
- }
-
- // averaging
- if (avg && decimation > 1) {
- sample = samples.sum / decimation;
- samples.sum = 0;
- }
-
- // store the sample
- samples.total_saved++;
-
- if (bits_per_sample == 8) {
-
- data.buffer[samples.total_saved - 1] = sample;
-
- // add number of bits.
- data.numbits = samples.total_saved << 3;
-
- } else {
- pushBit(&data, sample & 0x80);
- if (bits_per_sample > 1) pushBit(&data, sample & 0x40);
- if (bits_per_sample > 2) pushBit(&data, sample & 0x20);
- if (bits_per_sample > 3) pushBit(&data, sample & 0x10);
- if (bits_per_sample > 4) pushBit(&data, sample & 0x08);
- if (bits_per_sample > 5) pushBit(&data, sample & 0x04);
- if (bits_per_sample > 6) pushBit(&data, sample & 0x02);
- }
-}
-
-/**
-* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
-* if not already loaded, sets divisor and starts up the antenna.
-* @param divisor : 1, 88> 255 or negative ==> 134.8 kHz
-* 0 or 95 ==> 125 kHz
-*
-**/
-void LFSetupFPGAForADC(int divisor, bool reader_field) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- if ((divisor == 1) || (divisor < 0) || (divisor > 255))
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz
- else if (divisor == 0)
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- else
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (reader_field ? FPGA_LF_ADC_READER_FIELD : 0));
-
- // Connect the A/D to the peak-detected low-frequency path.
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- // 50ms for the resonant antenna to settle.
- if (reader_field)
- SpinDelay(50);
-
- // Now set up the SSC to get the ADC samples that are now streaming at us.
- FpgaSetupSsc();
-
- // start a 1.5ticks is 1us
- StartTicks();
-}
-
-/**
- * Does the sample acquisition. If threshold is specified, the actual sampling
- * is not commenced until the threshold has been reached.
- * This method implements decimation and quantization in order to
- * be able to provide longer sample traces.
- * Uses the following global settings:
- * @param decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc.
- * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample.
- * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample
- * value that will be used is the average value of the three samples.
- * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set
- * to -1 to ignore threshold.
- * @param verbose - is true, dbprints the status, else no outputs
- * @return the number of bits occupied by the samples.
- */
-uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold,
- bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip) {
-
- initSampleBuffer(&sample_size);
-
- uint32_t cancel_counter = 0;
- int16_t checked = 0;
-
- while (true) {
-
- // only every 1000th times, in order to save time when collecting samples.
- if (checked == 1000) {
- if (BUTTON_PRESS() || data_available()) {
- checked = -1;
- break;
- } else {
- checked = 0;
- }
- }
- ++checked;
-
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
-// AT91C_BASE_SSC->SSC_THR = 0x43;
- LED_D_ON();
- }
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
- // Testpoint 8 (TP8) can be used to trigger oscilliscope
- LED_D_OFF();
-
- // threshold either high or low values 128 = center 0. if trigger = 178
- if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
- if (cancel_after > 0) {
- cancel_counter++;
- if (cancel_after == cancel_counter)
- break;
- }
- continue;
- }
-
- trigger_threshold = 0;
-
- if (samples_to_skip > 0) {
- samples_to_skip--;
- continue;
- }
-
- logSample(sample, decimation, bits_per_sample, avg);
-
- if (samples.total_saved >= sample_size) break;
- }
- }
-
- if (checked == -1 && verbose) {
- Dbprintf("lf sampling aborted");
- }
-
- if (verbose) {
- Dbprintf("Done, saved " _YELLOW_("%d")"out of " _YELLOW_("%d")"seen samples at " _YELLOW_("%d")"bits/sample", samples.total_saved, samples.counter, bits_per_sample);
- }
-
- // Ensure that DC offset removal and noise check is performed for any device-side processing
- removeSignalOffset(data.buffer, samples.total_saved);
- computeSignalProperties(data.buffer, samples.total_saved);
-
- return data.numbits;
-}
-/**
- * @brief Does sample acquisition, ignoring the config values set in the sample_config.
- * This method is typically used by tag-specific readers who just wants to read the samples
- * the normal way
- * @param trigger_threshold
- * @param verbose
- * @return number of bits sampled
- */
-uint32_t DoAcquisition_default(int trigger_threshold, bool verbose) {
- return DoAcquisition(1, 8, 0, trigger_threshold, verbose, 0, 0, 0);
-}
-uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size) {
- return DoAcquisition(config.decimation
- , config.bits_per_sample
- , config.averaging
- , config.trigger_threshold
- , verbose
- , sample_size
- , 0
- , config.samples_to_skip);
-}
-
-uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after) {
- return DoAcquisition(1, 8, 0, trigger_threshold, verbose, sample_size, cancel_after, 0);
-}
-
-uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) {
- if (verbose)
- printConfig();
-
- LFSetupFPGAForADC(config.divisor, reader_field);
- uint32_t ret = DoAcquisition_config(verbose, sample_size);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- return ret;
-}
-
-/**
-* Initializes the FPGA for reader-mode (field on), and acquires the samples.
-* @return number of bits sampled
-**/
-uint32_t SampleLF(bool verbose, uint32_t sample_size) {
- BigBuf_Clear_ext(false);
- return ReadLF(true, verbose, sample_size);
-}
-/**
-* Initializes the FPGA for sniffer-mode (field off), and acquires the samples.
-* @return number of bits sampled
-**/
-uint32_t SniffLF() {
- BigBuf_Clear_ext(false);
- return ReadLF(false, true, 0);
-}
-
-/**
-* acquisition of T55x7 LF signal. Similar to other LF, but adjusted with @marshmellows thresholds
-* the data is collected in BigBuf.
-**/
-void doT55x7Acquisition(size_t sample_size) {
-
-#define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
-#define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
-#define T55xx_READ_TOL 5
-
- uint8_t *dest = BigBuf_get_addr();
- uint16_t bufsize = BigBuf_max_traceLen();
-
- if (bufsize > sample_size)
- bufsize = sample_size;
-
- uint8_t lastSample = 0;
- uint16_t i = 0, skipCnt = 0;
- bool startFound = false;
- bool highFound = false;
- bool lowFound = false;
-
- uint16_t checker = 0;
-
- while (skipCnt < 1000 && (i < bufsize)) {
- if (checker == 1000) {
- if (BUTTON_PRESS() || data_available())
- break;
- else
- checker = 0;
- } else {
- ++checker;
- }
-
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
- LED_D_ON();
- }
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- LED_D_OFF();
-
- // skip until the first high sample above threshold
- if (!startFound && sample > T55xx_READ_UPPER_THRESHOLD) {
- highFound = true;
- } else if (!highFound) {
- skipCnt++;
- continue;
- }
- // skip until the first low sample below threshold
- if (!startFound && sample < T55xx_READ_LOWER_THRESHOLD) {
- lastSample = sample;
- lowFound = true;
- } else if (!lowFound) {
- skipCnt++;
- continue;
- }
-
- // skip until first high samples begin to change
- if (startFound || sample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) {
- // if just found start - recover last sample
- if (!startFound) {
- dest[i++] = lastSample;
- startFound = true;
- }
- // collect samples
- dest[i++] = sample;
- }
- }
- }
-}
-/**
-* acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384
-* and is Manchester?, we directly gather the manchester data into bigbuff
-**/
-
-#define COTAG_T1 384
-#define COTAG_T2 (COTAG_T1>>1)
-#define COTAG_ONE_THRESHOLD 128+10
-#define COTAG_ZERO_THRESHOLD 128-10
-#ifndef COTAG_BITS
-#define COTAG_BITS 264
-#endif
-void doCotagAcquisition(size_t sample_size) {
-
- uint8_t *dest = BigBuf_get_addr();
- uint16_t bufsize = BigBuf_max_traceLen();
-
- if (bufsize > sample_size)
- bufsize = sample_size;
-
- dest[0] = 0;
- uint8_t firsthigh = 0, firstlow = 0;
- uint16_t i = 0;
- uint16_t noise_counter = 0;
-
- uint16_t checker = 0;
-
- while ((i < bufsize) && (noise_counter < (COTAG_T1 << 1))) {
- if (checker == 1000) {
- if (BUTTON_PRESS() || data_available())
- break;
- else
- checker = 0;
- } else {
- ++checker;
- }
-
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
- LED_D_ON();
- }
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
- // find first peak
- if (!firsthigh) {
- if (sample < COTAG_ONE_THRESHOLD) {
- noise_counter++;
- continue;
- }
- noise_counter = 0;
- firsthigh = 1;
- }
- if (!firstlow) {
- if (sample > COTAG_ZERO_THRESHOLD) {
- noise_counter++;
- continue;
- }
- noise_counter = 0;
- firstlow = 1;
- }
-
- ++i;
-
- if (sample > COTAG_ONE_THRESHOLD)
- dest[i] = 255;
- else if (sample < COTAG_ZERO_THRESHOLD)
- dest[i] = 0;
- else
- dest[i] = dest[i - 1];
- }
- }
-
- // Ensure that DC offset removal and noise check is performed for any device-side processing
- removeSignalOffset(dest, bufsize);
- computeSignalProperties(dest, bufsize);
-}
-
-uint32_t doCotagAcquisitionManchester() {
-
- uint8_t *dest = BigBuf_get_addr();
- uint16_t bufsize = BigBuf_max_traceLen();
-
- if (bufsize > COTAG_BITS)
- bufsize = COTAG_BITS;
-
- dest[0] = 0;
- uint8_t firsthigh = 0, firstlow = 0;
- uint16_t sample_counter = 0, period = 0;
- uint8_t curr = 0, prev = 0;
- uint16_t noise_counter = 0;
- uint16_t checker = 0;
-
- while ((sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1))) {
- if (checker == 1000) {
- if (BUTTON_PRESS() || data_available())
- break;
- else
- checker = 0;
- } else {
- ++checker;
- }
-
- WDT_HIT();
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
- LED_D_ON();
- }
-
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
- // find first peak
- if (!firsthigh) {
- if (sample < COTAG_ONE_THRESHOLD) {
- noise_counter++;
- continue;
- }
- noise_counter = 0;
- firsthigh = 1;
- }
-
- if (!firstlow) {
- if (sample > COTAG_ZERO_THRESHOLD) {
- noise_counter++;
- continue;
- }
- noise_counter = 0;
- firstlow = 1;
- }
-
- // set sample 255, 0, or previous
- if (sample > COTAG_ONE_THRESHOLD) {
- prev = curr;
- curr = 1;
- } else if (sample < COTAG_ZERO_THRESHOLD) {
- prev = curr;
- curr = 0;
- } else {
- curr = prev;
- }
-
- // full T1 periods,
- if (period > 0) {
- --period;
- continue;
- }
-
- dest[sample_counter] = curr;
- ++sample_counter;
- period = COTAG_T1;
- }
- }
- return sample_counter;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/lfsampling.h b/pm3rdv4rrg/src/main/cpp/armsrc/lfsampling.h
deleted file mode 100644
index 570dc20f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/lfsampling.h
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef __LFSAMPLING_H
-#define __LFSAMPLING_H
-
-#include "common.h"
-#include "pm3_cmd.h"
-
-typedef struct {
- uint8_t *buffer;
- uint32_t numbits;
- uint32_t position;
-} BitstreamOut;
-
-typedef struct {
- int dec_counter;
- uint32_t sum;
- uint32_t counter;
- uint32_t total_saved;
-} sampling_t;
-
-/**
-* acquisition of Cotag LF signal. Similar to other LF, since the Cotag has such long datarate RF/384
-* and is Manchester?, we directly gather the manchester data into bigbuff
-**/
-void doCotagAcquisition(size_t sample_size);
-uint32_t doCotagAcquisitionManchester(void);
-
-/**
-* acquisition of T55x7 LF signal. Similar to other LF, but adjusted with @marshmellows thresholds
-* the data is collected in BigBuf.
-**/
-void doT55x7Acquisition(size_t sample_size);
-
-/**
-* Initializes the FPGA for reader-mode (field on), and acquires the samples.
-* @return number of bits sampled
-**/
-uint32_t SampleLF(bool verbose, uint32_t sample_size);
-
-/**
-* Initializes the FPGA for sniff-mode (field off), and acquires the samples.
-* @return number of bits sampled
-**/
-uint32_t SniffLF();
-
-uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold,
- bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip);
-
-// adds sample size to default options
-uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after);
-
-/**
- * @brief Does sample acquisition, ignoring the config values set in the sample_config.
- * This method is typically used by tag-specific readers who just wants to read the samples
- * the normal way
- * @param trigger_threshold
- * @param verbose
- * @return number of bits sampled
- */
-uint32_t DoAcquisition_default(int trigger_threshold, bool verbose);
-/**
- * @brief Does sample acquisition, using the config values set in the sample_config.
- * @param trigger_threshold
- * @param verbose
- * @return number of bits sampled
- */
-
-uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size);
-
-/**
- * Refactoring of lf sampling buffer
- */
-void initSampleBuffer(uint32_t *sample_size);
-void initSampleBufferEx(uint32_t *sample_size, bool use_malloc);
-void logSampleSimple(uint8_t sample);
-void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg);
-uint32_t getSampleCounter();
-
-/**
-* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
-* if not already loaded, sets divisor and starts up the antenna.
-* @param divisor : 1, 88> 255 or negative ==> 134.8 kHz
-* 0 or 95 ==> 125 kHz
-*
-**/
-void LFSetupFPGAForADC(int divisor, bool lf_field);
-
-/**
- * Called from the USB-handler to set the sampling configuration
- * The sampling config is used for std reading and sniffing.
- *
- * Other functions may read samples and ignore the sampling config,
- * such as functions to read the UID from a prox tag or similar.
- *
- * Values set to '0' implies no change (except for averaging)
- * @brief setSamplingConfig
- * @param sc
- */
-void setSamplingConfig(sample_config *sc);
-
-sample_config *getSamplingConfig();
-
-void printConfig();
-
-#endif // __LFSAMPLING_H
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifarecmd.c b/pm3rdv4rrg/src/main/cpp/armsrc/mifarecmd.c
deleted file mode 100644
index 9e9c721b..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifarecmd.c
+++ /dev/null
@@ -1,2432 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011, 2012
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-// Midnitesnake - Dec 2013
-// Andy Davies - Apr 2014
-// Iceman - May 2014,2015,2016
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443 type A.
-//-----------------------------------------------------------------------------
-
-#include "mifarecmd.h"
-
-#include "pmflash.h"
-#include "proxmark3_arm.h"
-#include "string.h"
-#include "mifareutil.h"
-#include "protocols.h"
-#include "parity.h"
-#include "BigBuf.h"
-#include "cmd.h"
-#include "flashmem.h"
-#include "fpgaloader.h"
-#include "iso14443a.h"
-#include "mifaredesfire.h"
-#include "util.h"
-#include "commonutil.h"
-#include "crc16.h"
-#include "dbprint.h"
-#include "ticks.h"
-#include "usb_cdc.h" // usb_poll_validate_length
-#include "spiffs.h" // spiffs
-
-#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT
-# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
-#endif
-#ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME
-# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
-#endif
-
-// send an incomplete dummy response in order to trigger the card's authentication failure timeout
-#ifndef CHK_TIMEOUT
-# define CHK_TIMEOUT() { \
- ReaderTransmit(&dummy_answer, 1, NULL); \
- uint32_t timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; \
- while (GetCountSspClk() < timeout) {}; \
- }
-#endif
-
-static uint8_t dummy_answer = 0;
-
-//-----------------------------------------------------------------------------
-// Select, Authenticate, Read a MIFARE tag.
-// read block
-//-----------------------------------------------------------------------------
-void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) {
- // params
- uint64_t ui64Key = 0;
- ui64Key = bytes_to_num(datain, 6);
-
- // variables
- uint8_t dataoutbuf[16] = {0x00};
- uint8_t uid[10] = {0x00};
- uint32_t cuid = 0, status = PM3_EOPABORTED;
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- while (true) {
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- break;
- };
-
- if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
- if (DBGLEVEL >= 1) Dbprintf("Auth error");
- break;
- };
-
- if (mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {
- if (DBGLEVEL >= 1) Dbprintf("Read block error");
- break;
- };
-
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- break;
- };
-
- status = PM3_SUCCESS;
- break;
- }
-
- crypto1_deinit(pcs);
-
- if (DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
-
- LED_B_ON();
- reply_ng(CMD_HF_MIFARE_READBL, status, dataoutbuf, 16);
- LED_B_OFF();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
-}
-
-void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
-
- bool turnOffField = (arg0 == 1);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
- OnError(0);
- return;
- };
-
- if (!mifare_ultra_auth(keybytes)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Authentication failed");
- OnError(1);
- return;
- }
-
- if (turnOffField) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- }
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
-}
-
-// Arg0 = BlockNo,
-// Arg1 = UsePwd bool
-// datain = PWD bytes,
-void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
- uint8_t blockNo = arg0;
- uint8_t dataout[16] = {0x00};
- bool useKey = (arg1 == 1); //UL_C
- bool usePwd = (arg1 == 2); //UL_EV1/NTAG
-
- LEDsoff();
- LED_A_ON();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card (RC:%02X)", len);
- OnError(1);
- return;
- }
-
- // UL-C authentication
- if (useKey) {
- uint8_t key[16] = {0x00};
- memcpy(key, datain, sizeof(key));
-
- if (!mifare_ultra_auth(key)) {
- OnError(1);
- return;
- }
- }
-
- // UL-EV1 / NTAG authentication
- if (usePwd) {
- uint8_t pwd[4] = {0x00};
- memcpy(pwd, datain, 4);
- uint8_t pack[4] = {0, 0, 0, 0};
- if (!mifare_ul_ev1_auth(pwd, pack)) {
- OnError(1);
- return;
- }
- }
-
- if (mifare_ultra_readblock(blockNo, dataout)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Read block error");
- OnError(2);
- return;
- }
-
- if (mifare_ultra_halt()) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
- OnError(3);
- return;
- }
-
- reply_mix(CMD_ACK, 1, 0, 0, dataout, 16);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
-}
-
-//-----------------------------------------------------------------------------
-// Select, Authenticate, Read a MIFARE tag.
-// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)
-//-----------------------------------------------------------------------------
-void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
- // params
- uint8_t sectorNo = arg0;
- uint8_t keyType = arg1;
- uint64_t ui64Key = 0;
- ui64Key = bytes_to_num(datain, 6);
-
- // variables
- uint8_t isOK = 0;
- uint8_t dataoutbuf[16 * 16];
- uint8_t uid[10] = {0x00};
- uint32_t cuid = 0;
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- isOK = 1;
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- isOK = 0;
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- }
-
-
- if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
- isOK = 0;
- if (DBGLEVEL >= 1) Dbprintf("Auth error");
- }
-
- for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
- if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {
- isOK = 0;
- if (DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);
- break;
- }
- }
-
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- }
-
- if (DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
-
- crypto1_deinit(pcs);
-
- LED_B_ON();
- reply_old(CMD_ACK, isOK, 0, 0, dataoutbuf, 16 * NumBlocksPerSector(sectorNo));
- LED_B_OFF();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-
-// arg0 = blockNo (start)
-// arg1 = Pages (number of blocks)
-// arg2 = useKey
-// datain = KEY bytes
-void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) {
- LEDsoff();
- LED_A_ON();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // params
- uint8_t blockNo = arg0;
- uint16_t blocks = arg1;
- bool useKey = (arg2 == 1); //UL_C
- bool usePwd = (arg2 == 2); //UL_EV1/NTAG
- uint32_t countblocks = 0;
- uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE);
- if (dataout == NULL) {
- Dbprintf("out of memory");
- OnError(1);
- return;
- }
-
- int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card (RC:%d)", len);
- OnError(1);
- return;
- }
-
- // UL-C authentication
- if (useKey) {
- uint8_t key[16] = {0x00};
- memcpy(key, datain, sizeof(key));
-
- if (!mifare_ultra_auth(key)) {
- OnError(1);
- return;
- }
- }
-
- // UL-EV1 / NTAG authentication
- if (usePwd) {
- uint8_t pwd[4] = {0x00};
- memcpy(pwd, datain, sizeof(pwd));
- uint8_t pack[4] = {0, 0, 0, 0};
-
- if (!mifare_ul_ev1_auth(pwd, pack)) {
- OnError(1);
- return;
- }
- }
-
- for (int i = 0; i < blocks; i++) {
- if ((i * 4) + 4 >= CARD_MEMORY_SIZE) {
- Dbprintf("Data exceeds buffer!!");
- break;
- }
-
- len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);
-
- if (len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Read block %d error", i);
- // if no blocks read - error out
- if (i == 0) {
- OnError(2);
- return;
- } else {
- //stop at last successful read block and return what we got
- break;
- }
- } else {
- countblocks++;
- }
- }
-
- len = mifare_ultra_halt();
- if (len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
- OnError(3);
- return;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);
-
- countblocks *= 4;
-
- reply_mix(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- BigBuf_free();
- set_tracing(false);
-}
-
-//-----------------------------------------------------------------------------
-// Select, Authenticate, Write a MIFARE tag.
-// read block
-//-----------------------------------------------------------------------------
-void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
- // params
- uint8_t blockNo = arg0;
- uint8_t keyType = arg1;
- uint64_t ui64Key = 0;
- uint8_t blockdata[16] = {0x00};
-
- ui64Key = bytes_to_num(datain, 6);
- memcpy(blockdata, datain + 10, 16);
-
- // variables
- uint8_t isOK = 0;
- uint8_t uid[10] = {0x00};
- uint32_t cuid = 0;
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- while (true) {
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- break;
- };
-
- if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
- if (DBGLEVEL >= 1) Dbprintf("Auth error");
- break;
- };
-
- if (mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- break;
- };
-
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- break;
- };
-
- isOK = 1;
- break;
- }
-
- crypto1_deinit(pcs);
-
- if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
-
- reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-
-/* // Command not needed but left for future testing
-void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
-{
- uint8_t blockNo = arg0;
- uint8_t blockdata[16] = {0x00};
-
- memcpy(blockdata, datain, 16);
-
- uint8_t uid[10] = {0x00};
-
- LED_A_ON(); LED_B_OFF(); LED_C_OFF();
-
- clear_trace();
- set_tracing(true);
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- OnError(0);
- return;
- };
-
- if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- OnError(0);
- return; };
-
- if(mifare_ultra_halt()) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- OnError(0);
- return;
- };
-
- if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
-
- reply_mix(CMD_ACK,1,0,0,0,0);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
-}
-*/
-
-// Arg0 : Block to write to.
-// Arg1 : 0 = use no authentication.
-// 1 = use 0x1A authentication.
-// 2 = use 0x1B authentication.
-// datain : 4 first bytes is data to be written.
-// : 4/16 next bytes is authentication key.
-void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
- uint8_t blockNo = arg0;
- bool useKey = (arg1 == 1); //UL_C
- bool usePwd = (arg1 == 2); //UL_EV1/NTAG
- uint8_t blockdata[4] = {0x00};
-
- memcpy(blockdata, datain, 4);
-
- LEDsoff();
- LED_A_ON();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- OnError(0);
- return;
- };
-
- // UL-C authentication
- if (useKey) {
- uint8_t key[16] = {0x00};
- memcpy(key, datain + 4, sizeof(key));
-
- if (!mifare_ultra_auth(key)) {
- OnError(1);
- return;
- }
- }
-
- // UL-EV1 / NTAG authentication
- if (usePwd) {
- uint8_t pwd[4] = {0x00};
- memcpy(pwd, datain + 4, 4);
- uint8_t pack[4] = {0, 0, 0, 0};
- if (!mifare_ul_ev1_auth(pwd, pack)) {
- OnError(1);
- return;
- }
- }
-
- if (mifare_ultra_writeblock(blockNo, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- OnError(0);
- return;
- };
-
- if (mifare_ultra_halt()) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- OnError(0);
- return;
- };
-
- if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
-
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-
-void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
-
- uint8_t pwd[16] = {0x00};
- uint8_t blockdata[4] = {0x00};
-
- memcpy(pwd, datain, 16);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- OnError(0);
- return;
- };
-
- blockdata[0] = pwd[7];
- blockdata[1] = pwd[6];
- blockdata[2] = pwd[5];
- blockdata[3] = pwd[4];
- if (mifare_ultra_writeblock(44, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- OnError(44);
- return;
- };
-
- blockdata[0] = pwd[3];
- blockdata[1] = pwd[2];
- blockdata[2] = pwd[1];
- blockdata[3] = pwd[0];
- if (mifare_ultra_writeblock(45, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- OnError(45);
- return;
- };
-
- blockdata[0] = pwd[15];
- blockdata[1] = pwd[14];
- blockdata[2] = pwd[13];
- blockdata[3] = pwd[12];
- if (mifare_ultra_writeblock(46, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- OnError(46);
- return;
- };
-
- blockdata[0] = pwd[11];
- blockdata[1] = pwd[10];
- blockdata[2] = pwd[9];
- blockdata[3] = pwd[8];
- if (mifare_ultra_writeblock(47, blockdata)) {
- if (DBGLEVEL >= 1) Dbprintf("Write block error");
- OnError(47);
- return;
- };
-
- if (mifare_ultra_halt()) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- OnError(0);
- return;
- };
-
- reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-
-// Return 1 if the nonce is invalid else return 0
-int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
- return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) & \
- (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) & \
- (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0)))) ? 1 : 0;
-}
-
-void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
-
- uint8_t uid[10] = {0x00};
- uint8_t answer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t par[1] = {0x00};
- uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00};
- uint32_t cuid = 0;
- int16_t isOK = 0;
- uint16_t num_nonces = 0;
- uint8_t cascade_levels = 0;
- uint8_t blockNo = arg0 & 0xff;
- uint8_t keyType = (arg0 >> 8) & 0xff;
- bool initialize = flags & 0x0001;
- bool field_off = flags & 0x0004;
- bool have_uid = false;
-
- LED_A_ON();
- LED_C_OFF();
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- if (initialize)
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- LED_C_ON();
-
- for (uint16_t i = 0; i <= PM3_CMD_DATA_SIZE - 4; i += 4) {
-
- // Test if the action was cancelled
- if (BUTTON_PRESS()) {
- isOK = 2;
- field_off = true;
- break;
- }
-
- if (!have_uid) { // need a full select cycle to get the uid first
- iso14a_card_select_t card_info;
- if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");
- continue;
- }
- switch (card_info.uidlen) {
- case 4 :
- cascade_levels = 1;
- break;
- case 7 :
- cascade_levels = 2;
- break;
- case 10:
- cascade_levels = 3;
- break;
- default:
- break;
- }
- have_uid = true;
- } else { // no need for anticollision. We can directly select the card
- if (!iso14443a_fast_select_card(uid, cascade_levels)) {
- if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");
- continue;
- }
- }
-
- // Transmit MIFARE_CLASSIC_AUTH
- uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00};
- AddCrc14A(dcmd, 2);
- ReaderTransmit(dcmd, sizeof(dcmd), NULL);
- int len = ReaderReceive(answer, par);
-
- // wait for the card to become ready again
- CHK_TIMEOUT();
-
- if (len != 4) {
- if (DBGLEVEL >= 2) Dbprintf("AcquireNonces: Auth1 error");
- continue;
- }
-
- num_nonces++;
-
- // Save the tag nonce (nt)
- buf[i] = answer[0];
- buf[i + 1] = answer[1];
- buf[i + 2] = answer[2];
- buf[i + 3] = answer[3];
- }
-
- LED_C_OFF();
- LED_B_ON();
- reply_old(CMD_ACK, isOK, cuid, num_nonces - 1, buf, sizeof(buf));
- LED_B_OFF();
-
- if (DBGLEVEL >= 3) DbpString("AcquireNonces finished");
-
- if (field_off) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
- }
-}
-
-//-----------------------------------------------------------------------------
-// acquire encrypted nonces in order to perform the attack described in
-// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened
-// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on
-// Computer and Communications Security, 2015
-//-----------------------------------------------------------------------------
-void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) {
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- uint8_t uid[10] = {0x00};
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t par_enc[1] = {0x00};
- uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00};
-
- uint64_t ui64Key = bytes_to_num(datain, 6);
- uint32_t cuid = 0;
- int16_t isOK = 0;
- uint16_t num_nonces = 0;
- uint8_t nt_par_enc = 0;
- uint8_t cascade_levels = 0;
- uint8_t blockNo = arg0 & 0xff;
- uint8_t keyType = (arg0 >> 8) & 0xff;
- uint8_t targetBlockNo = arg1 & 0xff;
- uint8_t targetKeyType = (arg1 >> 8) & 0xff;
- bool initialize = flags & 0x0001;
- bool slow = flags & 0x0002;
- bool field_off = flags & 0x0004;
- bool have_uid = false;
-
- LED_A_ON();
- LED_C_OFF();
-
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(false);
-
- if (initialize)
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- LED_C_ON();
-
- for (uint16_t i = 0; i <= PM3_CMD_DATA_SIZE - 9;) {
-
- // Test if the action was cancelled
- if (BUTTON_PRESS()) {
- isOK = 2;
- field_off = true;
- break;
- }
-
- if (!have_uid) { // need a full select cycle to get the uid first
- iso14a_card_select_t card_info;
- if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");
- continue;
- }
- switch (card_info.uidlen) {
- case 4 :
- cascade_levels = 1;
- break;
- case 7 :
- cascade_levels = 2;
- break;
- case 10:
- cascade_levels = 3;
- break;
- default:
- break;
- }
- have_uid = true;
- } else { // no need for anticollision. We can directly select the card
- if (!iso14443a_fast_select_card(uid, cascade_levels)) {
- if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");
- continue;
- }
- }
-
- if (slow)
- SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME);
-
- uint32_t nt1;
- if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
- if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");
- continue;
- }
-
- // nested authentication
- uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
-
- // wait for the card to become ready again
- CHK_TIMEOUT();
-
- if (len != 4) {
- if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);
- continue;
- }
-
- num_nonces++;
- if (num_nonces % 2) {
- memcpy(buf + i, receivedAnswer, 4);
- nt_par_enc = par_enc[0] & 0xf0;
- } else {
- nt_par_enc |= par_enc[0] >> 4;
- memcpy(buf + i + 4, receivedAnswer, 4);
- memcpy(buf + i + 8, &nt_par_enc, 1);
- i += 9;
- }
- }
-
- LED_C_OFF();
- crypto1_deinit(pcs);
- LED_B_ON();
- reply_old(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
- LED_B_OFF();
-
- if (DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
-
- if (field_off) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// MIFARE nested authentication.
-//
-//-----------------------------------------------------------------------------
-void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key) {
- uint64_t ui64Key = 0;
- ui64Key = bytes_to_num(key, 6);
-
- // variables
- uint16_t i, j, len;
- static uint16_t dmin, dmax;
-
- uint8_t par[1] = {0x00};
- uint8_t par_array[4] = {0x00};
- uint8_t uid[10] = {0x00};
- uint32_t cuid = 0, nt1, nt2, nttest, ks1;
- uint32_t target_nt[2] = {0x00}, target_ks[2] = {0x00};
-
- uint16_t ncount = 0;
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
-
- uint32_t auth1_time, auth2_time;
- static uint16_t delta_time = 0;
-
- LED_A_ON();
- LED_C_OFF();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
- BigBuf_Clear_ext(false);
-
- if (calibrate)
- clear_trace();
-
- set_tracing(true);
-
- // statistics on nonce distance
- int16_t isOK = 0;
-#define NESTED_MAX_TRIES 12
- if (calibrate) { // calibrate: for first call only. Otherwise reuse previous calibration
- LED_B_ON();
- WDT_HIT();
-
- uint16_t unsuccessful_tries = 0;
- uint16_t davg = 0;
- dmax = 0;
- dmin = 2000;
- delta_time = 0;
- uint16_t rtr;
- for (rtr = 0; rtr < 17; rtr++) {
-
- // Test if the action was cancelled
- if (BUTTON_PRESS() || data_available()) {
- isOK = -2;
- break;
- }
-
- // prepare next select. No need to power down the card.
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Halt error");
- rtr--;
- continue;
- }
-
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Can't select card");
- rtr--;
- continue;
- };
-
- auth1_time = 0;
- if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
- rtr--;
- continue;
- };
- auth2_time = (delta_time) ? auth1_time + delta_time : 0;
-
- if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth2 error");
- rtr--;
- continue;
- };
-
- // cards with fixed nonce
- if (nt1 == nt2) {
- Dbprintf("Nested: %08x vs %08x", nt1, nt2);
- break;
- }
-
- uint32_t nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
- for (i = 101; i < 1200; i++) {
- nttmp = prng_successor(nttmp, 1);
- if (nttmp == nt2) break;
- }
-
- if (i != 1200) {
- if (rtr != 0) {
- davg += i;
- dmin = MIN(dmin, i);
- dmax = MAX(dmax, i);
- } else {
- delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing
- }
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Nested: calibrating... ntdist=%d", i);
- } else {
- unsuccessful_tries++;
- if (unsuccessful_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
- isOK = -3;
- }
- }
- }
-
- davg = (davg + (rtr - 1) / 2) / (rtr - 1);
-
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);
-
- dmin = davg - 2;
- dmax = davg + 2;
-
- LED_B_OFF();
- }
-// -------------------------------------------------------------------------------------------------
-
- LED_C_ON();
-
- // get crypted nonces for target sector
- for (i = 0; i < 2 && !isOK; i++) { // look for exactly two different nonces
-
- target_nt[i] = 0;
- while (target_nt[i] == 0) { // continue until we have an unambiguous nonce
-
- // Test if the action was cancelled
- if (BUTTON_PRESS() || data_available()) {
- isOK = -2;
- break;
- }
-
- // prepare next select. No need to power down the card.
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Halt error");
- continue;
- }
-
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Can't select card");
- continue;
- };
-
- auth1_time = 0;
- if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
- continue;
- };
-
- // nested authentication
- auth2_time = auth1_time + delta_time;
-
- len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
- if (len != 4) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth2 error len=%d", len);
- continue;
- };
-
- nt2 = bytes_to_num(receivedAnswer, 4);
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i + 1, nt1, nt2, par[0]);
-
- // Parity validity check
- for (j = 0; j < 4; j++) {
- par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7 - j)) & 0x01));
- }
-
- ncount = 0;
- nttest = prng_successor(nt1, dmin - 1);
- for (j = dmin; j < dmax + 1; j++) {
- nttest = prng_successor(nttest, 1);
- ks1 = nt2 ^ nttest;
-
- if (valid_nonce(nttest, nt2, ks1, par_array)) {
- if (ncount > 0) { // we are only interested in disambiguous nonces, try again
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Nonce#%d: dismissed (ambiguous), ntdist=%d", i + 1, j);
- target_nt[i] = 0;
- break;
- }
- target_nt[i] = nttest;
- target_ks[i] = ks1;
- ncount++;
- if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces
- target_nt[i] = 0;
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j);
- break;
- }
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Nonce#%d: valid, ntdist=%d", i + 1, j);
- }
- }
- if (target_nt[i] == 0 && j == dmax + 1 && DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i + 1);
- }
- }
-
- LED_C_OFF();
-
- crypto1_deinit(pcs);
-
- struct p {
- int16_t isOK;
- uint8_t block;
- uint8_t keytype;
- uint8_t cuid[4];
- uint8_t nt_a[4];
- uint8_t ks_a[4];
- uint8_t nt_b[4];
- uint8_t ks_b[4];
- } PACKED payload;
- payload.isOK = isOK;
- payload.block = targetBlockNo;
- payload.keytype = targetKeyType;
-
- memcpy(payload.cuid, &cuid, 4);
- memcpy(payload.nt_a, &target_nt[0], 4);
- memcpy(payload.ks_a, &target_ks[0], 4);
- memcpy(payload.nt_b, &target_nt[1], 4);
- memcpy(payload.ks_b, &target_ks[1], 4);
-
- LED_B_ON();
- reply_ng(CMD_HF_MIFARE_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
- LED_B_OFF();
-
- if (DBGLEVEL >= 3) DbpString("NESTED FINISHED");
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-
-void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key) {
-
- LEDsoff();
-
- uint64_t ui64Key = 0;
- ui64Key = bytes_to_num(key, 6);
-
- // variables
- uint16_t len;
-
- uint8_t uid[10] = {0x00};
- uint32_t cuid = 0, nt1, nt2;
- uint32_t target_nt = {0x00}, target_ks = {0x00};
- uint8_t par[1] = {0x00};
- uint8_t receivedAnswer[10] = {0x00};
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- LED_A_ON();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- int16_t isOK = 0;
-
- LED_C_ON();
-
- for (uint8_t retry = 0; retry < 3 && (isOK == 0); retry++) {
-
- WDT_HIT();
-
- // prepare next select. No need to power down the card.
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Halt error");
- retry--;
- continue;
- }
-
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Can't select card");
- retry--;
- continue;
- };
-
- // First authenticatoin. Normal auth.
- if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
- retry--;
- continue;
- };
-
- // second authentication. Nested auth
- len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, NULL);
- if (len != 4) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth2 error len=%d", len);
- continue;
- };
-
- nt2 = bytes_to_num(receivedAnswer, 4);
- uint32_t nt_tmp = prng_successor(nt1, 160);
- target_ks = nt2 ^ nt_tmp;
- target_nt = nt_tmp;
- isOK = 1;
-
- if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Testing nt1=%08x nt2enc=%08x nt2par=%02x ks=%08x", nt1, nt2, par[0], target_ks);
- }
-
- LED_C_OFF();
-
- crypto1_deinit(pcs);
-
- struct p {
- int16_t isOK;
- uint8_t block;
- uint8_t keytype;
- uint8_t cuid[4];
- uint8_t nt[4];
- uint8_t ks[4];
- } PACKED payload;
- payload.isOK = isOK;
- payload.block = targetBlockNo;
- payload.keytype = targetKeyType;
-
- memcpy(payload.cuid, &cuid, 4);
- memcpy(payload.nt, &target_nt, 4);
- memcpy(payload.ks, &target_ks, 4);
-
- LED_B_ON();
- reply_ng(CMD_HF_MIFARE_STATIC_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
- LED_B_OFF();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-//-----------------------------------------------------------------------------
-// MIFARE check keys. key count up to 85.
-//
-//-----------------------------------------------------------------------------
-typedef struct sector_t {
- uint8_t keyA[6];
- uint8_t keyB[6];
-} sector_t;
-
-typedef struct chk_t {
- uint64_t key;
- uint32_t cuid;
- uint8_t cl;
- uint8_t block;
- uint8_t keyType;
- uint8_t *uid;
- struct Crypto1State *pcs;
-} chk_t;
-
-// checks one key.
-// fast select, tries 5 times to select
-//
-// return:
-// 2 = failed to select.
-// 1 = wrong key
-// 0 = correct key
-uint8_t chkKey(struct chk_t *c) {
- uint8_t i = 0, res = 2;
- while (i < 5) {
- // this part is from Piwi's faster nonce collecting part in Hardnested.
- // assume: fast select
- if (!iso14443a_fast_select_card(c->uid, c->cl)) {
- ++i;
- continue;
- }
- res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL);
-
-// CHK_TIMEOUT();
-
- // if successful auth, send HALT
- // if ( !res )
- // mifare_classic_halt_ex(c->pcs);
- break;
- }
- return res;
-}
-
-uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) {
-
- if (!iso14443a_fast_select_card(c->uid, c->cl))
- return 2;
-
- if (mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL))
- return 1;
-
- uint8_t data[16] = {0x00};
- uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data);
-
- // successful read
- if (!res) {
- // data was something else than zeros.
- if (memcmp(data + 10, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
- memcpy(keyb, data + 10, 6);
- res = 0;
- } else {
- res = 3;
- }
- mifare_classic_halt_ex(c->pcs);
- }
- return res;
-}
-
-void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) {
- for (uint8_t s = 0; s < *sectorcnt; s++) {
-
- // skip already found A keys
- if (found[(s * 2)])
- continue;
-
- c->block = FirstBlockOfSector(s);
- if (chkKey(c) == 0) {
- num_to_bytes(c->key, 6, k_sector[s].keyA);
- found[(s * 2)] = 1;
- ++*foundkeys;
-
- if (DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A found (%d)", c->block);
- }
- }
-}
-
-void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) {
- for (uint8_t s = 0; s < *sectorcnt; s++) {
-
- // skip already found B keys
- if (found[(s * 2) + 1])
- continue;
-
- c->block = FirstBlockOfSector(s);
- if (chkKey(c) == 0) {
- num_to_bytes(c->key, 6, k_sector[s].keyB);
- found[(s * 2) + 1] = 1;
- ++*foundkeys;
-
- if (DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B found (%d)", c->block);
- }
- }
-}
-
-// loop all A keys,
-// when A is found but not B, try to read B.
-void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) {
-
- // read Block B, if A is found.
- for (uint8_t s = 0; s < *sectorcnt; ++s) {
-
- if (found[(s * 2)] && found[(s * 2) + 1])
- continue;
-
- c->block = (FirstBlockOfSector(s) + NumBlocksPerSector(s) - 1);
-
- // A but not B
- if (found[(s * 2)] && !found[(s * 2) + 1]) {
- c->key = bytes_to_num(k_sector[s].keyA, 6);
- uint8_t status = chkKey_readb(c, k_sector[s].keyB);
- if (status == 0) {
- found[(s * 2) + 1] = 1;
- ++*foundkeys;
-
- if (DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block);
-
- // try quick find all B?
- // assume: keys comes in groups. Find one B, test against all B.
- c->key = bytes_to_num(k_sector[s].keyB, 6);
- c->keyType = 1;
- chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys);
- }
- }
- }
-}
-
-// get Chunks of keys, to test authentication against card.
-// arg0 = antal sectorer
-// arg0 = first time
-// arg1 = clear trace
-// arg2 = antal nycklar i keychunk
-// datain = keys as array
-void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
-
- // first call or
- uint8_t sectorcnt = arg0 & 0xFF; // 16;
- uint8_t firstchunk = (arg0 >> 8) & 0xF;
- uint8_t lastchunk = (arg0 >> 12) & 0xF;
- uint8_t strategy = arg1 & 0xFF;
- uint8_t use_flashmem = (arg1 >> 8) & 0xFF;
- uint16_t keyCount = arg2 & 0xFF;
- uint8_t status = 0;
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
- struct chk_t chk_data;
-
- uint8_t allkeys = sectorcnt << 1;
-
- static uint32_t cuid = 0;
- static uint8_t cascade_levels = 0;
- static uint8_t foundkeys = 0;
- static sector_t k_sector[80];
- static uint8_t found[80];
- static uint8_t *uid;
-
- int oldbg = DBGLEVEL;
-
-#ifdef WITH_FLASH
- if (use_flashmem) {
- BigBuf_free();
- uint16_t isok = 0;
- uint8_t size[2] = {0x00, 0x00};
- isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2);
- if (isok != 2)
- goto OUT;
-
- keyCount = size[1] << 8 | size[0];
-
- if (keyCount == 0 || keyCount == 0xFFFF)
- goto OUT;
-
- datain = BigBuf_malloc(keyCount * 6);
- if (datain == NULL)
- goto OUT;
-
- isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET + 2, datain, keyCount * 6);
- if (isok != keyCount * 6)
- goto OUT;
-
- }
-#endif
-
- if (uid == NULL || firstchunk) {
- uid = BigBuf_malloc(10);
- if (uid == NULL)
- goto OUT;
- }
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- LEDsoff();
- LED_A_ON();
-
- if (firstchunk) {
- clear_trace();
- set_tracing(false);
-
- memset(k_sector, 0x00, 480 + 10);
- memset(found, 0x00, sizeof(found));
- foundkeys = 0;
-
- iso14a_card_select_t card_info;
- if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)");
- goto OUT;
- }
-
- switch (card_info.uidlen) {
- case 4 :
- cascade_levels = 1;
- break;
- case 7 :
- cascade_levels = 2;
- break;
- case 10:
- cascade_levels = 3;
- break;
- default:
- break;
- }
-
- CHK_TIMEOUT();
- }
-
- // clear debug level. We are expecting lots of authentication failures...
- DBGLEVEL = DBG_NONE;
-
- // set check struct.
- chk_data.uid = uid;
- chk_data.cuid = cuid;
- chk_data.cl = cascade_levels;
- chk_data.pcs = pcs;
- chk_data.block = 0;
-
- // keychunk loop - depth first one sector.
- if (strategy == 1 || use_flashmem) {
-
- uint8_t newfound = foundkeys;
-
- uint16_t lastpos = 0;
- uint16_t s_point = 0;
- // Sector main loop
- // keep track of how many sectors on card.
- for (uint8_t s = 0; s < sectorcnt; ++s) {
-
- if (found[(s * 2)] && found[(s * 2) + 1])
- continue;
-
- for (uint16_t i = s_point; i < keyCount; ++i) {
-
- // Allow button press / usb cmd to interrupt device
- if (BUTTON_PRESS() && data_available()) {
- goto OUT;
- }
-
- // found all keys?
- if (foundkeys == allkeys)
- goto OUT;
-
- WDT_HIT();
-
- // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector
- chk_data.block = FirstBlockOfSector(s);
-
- // new key
- chk_data.key = bytes_to_num(datain + i * 6, 6);
-
- // skip already found A keys
- if (!found[(s * 2)]) {
- chk_data.keyType = 0;
- status = chkKey(&chk_data);
- if (status == 0) {
- memcpy(k_sector[s].keyA, datain + i * 6, 6);
- found[(s * 2)] = 1;
- ++foundkeys;
-
- chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys);
-
- // read Block B, if A is found.
- chkKey_loopBonly(&chk_data, k_sector, found, §orcnt, &foundkeys);
-
- chk_data.keyType = 1;
- chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys);
-
- chk_data.keyType = 0;
- chk_data.block = FirstBlockOfSector(s);
-
- if (use_flashmem) {
- if (lastpos != i && lastpos != 0) {
- if (i - lastpos < 0xF) {
- s_point = i & 0xFFF0;
- }
- } else {
- lastpos = i;
- }
- }
- }
- }
-
- // skip already found B keys
- if (!found[(s * 2) + 1]) {
- chk_data.keyType = 1;
- status = chkKey(&chk_data);
- if (status == 0) {
- memcpy(k_sector[s].keyB, datain + i * 6, 6);
- found[(s * 2) + 1] = 1;
- ++foundkeys;
-
- chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys);
-
- if (use_flashmem) {
- if (lastpos != i && lastpos != 0) {
-
- if (i - lastpos < 0xF)
- s_point = i & 0xFFF0;
- } else {
- lastpos = i;
- }
- }
- }
- }
-
- if (found[(s * 2)] && found[(s * 2) + 1])
- break;
-
- } // end keys test loop - depth first
-
- // assume1. if no keys found in first sector, get next keychunk from client
- if (!use_flashmem && (newfound - foundkeys == 0))
- goto OUT;
-
- } // end loop - sector
- } // end strategy 1
-
- if (foundkeys == allkeys)
- goto OUT;
-
- if (strategy == 2 || use_flashmem) {
-
- // Keychunk loop
- for (uint16_t i = 0; i < keyCount; i++) {
-
- // Allow button press / usb cmd to interrupt device
- if (BUTTON_PRESS() && data_available()) break;
-
- // found all keys?
- if (foundkeys == allkeys)
- goto OUT;
-
- WDT_HIT();
-
- // new key
- chk_data.key = bytes_to_num(datain + i * 6, 6);
-
- // Sector main loop
- // keep track of how many sectors on card.
- for (uint8_t s = 0; s < sectorcnt; ++s) {
-
- if (found[(s * 2)] && found[(s * 2) + 1]) continue;
-
- // found all keys?
- if (foundkeys == allkeys)
- goto OUT;
-
- // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector
- chk_data.block = FirstBlockOfSector(s);
-
- // skip already found A keys
- if (!found[(s * 2)]) {
- chk_data.keyType = 0;
- status = chkKey(&chk_data);
- if (status == 0) {
- memcpy(k_sector[s].keyA, datain + i * 6, 6);
- found[(s * 2)] = 1;
- ++foundkeys;
-
- chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys);
-
- // read Block B, if A is found.
- chkKey_loopBonly(&chk_data, k_sector, found, §orcnt, &foundkeys);
-
- chk_data.block = FirstBlockOfSector(s);
- }
- }
-
- // skip already found B keys
- if (!found[(s * 2) + 1]) {
- chk_data.keyType = 1;
- status = chkKey(&chk_data);
- if (status == 0) {
- memcpy(k_sector[s].keyB, datain + i * 6, 6);
- found[(s * 2) + 1] = 1;
- ++foundkeys;
-
- chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys);
- }
- }
- } // end loop sectors
- } // end loop keys
- } // end loop strategy 2
-OUT:
- LEDsoff();
-
- crypto1_deinit(pcs);
-
- // All keys found, send to client, or last keychunk from client
- if (foundkeys == allkeys || lastchunk) {
-
- uint64_t foo = 0;
- for (uint8_t m = 0; m < 64; m++) {
- foo |= ((uint64_t)(found[m] & 1) << m);
- }
-
- uint16_t bar = 0;
- uint8_t j = 0;
- for (uint8_t m = 64; m < ARRAYLEN(found); m++) {
- bar |= ((uint16_t)(found[m] & 1) << j++);
- }
-
- uint8_t *tmp = BigBuf_malloc(480 + 10);
- memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t));
- num_to_bytes(foo, 8, tmp + 480);
- tmp[488] = bar & 0xFF;
- tmp[489] = bar >> 8 & 0xFF;
-
- reply_old(CMD_ACK, foundkeys, 0, 0, tmp, 480 + 10);
-
- set_tracing(false);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- BigBuf_free();
- BigBuf_Clear_ext(false);
-
- // special trick ecfill
- if (use_flashmem && foundkeys == allkeys) {
-
- uint8_t block[16] = {0};
- for (int i = 0; i < sectorcnt; i++) {
-
- uint8_t blockno;
- if (i < 32) {
- blockno = (i * 4) ^ 0x3;
- } else {
- blockno = (32 * 4 + (i - 32) * 16) ^ 0xF;
- }
- // get ST
- emlGetMem(block, blockno, 1);
-
- memcpy(block, k_sector[i].keyA, 6);
- memcpy(block + 10, k_sector[i].keyB, 6);
-
- emlSetMem_xt(block, blockno, 1, sizeof(block));
- }
-
- MifareECardLoad(sectorcnt, 0);
- MifareECardLoad(sectorcnt, 1);
- }
- } else {
- // partial/none keys found
- reply_mix(CMD_ACK, foundkeys, 0, 0, 0, 0);
- }
-
- DBGLEVEL = oldbg;
-}
-
-void MifareChkKeys(uint8_t *datain) {
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- uint8_t uid[10] = {0x00};
-
- uint64_t key = 0;
- uint32_t cuid = 0;
- int i, res;
- uint8_t cascade_levels = 0;
- struct {
- uint8_t key[6];
- bool found;
- } PACKED keyresult;
- keyresult.found = false;
- uint8_t blockNo, keyType;
- uint16_t keyCount;
- bool clearTrace, have_uid = false;
-
- keyType = datain[0];
- blockNo = datain[1];
- clearTrace = datain[2];
- keyCount = (datain[3] << 8) | datain[4];
- datain += 5;
-
- LEDsoff();
- LED_A_ON();
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- if (clearTrace)
- clear_trace();
-
- int oldbg = DBGLEVEL;
- DBGLEVEL = DBG_NONE;
-
- set_tracing(false);
-
- for (i = 0; i < keyCount; i++) {
-
- // Iceman: use piwi's faster nonce collecting part in hardnested.
- if (!have_uid) { // need a full select cycle to get the uid first
- iso14a_card_select_t card_info;
- if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)");
- --i; // try same key once again
- continue;
- }
- switch (card_info.uidlen) {
- case 4 :
- cascade_levels = 1;
- break;
- case 7 :
- cascade_levels = 2;
- break;
- case 10:
- cascade_levels = 3;
- break;
- default:
- break;
- }
- have_uid = true;
- } else { // no need for anticollision. We can directly select the card
- if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {
- if (DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)");
- --i; // try same key once again
- continue;
- }
- }
-
- key = bytes_to_num(datain + i * 6, 6);
- res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST);
-
-// CHK_TIMEOUT();
-
- if (res)
- continue;
-
- memcpy(keyresult.key, datain + i * 6, 6);
- keyresult.found = true;
- break;
- }
-
- LED_B_ON();
-
- reply_ng(CMD_HF_MIFARE_CHKKEYS, PM3_SUCCESS, (uint8_t *)&keyresult, sizeof(keyresult));
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
-
- set_tracing(false);
- crypto1_deinit(pcs);
-
- DBGLEVEL = oldbg;
-}
-
-void MifareChkKeys_file(uint8_t *fn) {
-
-#ifdef WITH_FLASH
- SpinOff(0);
-
- int changed = rdv40_spiffs_lazy_mount();
- uint32_t size = size_in_spiffs((char *)fn);
- uint8_t *mem = BigBuf_malloc(size);
-
- rdv40_spiffs_read_as_filetype((char *)fn, mem, size, RDV40_SPIFFS_SAFETY_SAFE);
-
- if (changed) {
- rdv40_spiffs_lazy_unmount();
- }
-
- SpinOff(0);
-
- MifareChkKeys(mem);
-
- BigBuf_free();
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Work with emulator memory
-//
-// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
-// involved in dealing with emulator memory. But if it is called later, it might
-// destroy the Emulator Memory.
-//-----------------------------------------------------------------------------
-
-void MifareEMemClr(void) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- emlClearMem();
-}
-
-void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- if (blockwidth == 0)
- blockwidth = 16; // backwards compat... default bytewidth
-
- emlSetMem_xt(datain, blockno, blockcnt, blockwidth); // data, block num, blocks count, block byte width
-}
-
-void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-
- //
- size_t size = blockcnt * 16;
- if (size > PM3_CMD_DATA_SIZE) {
- reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
- return;
- }
-
- uint8_t *buf = BigBuf_malloc(size);
-
- emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4)
-
- LED_B_ON();
- reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
- LED_B_OFF();
- BigBuf_free_keep_EM();
-}
-
-//-----------------------------------------------------------------------------
-// Load a card into the emulator memory
-//
-//-----------------------------------------------------------------------------
-int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype) {
- int retval = MifareECardLoad(sectorcnt, keytype);
- reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0);
- return retval;
-}
-
-int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
-
- uint32_t cuid = 0;
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- // variables
- uint8_t dataoutbuf[16] = {0x00};
- uint8_t dataoutbuf2[16] = {0x00};
- uint8_t uid[10] = {0x00};
-
- LED_A_ON();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- int retval;
-
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- retval = PM3_ESOFT;
- if (DBGLEVEL > DBG_ERROR) Dbprintf("Can't select card");
- goto out;
- }
-
- for (uint8_t sectorNo = 0; sectorNo < sectorcnt; sectorNo++) {
- uint64_t ui64Key = emlGetKey(sectorNo, keytype);
- if (sectorNo == 0) {
- if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_FIRST)) {
- if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo);
- break;
- }
- } else {
- if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_NESTED)) {
- retval = PM3_ESOFT;
- if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
- goto out;
- }
- }
-
- for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
- if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
- retval = PM3_ESOFT;
- if (DBGLEVEL > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
- break;
- }
- if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
- emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
- } else { // sector trailer, keep the keys, set only the AC
- emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
- memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
- emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
- }
- }
- }
-
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL > DBG_ERROR)
- Dbprintf("Halt error");
- }
-
- if (DBGLEVEL >= DBG_INFO) DbpString("Emulator fill sectors finished");
-
-out:
- crypto1_deinit(pcs);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
- return retval;
-}
-
-
-//-----------------------------------------------------------------------------
-// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
-//
-// PARAMS - workFlags
-// bit 0 - need get UID
-// bit 1 - need wupC
-// bit 2 - need HALT after sequence
-// bit 3 - need turn on FPGA before sequence
-// bit 4 - need turn off FPGA
-// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
-// bit 6 - wipe tag.
-//-----------------------------------------------------------------------------
-// magic uid card generation 1 commands
-uint8_t wupC1[] = { MIFARE_MAGICWUPC1 };
-uint8_t wupC2[] = { MIFARE_MAGICWUPC2 };
-uint8_t wipeC[] = { MIFARE_MAGICWIPEC };
-
-void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
-
- // params
- uint8_t workFlags = arg0;
- uint8_t blockNo = arg1;
-
- // detect 1a/1b
- bool is1b = false;
-
- // variables
- bool isOK = false; //assume we will get an error
- uint8_t errormsg = 0x00;
- uint8_t uid[10] = {0x00};
- uint8_t data[18] = {0x00};
- uint32_t cuid = 0;
-
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- if (workFlags & MAGIC_INIT) {
- LED_A_ON();
- LED_B_OFF();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- clear_trace();
- set_tracing(true);
- }
-
- //loop doesn't loop just breaks out if error
- while (true) {
- // read UID and return to client with write
- if (workFlags & MAGIC_UID) {
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
- errormsg = MAGIC_UID;
- }
- mifare_classic_halt_ex(NULL);
- break;
- }
-
- // wipe tag, fill it with zeros
- if (workFlags & MAGIC_WIPE) {
- ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("wupC1 error");
- errormsg = MAGIC_WIPE;
- break;
- }
-
- ReaderTransmit(wipeC, sizeof(wipeC), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("wipeC error");
- errormsg = MAGIC_WIPE;
- break;
- }
-
- mifare_classic_halt_ex(NULL);
- }
-
- // write block
- if (workFlags & MAGIC_WUPC) {
- ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("wupC1 error");
- errormsg = MAGIC_WUPC;
- break;
- }
-
- if (!is1b) {
- ReaderTransmit(wupC2, sizeof(wupC2), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]");
- is1b = true;
- continue;
- }
- }
- }
-
- if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("write block send command error");
- errormsg = 4;
- break;
- }
-
- memcpy(data, datain, 16);
- AddCrc14A(data, 16);
-
- ReaderTransmit(data, sizeof(data), NULL);
- if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("write block send data error");
- errormsg = 0;
- break;
- }
-
- if (workFlags & MAGIC_HALT)
- mifare_classic_halt_ex(NULL);
-
- isOK = true;
- break;
-
- } // end while
-
- if (isOK)
- reply_mix(CMD_ACK, 1, 0, 0, uid, sizeof(uid));
- else
- OnErrorMagic(errormsg);
-
- if (workFlags & MAGIC_OFF)
- OnSuccessMagic();
-}
-
-void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
-
- uint8_t workFlags = arg0;
- uint8_t blockNo = arg1;
- uint8_t errormsg = 0x00;
- bool isOK = false; //assume we will get an error
-
- // detect 1a/1b
- bool is1b = false;
-
- // variables
- uint8_t data[MAX_MIFARE_FRAME_SIZE];
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- memset(data, 0x00, sizeof(data));
-
- if (workFlags & MAGIC_INIT) {
- LED_A_ON();
- LED_B_OFF();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- clear_trace();
- set_tracing(true);
- }
-
- //loop doesn't loop just breaks out if error or done
- while (true) {
- if (workFlags & MAGIC_WUPC) {
- ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("wupC1 error");
- errormsg = MAGIC_WUPC;
- break;
- }
-
- if (!is1b) {
- ReaderTransmit(wupC2, sizeof(wupC2), NULL);
- if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]");
- is1b = true;
- continue;
- }
- }
- }
-
- // read block
- if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("read block send command error");
- errormsg = 0;
- break;
- }
-
- memcpy(data, receivedAnswer, sizeof(data));
-
- // send HALT
- if (workFlags & MAGIC_HALT)
- mifare_classic_halt_ex(NULL);
-
- isOK = true;
- break;
- }
- // if MAGIC_DATAIN, the data stays on device side.
- if (workFlags & MAGIC_DATAIN) {
- if (isOK)
- memcpy(datain, data, sizeof(data));
- } else {
- if (isOK)
- reply_old(CMD_ACK, 1, 0, 0, data, sizeof(data));
- else
- OnErrorMagic(errormsg);
- }
-
- if (workFlags & MAGIC_OFF)
- OnSuccessMagic();
-}
-
-void MifareCIdent() {
- // variables
- uint8_t isGen = 0;
- uint8_t rec[1] = {0x00};
- uint8_t recpar[1] = {0x00};
- uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 };
- uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
- uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
- uint8_t *uid = BigBuf_malloc(10);
- uint32_t cuid = 0;
- uint8_t data[1] = {0x00};
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- // Generation 1 test
- ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
- if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) {
- ReaderTransmit(wupC2, sizeof(wupC2), NULL);
- if (!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) {
- isGen = MAGIC_GEN_1B;
- goto OUT;
- };
- isGen = MAGIC_GEN_1A;
- goto OUT;
- }
-
- // reset card
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(40);
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
- if (res == 2) {
- if (cuid == 0xAA55C396) {
- isGen = MAGIC_GEN_UNFUSED;
- goto OUT;
- }
-
- ReaderTransmit(rats, sizeof(rats), NULL);
- res = ReaderReceive(buf, par);
- if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
- isGen = MAGIC_GEN_2;
- goto OUT;
- }
- if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
- isGen = MAGIC_GEN_2;
- }
- };
-
-OUT:
-
- data[0] = isGen;
- reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, data, sizeof(data));
- // turns off
- OnSuccessMagic();
- BigBuf_free();
-}
-
-void MifareHasStaticNonce() {
-
- // variables
- int retval = PM3_SUCCESS, len;
-
- uint32_t nt = 0 ;
- uint8_t rec[1] = {0x00};
- uint8_t recpar[1] = {0x00};
- uint8_t *uid = BigBuf_malloc(10);
- uint8_t data[1] = {0x00};
-
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
- iso14a_card_select_t card_info;
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- for (int i = 0; i < 3; i++) {
- if (!iso14443a_select_card(uid, &card_info, NULL, true, 0, true)) {
- retval = PM3_ESOFT;
- goto OUT;
- }
-
- // Transmit MIFARE_CLASSIC_AUTH 0x60, block 0
- len = mifare_sendcmd_short(pcs, false, MIFARE_AUTH_KEYA, 0, rec, recpar, NULL);
- if (len != 4) {
- retval = PM3_ESOFT;
- goto OUT;
- }
-
- // Save the tag nonce (nt)
- if (nt == bytes_to_num(rec, 4)) {
- data[0]++;
- }
-
- nt = bytes_to_num(rec, 4);
-
-// CHK_TIMEOUT();
- }
-
-OUT:
- reply_ng(CMD_HF_MIFARE_STATIC_NONCE, retval, data, sizeof(data));
- // turns off
- OnSuccessMagic();
- BigBuf_free();
- crypto1_deinit(pcs);
-}
-
-void OnSuccessMagic() {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-void OnErrorMagic(uint8_t reason) {
- // ACK, ISOK, reason,0,0,0
- reply_mix(CMD_ACK, 0, reason, 0, 0, 0);
- OnSuccessMagic();
-}
-
-void MifareSetMod(uint8_t *datain) {
-
- uint8_t mod = datain[0];
- uint64_t ui64Key = bytes_to_num(datain + 1, 6);
-
- // variables
- uint16_t isOK = PM3_EUNDEF;
- uint8_t uid[10] = {0};
- uint32_t cuid = 0;
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs = &mpcs;
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0};
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- clear_trace();
- set_tracing(true);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- while (true) {
- if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
- if (DBGLEVEL >= 1) Dbprintf("Can't select card");
- break;
- }
-
- if (mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) {
- if (DBGLEVEL >= 1) Dbprintf("Auth error");
- break;
- }
-
- int respLen;
- if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) {
- if (DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
- break;
- }
-
- if (mifare_classic_halt(pcs, cuid)) {
- if (DBGLEVEL >= 1) Dbprintf("Halt error");
- break;
- }
-
- isOK = PM3_SUCCESS;
- break;
- }
-
- crypto1_deinit(pcs);
-
- LED_B_ON();
- reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0);
-
- LED_B_OFF();
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
-}
-
-//
-// DESFIRE
-//
-void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain) {
- uint8_t dataout[12] = {0x00};
- uint8_t uid[10] = {0x00};
- uint32_t cuid = 0;
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- clear_trace();
- set_tracing(true);
-
- int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, false);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
- OnError(1);
- return;
- };
-
- if (mifare_desfire_des_auth1(cuid, dataout)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Authentication part1: Fail.");
- OnError(4);
- return;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
- reply_mix(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
-}
-
-void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
- uint32_t cuid = arg0;
- uint8_t key[16] = {0x00};
- uint8_t dataout[12] = {0x00};
- uint8_t isOK = 0;
-
- memcpy(key, datain, 16);
-
- isOK = mifare_desfire_des_auth2(cuid, key, dataout);
-
- if (isOK) {
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication part2: Failed");
- OnError(4);
- return;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED) DbpString("AUTH 2 FINISHED");
-
- reply_old(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
-}
-
-//
-// Tear-off attack against MFU.
-// - Moebius et al
-void MifareU_Otp_Tearoff() {
-
-// should the
-// optional time be configurable via client side?
-// optional authentication before?
-// optional data to be written?
-
- if (DBGLEVEL >= DBG_ERROR) DbpString("Preparing OTP tear-off");
-
- LEDsoff();
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- clear_trace();
- set_tracing(true);
-
- StartTicks();
-
-#define OTP_TEAR_OFF_TIME 1000
-#define OTP_BLK_NO 3
-
- // write cmd to send, include CRC
- // 1b write, 1b block, 4b data, 2 crc
- uint8_t cmd[] = {MIFARE_ULC_WRITE, OTP_BLK_NO, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0};
-
-// User specific data to write?
-// memcpy(block + 2, blockData, 4);
-
- AddCrc14A(cmd, sizeof(cmd) - 2);
-
- if (DBGLEVEL >= DBG_ERROR) DbpString("Transmitting");
-
- // anticollision / select card
- if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
- OnError(1);
- return;
- };
-
- /*
- // UL-EV1 / NTAG authentication
- if (usePwd) {
- uint8_t pwd[4] = {0x00};
- memcpy(pwd, datain + 4, 4);
- uint8_t pack[4] = {0, 0, 0, 0};
- if (!mifare_ul_ev1_auth(pwd, pack)) {
- OnError(1);
- return;
- }
- }
- */
-
- // send
- ReaderTransmit(cmd, sizeof(cmd), NULL);
-
- // Wait before cutting power. aka tear-off
- LED_D_ON();
- WaitUS(OTP_TEAR_OFF_TIME);
- switch_off();
-
- reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0);
- StopTicks();
-
- if (DBGLEVEL >= DBG_ERROR) DbpString("Done");
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifarecmd.h b/pm3rdv4rrg/src/main/cpp/armsrc/mifarecmd.h
deleted file mode 100644
index 1f5ee63a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifarecmd.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __MIFARECMD_H
-#define __MIFARECMD_H
-
-#include "common.h"
-
-void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
-
-void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
-void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
-void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
-
-void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
-
-void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key);
-
-void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
-void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
-void MifareChkKeys(uint8_t *datain);
-void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareChkKeys_file(uint8_t *fn);
-
-void MifareEMemClr(void);
-void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
-void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
-int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
-int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype);
-
-void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
-void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
-void MifareCIdent(); // is "magic chinese" card?
-void MifareHasStaticNonce(); // Has the tag a static nonce?
-
-void MifareSetMod(uint8_t *datain);
-void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
-void OnSuccessMagic();
-void OnErrorMagic(uint8_t reason);
-
-int32_t dist_nt(uint32_t nt1, uint32_t nt2);
-void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
-//void RAMFUNC SniffMifare(uint8_t param);
-
-void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
-void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
-
-// Tear-off test for MFU
-void MifareU_Otp_Tearoff();
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifaredesfire.c b/pm3rdv4rrg/src/main/cpp/armsrc/mifaredesfire.c
deleted file mode 100644
index 8fd48c62..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifaredesfire.c
+++ /dev/null
@@ -1,597 +0,0 @@
-#include "mifaredesfire.h"
-
-#include "common.h"
-#include "proxmark3_arm.h"
-#include "string.h"
-#include "BigBuf.h"
-#include "desfire_key.h"
-#include "mifareutil.h"
-#include "des.h"
-#include "cmd.h"
-#include "dbprint.h"
-#include "fpgaloader.h"
-#include "iso14443a.h"
-#include "crc16.h"
-#include "mbedtls/aes.h"
-#include "commonutil.h"
-
-#define MAX_APPLICATION_COUNT 28
-#define MAX_FILE_COUNT 16
-#define MAX_DESFIRE_FRAME_SIZE 60
-#define NOT_YET_AUTHENTICATED 255
-#define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
-#define RECEIVE_SIZE 64
-
-// the block number for the ISO14443-4 PCB
-uint8_t pcb_blocknum = 0;
-// Deselect card by sending a s-block. the crc is precalced for speed
-static uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4};
-
-//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
-/* PCB CID CMD PAYLOAD */
-//static uint8_t __res[MAX_FRAME_SIZE];
-
-bool InitDesfireCard() {
-
- iso14a_card_select_t card;
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
- set_tracing(true);
-
- if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
- if (DBGLEVEL >= DBG_ERROR) DbpString("Can't select card");
- OnError(1);
- return false;
- }
- return true;
-}
-
-// ARG0 flag enums
-enum {
- NONE = 0x00,
- INIT = 0x01,
- DISCONNECT = 0x02,
- CLEARTRACE = 0x04,
- BAR = 0x08,
-} CmdOptions ;
-
-void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
-
- /* ARG0 contains flags.
- 0x01 = init card.
- 0x02 = Disconnect
- 0x03
- */
- uint8_t flags = arg0;
- size_t datalen = arg1;
- uint8_t resp[RECEIVE_SIZE];
- memset(resp, 0, sizeof(resp));
-
- if (DBGLEVEL >= 4) {
- Dbprintf(" flags : %02X", flags);
- Dbprintf(" len : %02X", datalen);
- print_result(" RX : ", datain, datalen);
- }
-
- if (flags & CLEARTRACE)
- clear_trace();
-
- if (flags & INIT) {
- if (!InitDesfireCard())
- return;
- }
-
- int len = DesfireAPDU(datain, datalen, resp);
- if (DBGLEVEL >= 4)
- print_result("ERR <--: ", resp, len);
-
- if (!len) {
- OnError(2);
- return;
- }
-
- // reset the pcb_blocknum,
- pcb_blocknum = 0;
-
- if (flags & DISCONNECT)
- OnSuccess();
-
- reply_old(CMD_ACK, 1, len, 0, resp, len);
-}
-
-void MifareDesfireGetInformation() {
-
- int len = 0;
- iso14a_card_select_t card;
- uint8_t resp[PM3_CMD_DATA_SIZE] = {0x00};
- uint8_t dataout[PM3_CMD_DATA_SIZE] = {0x00};
-
- /*
- 1 = PCB 1
- 2 = cid 2
- 3 = desfire command 3
- 4-5 = crc 4 key
- 5-6 crc
- PCB == 0x0A because sending CID byte.
- CID == 0x00 first card?
- */
- clear_trace();
- set_tracing(true);
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- // card select - information
- if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
- if (DBGLEVEL >= DBG_ERROR) DbpString("Can't select card");
- OnError(1);
- return;
- }
-
- if (card.uidlen != 7) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen);
- OnError(2);
- return;
- }
-
- memcpy(dataout, card.uid, 7);
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- uint8_t cmd[] = {GET_VERSION};
- size_t cmd_len = sizeof(cmd);
-
- len = DesfireAPDU(cmd, cmd_len, resp);
- if (!len) {
- print_result("ERROR <--: ", resp, len);
- OnError(3);
- return;
- }
-
- LED_A_OFF();
- LED_B_ON();
- memcpy(dataout + 7, resp + 3, 7);
-
- // ADDITION_FRAME 1
- cmd[0] = ADDITIONAL_FRAME;
- len = DesfireAPDU(cmd, cmd_len, resp);
- if (!len) {
- print_result("ERROR <--: ", resp, len);
- OnError(3);
- return;
- }
-
- LED_B_OFF();
- LED_C_ON();
- memcpy(dataout + 7 + 7, resp + 3, 7);
-
- // ADDITION_FRAME 2
- len = DesfireAPDU(cmd, cmd_len, resp);
- if (!len) {
- print_result("ERROR <--: ", resp, len);
- OnError(3);
- return;
- }
-
- memcpy(dataout + 7 + 7 + 7, resp + 3, 14);
-
- reply_old(CMD_ACK, 1, 0, 0, dataout, sizeof(dataout));
-
- // reset the pcb_blocknum,
- pcb_blocknum = 0;
- OnSuccess();
-}
-
-void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
- // mode = arg0
- // algo = arg1
- // keyno = arg2
- int len = 0;
- //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
- uint8_t PICC_MASTER_KEY16[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
- //uint8_t null_key_data16[16] = {0x00};
- //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
- //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
-
- uint8_t resp[256] = {0x00};
-
- size_t datalen = datain[0];
-
- uint8_t cmd[40] = {0x00};
- uint8_t encRndB[16] = {0x00};
- uint8_t decRndB[16] = {0x00};
- uint8_t both[32] = {0x00};
-
- InitDesfireCard();
-
- LED_A_ON();
- LED_B_OFF();
- LED_C_OFF();
-
- // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
- // 4 different crypto arg1 DES, 3DES, 3K3DES, AES
- // 3 different communication modes, PLAIN,MAC,CRYPTO
-
- // des, key 0,
- switch (arg0) {
- case 1: {
- uint8_t keybytes[16];
- uint8_t RndA[8] = {0x00};
- uint8_t RndB[8] = {0x00};
-
- if (arg1 == 2) {
- if (datain[1] == 0xff) {
- memcpy(keybytes, PICC_MASTER_KEY16, 16);
- } else {
- memcpy(keybytes, datain + 1, datalen);
- }
- } else {
- if (arg1 == 1) {
- if (datain[1] == 0xff) {
- uint8_t null_key_data8[8] = {0x00};
- memcpy(keybytes, null_key_data8, 8);
- } else {
- memcpy(keybytes, datain + 1, datalen);
- }
- }
- }
-
- struct desfire_key defaultkey = {0};
- desfirekey_t key = &defaultkey;
-
- if (arg1 == 2)
- Desfire_3des_key_new_with_version(keybytes, key);
- else if (arg1 == 1)
- Desfire_des_key_new(keybytes, key);
-
- cmd[0] = AUTHENTICATE;
- cmd[1] = arg2; //keynumber
- len = DesfireAPDU(cmd, 2, resp);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) {
- DbpString("Authentication failed. Card timeout.");
- }
- OnError(3);
- return;
- }
-
- if (resp[2] == 0xaf) {
- } else {
- DbpString("Authentication failed. Invalid key number.");
- OnError(3);
- return;
- }
-
- memcpy(encRndB, resp + 3, 8);
- if (arg1 == 2)
- tdes_dec(&decRndB, &encRndB, key->data);
- else if (arg1 == 1)
- des_dec(&decRndB, &encRndB, key->data);
-
- memcpy(RndB, decRndB, 8);
- rol(decRndB, 8);
-
- // This should be random
- uint8_t decRndA[8] = {0x00};
- memcpy(RndA, decRndA, 8);
- uint8_t encRndA[8] = {0x00};
-
- if (arg1 == 2)
- tdes_dec(&encRndA, &decRndA, key->data);
- else if (arg1 == 1)
- des_dec(&encRndA, &decRndA, key->data);
-
- memcpy(both, encRndA, 8);
-
- for (int x = 0; x < 8; x++) {
- decRndB[x] = decRndB[x] ^ encRndA[x];
-
- }
-
- if (arg1 == 2)
- tdes_dec(&encRndB, &decRndB, key->data);
- else if (arg1 == 1)
- des_dec(&encRndB, &decRndB, key->data);
-
- memcpy(both + 8, encRndB, 8);
-
- cmd[0] = ADDITIONAL_FRAME;
- memcpy(cmd + 1, both, 16);
-
- len = DesfireAPDU(cmd, 17, resp);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) {
- DbpString("Authentication failed. Card timeout.");
- }
- OnError(3);
- return;
- }
-
- if (resp[2] == 0x00) {
-
- struct desfire_key sessionKey = {0};
- desfirekey_t skey = &sessionKey;
- Desfire_session_key_new(RndA, RndB, key, skey);
- //print_result("SESSION : ", skey->data, 8);
-
- memcpy(encRndA, resp + 3, 8);
-
- if (arg1 == 2)
- tdes_dec(&encRndA, &encRndA, key->data);
- else if (arg1 == 1)
- des_dec(&encRndA, &encRndA, key->data);
-
- rol(decRndA, 8);
- for (int x = 0; x < 8; x++) {
- if (decRndA[x] != encRndA[x]) {
- DbpString("Authentication failed. Cannot varify PICC.");
- OnError(4);
- return;
- }
- }
-
- //Change the selected key to a new value.
- /*
-
- // Current key is a 3DES key, change it to a DES key
- if (arg1 == 2) {
- cmd[0] = CHANGE_KEY;
- cmd[1] = arg2;
-
- uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
-
- uint8_t first, second;
- uint8_t buff1[8] = {0x00};
- uint8_t buff2[8] = {0x00};
- uint8_t buff3[8] = {0x00};
-
- memcpy(buff1,newKey, 8);
- memcpy(buff2,newKey + 8, 8);
-
- compute_crc(CRC_14443_A, newKey, 16, &first, &second);
- memcpy(buff3, &first, 1);
- memcpy(buff3 + 1, &second, 1);
-
- tdes_dec(&buff1, &buff1, skey->data);
- memcpy(cmd+2,buff1,8);
-
- for (int x = 0; x < 8; x++) {
- buff2[x] = buff2[x] ^ buff1[x];
- }
- tdes_dec(&buff2, &buff2, skey->data);
- memcpy(cmd+10,buff2,8);
-
- for (int x = 0; x < 8; x++) {
- buff3[x] = buff3[x] ^ buff2[x];
- }
- tdes_dec(&buff3, &buff3, skey->data);
- memcpy(cmd+18,buff3,8);
-
- // The command always times out on the first attempt, this will retry until a response
- // is recieved.
- len = 0;
- while(!len) {
- len = DesfireAPDU(cmd,26,resp);
- }
-
- } else {
- // Current key is a DES key, change it to a 3DES key
- if (arg1 == 1) {
- cmd[0] = CHANGE_KEY;
- cmd[1] = arg2;
-
- uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
-
- uint8_t first, second;
- uint8_t buff1[8] = {0x00};
- uint8_t buff2[8] = {0x00};
- uint8_t buff3[8] = {0x00};
-
- memcpy(buff1,newKey, 8);
- memcpy(buff2,newKey + 8, 8);
-
- compute_crc(CRC_14443_A, newKey, 16, &first, &second);
- memcpy(buff3, &first, 1);
- memcpy(buff3 + 1, &second, 1);
-
- des_dec(&buff1, &buff1, skey->data);
- memcpy(cmd+2,buff1,8);
-
- for (int x = 0; x < 8; x++) {
- buff2[x] = buff2[x] ^ buff1[x];
- }
- des_dec(&buff2, &buff2, skey->data);
- memcpy(cmd+10,buff2,8);
-
- for (int x = 0; x < 8; x++) {
- buff3[x] = buff3[x] ^ buff2[x];
- }
- des_dec(&buff3, &buff3, skey->data);
- memcpy(cmd+18,buff3,8);
-
- // The command always times out on the first attempt, this will retry until a response
- // is recieved.
- len = 0;
- while(!len) {
- len = DesfireAPDU(cmd,26,resp);
- }
- }
- }
- */
-
- OnSuccess();
- if (arg1 == 2)
- reply_old(CMD_ACK, 1, 0, 0, skey->data, 16);
- else if (arg1 == 1)
- reply_old(CMD_ACK, 1, 0, 0, skey->data, 8);
- } else {
- DbpString("Authentication failed.");
- OnError(6);
- return;
- }
- }
- break;
- case 2:
- //SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp);
- break;
- case 3: {
-
- //defaultkey
- uint8_t keybytes[16] = {0x00};
- if (datain[1] == 0xff) {
- memcpy(keybytes, PICC_MASTER_KEY16, 16);
- } else {
- memcpy(keybytes, datain + 1, datalen);
- }
-
- struct desfire_key defaultkey = {0x00};
- desfirekey_t key = &defaultkey;
- Desfire_aes_key_new(keybytes, key);
-
- mbedtls_aes_context ctx;
- uint8_t IV[16] = {0x00};
- mbedtls_aes_init(&ctx);
-
- cmd[0] = AUTHENTICATE_AES;
- cmd[1] = 0x00; //keynumber
- len = DesfireAPDU(cmd, 2, resp);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) {
- DbpString("Authentication failed. Card timeout.");
- }
- OnError(3);
- return;
- }
-
- memcpy(encRndB, resp + 3, 16);
-
- // dekryptera tagnonce.
- if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
- if (DBGLEVEL >= 4) {
- DbpString("mbedtls_aes_setkey_dec failed");
- }
- OnError(7);
- return;
- }
- mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, decRndB);
- rol(decRndB, 16);
- uint8_t nonce[16] = {0x00};
- memcpy(both, nonce, 16);
- memcpy(both + 16, decRndB, 16);
- uint8_t encBoth[32] = {0x00};
- if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) {
- if (DBGLEVEL >= 4) {
- DbpString("mbedtls_aes_setkey_enc failed");
- }
- OnError(7);
- return;
- }
- mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, both, encBoth);
-
- cmd[0] = ADDITIONAL_FRAME;
- memcpy(cmd + 1, encBoth, 32);
-
- len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) {
- DbpString("Authentication failed. Card timeout.");
- }
- OnError(3);
- return;
- }
-
- if (resp[2] == 0x00) {
- // Create AES Session key
- struct desfire_key sessionKey = {0};
- desfirekey_t skey = &sessionKey;
- Desfire_session_key_new(nonce, decRndB, key, skey);
- print_result("SESSION : ", skey->data, 16);
- } else {
- DbpString("Authentication failed.");
- OnError(7);
- return;
- }
-
- break;
- }
- }
-
- OnSuccess();
- reply_old(CMD_ACK, 1, len, 0, resp, len);
-}
-
-// 3 different ISO ways to write data to a DESFIRE (direct, capsuled, capsuled ISO)
-// cmd = cmd bytes to write
-// cmd_len = length of cmd
-// dataout = pointer to response data array
-int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) {
-
- size_t len = 0;
- size_t wrappedLen = 0;
- uint8_t wCmd[PM3_CMD_DATA_SIZE] = {0x00};
- uint8_t resp[MAX_FRAME_SIZE];
- uint8_t par[MAX_PARITY_SIZE];
-
- wrappedLen = CreateAPDU(cmd, cmd_len, wCmd);
-
- if (DBGLEVEL >= 4)
- print_result("WCMD <--: ", wCmd, wrappedLen);
-
- ReaderTransmit(wCmd, wrappedLen, NULL);
-
- len = ReaderReceive(resp, par);
- if (!len) {
- if (DBGLEVEL >= 4) Dbprintf("fukked");
- return false; //DATA LINK ERROR
- }
- // if we received an I- or R(ACK)-Block with a block number equal to the
- // current block number, toggle the current block number
- else if (len >= 4 // PCB+CID+CRC = 4 bytes
- && ((resp[0] & 0xC0) == 0 // I-Block
- || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
- && (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
- pcb_blocknum ^= 1; //toggle next block
- }
-
- memcpy(dataout, resp, len);
- return len;
-}
-
-// CreateAPDU
-size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
-
- size_t cmdlen = MIN(len + 4, PM3_CMD_DATA_SIZE - 1);
-
- uint8_t cmd[cmdlen];
- memset(cmd, 0, cmdlen);
-
- cmd[0] = 0x0A; // 0x0A = write cid, 0x02 = no cid.
- cmd[0] |= pcb_blocknum; // OR the block number into the PCB
- cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
-
- memcpy(cmd + 2, datain, len);
- AddCrc14A(cmd, len + 2);
-
- memcpy(dataout, cmd, cmdlen);
-
- return cmdlen;
-}
-
-// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
-// crc_update(&desfire_crc32, addr, addr_sz);
-// crc_update(&desfire_crc32, byte, 8);
-// uint32_t crc = crc_finish(&desfire_crc32);
-
-void OnSuccess() {
- pcb_blocknum = 0;
- ReaderTransmit(deselect_cmd, 3, NULL);
- if (mifare_ultra_halt()) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
- }
- switch_off();
-}
-
-void OnError(uint8_t reason) {
- reply_old(CMD_ACK, 0, reason, 0, 0, 0);
- OnSuccess();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifaredesfire.h b/pm3rdv4rrg/src/main/cpp/armsrc/mifaredesfire.h
deleted file mode 100644
index 8daed69a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifaredesfire.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008, May 2011
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Definitions internal to the app source.
-//-----------------------------------------------------------------------------
-#ifndef __MIFAREDESFIRE_H
-#define __MIFAREDESFIRE_H
-
-#include "common.h"
-
-bool InitDesfireCard();
-void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-void MifareDesfireGetInformation();
-void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
-void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
-int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
-size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout);
-void OnSuccess();
-void OnError(uint8_t reason);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresim.c b/pm3rdv4rrg/src/main/cpp/armsrc/mifaresim.c
deleted file mode 100644
index 13e9cd12..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresim.c
+++ /dev/null
@@ -1,1305 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011, 2012
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Mifare Classic Card Simulation
-//-----------------------------------------------------------------------------
-
-// Verbose Mode:
-// DBG_NONE 0
-// DBG_ERROR 1
-// DBG_INFO 2
-// DBG_DEBUG 3
-// DBG_EXTENDED 4
-
-// /!\ Printing Debug message is disrupting emulation,
-// Only use with caution during debugging
-
-#include "mifaresim.h"
-
-#include
-
-#include "iso14443a.h"
-#include "BigBuf.h"
-#include "string.h"
-#include "mifareutil.h"
-#include "fpgaloader.h"
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "protocols.h"
-#include "appmain.h"
-#include "util.h"
-#include "commonutil.h"
-#include "crc16.h"
-#include "dbprint.h"
-#include "ticks.h"
-
-static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
- uint8_t sector_trailer[16];
- emlGetMem(sector_trailer, blockNo, 1);
- uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
- | ((sector_trailer[8] >> 2) & 0x02)
- | ((sector_trailer[8] >> 7) & 0x01);
- switch (action) {
- case AC_KEYA_READ: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
- return false;
- }
- case AC_KEYA_WRITE: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
- return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
- || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
- }
- case AC_KEYB_READ: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
- return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01));
- }
- case AC_KEYB_WRITE: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
- return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
- || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
- }
- case AC_AC_READ: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
- return ((keytype == AUTHKEYA)
- || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
- }
- case AC_AC_WRITE: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
- return ((keytype == AUTHKEYA && (AC == 0x01))
- || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
- }
- default:
- return false;
- }
-}
-
-
-static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
-
- uint8_t sector_trailer[16];
- emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
-
- uint8_t sector_block;
- if (blockNo <= MIFARE_2K_MAXBLOCK) {
- sector_block = blockNo & 0x03;
- } else {
- sector_block = (blockNo & 0x0f) / 5;
- }
-
- uint8_t AC;
- switch (sector_block) {
- case 0x00: {
- AC = ((sector_trailer[7] >> 2) & 0x04)
- | ((sector_trailer[8] << 1) & 0x02)
- | ((sector_trailer[8] >> 4) & 0x01);
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
- break;
- }
- case 0x01: {
- AC = ((sector_trailer[7] >> 3) & 0x04)
- | ((sector_trailer[8] >> 0) & 0x02)
- | ((sector_trailer[8] >> 5) & 0x01);
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
- break;
- }
- case 0x02: {
- AC = ((sector_trailer[7] >> 4) & 0x04)
- | ((sector_trailer[8] >> 1) & 0x02)
- | ((sector_trailer[8] >> 6) & 0x01);
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
- break;
- }
- default:
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed: Error");
- return false;
- }
-
- switch (action) {
- case AC_DATA_READ: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
- return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07))
- || (keytype == AUTHKEYB && !(AC == 0x07)));
- }
- case AC_DATA_WRITE: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
- return ((keytype == AUTHKEYA && (AC == 0x00))
- || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03)));
- }
- case AC_DATA_INC: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
- return ((keytype == AUTHKEYA && (AC == 0x00))
- || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06)));
- }
- case AC_DATA_DEC_TRANS_REST: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
- return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01))
- || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01)));
- }
- }
-
- return false;
-}
-
-static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
- if (IsSectorTrailer(blockNo)) {
- return IsTrailerAccessAllowed(blockNo, keytype, action);
- } else {
- return IsDataAccessAllowed(blockNo, keytype, action);
- }
-}
-
-static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
-
- // SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
- // ATQA
- static uint8_t rATQA_Mini[] = {0x04, 0x00}; // indicate Mifare classic Mini 4Byte UID
- static uint8_t rATQA_1k[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID
- static uint8_t rATQA_2k[] = {0x04, 0x00}; // indicate Mifare classic 2k 4Byte UID
- static uint8_t rATQA_4k[] = {0x02, 0x00}; // indicate Mifare classic 4k 4Byte UID
-
- // SAK
- static uint8_t rSAK_Mini = 0x09; // mifare Mini
- static uint8_t rSAK_1k = 0x08; // mifare 1k
- static uint8_t rSAK_2k = 0x08; // mifare 2k with RATS support
- static uint8_t rSAK_4k = 0x18; // mifare 4k
-
- static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level
- static uint8_t rUIDBCC1b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level, last 4 bytes
- static uint8_t rUIDBCC1b3[] = {0x00, 0x00, 0x00}; // UID 1st cascade level, last 3 bytes
- static uint8_t rUIDBCC1b2[] = {0x00, 0x00}; // UID 1st cascade level, last 2 bytes
- static uint8_t rUIDBCC1b1[] = {0x00}; // UID 1st cascade level, last byte
- static uint8_t rUIDBCC2[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 2nd cascade level
- static uint8_t rUIDBCC2b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 2st cascade level, last 4 bytes
- static uint8_t rUIDBCC2b3[] = {0x00, 0x00, 0x00}; // UID 2st cascade level, last 3 bytes
- static uint8_t rUIDBCC2b2[] = {0x00, 0x00}; // UID 2st cascade level, last 2 bytes
- static uint8_t rUIDBCC2b1[] = {0x00}; // UID 2st cascade level, last byte
- static uint8_t rUIDBCC3[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 3nd cascade level
- static uint8_t rUIDBCC3b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 3st cascade level, last 4 bytes
- static uint8_t rUIDBCC3b3[] = {0x00, 0x00, 0x00}; // UID 3st cascade level, last 3 bytes
- static uint8_t rUIDBCC3b2[] = {0x00, 0x00}; // UID 3st cascade level, last 2 bytes
- static uint8_t rUIDBCC3b1[] = {0x00}; // UID 3st cascade level, last byte
-
- static uint8_t rATQA[] = {0x00, 0x00}; // Current ATQA
- static uint8_t rSAK[] = {0x00, 0x00, 0x00}; // Current SAK, CRC
- static uint8_t rSAKuid[] = {0x04, 0xda, 0x17}; // UID incomplete cascade bit, CRC
-
- // RATS answer for 2K NXP mifare classic (with CRC)
- static uint8_t rRATS[] = {0x0c, 0x75, 0x77, 0x80, 0x02, 0xc1, 0x05, 0x2f, 0x2f, 0x01, 0xbc, 0xd6, 0x60, 0xd3};
-
- *uid_len = 0;
-
- // By default use 1K tag
- memcpy(rATQA, rATQA_1k, sizeof(rATQA));
- rSAK[0] = rSAK_1k;
-
- //by default RATS not supported
- *rats_len = 0;
- *rats = NULL;
-
- // -- Determine the UID
- // Can be set from emulator memory or incoming data
- // Length: 4,7,or 10 bytes
-
- // Get UID, SAK, ATQA from EMUL
- if ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) {
- uint8_t block0[16];
- emlGetMemBt(block0, 0, 16);
-
- // If uid size defined, copy only uid from EMUL to use, backward compatibility for 'hf_colin.c', 'hf_mattyrun.c'
- if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) != 0) {
- memcpy(datain, block0, 10); // load 10bytes from EMUL to the datain pointer. to be used below.
- } else {
- // Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
- if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) {
- flags |= FLAG_4B_UID_IN_DATA;
- memcpy(datain, block0, 4);
- rSAK[0] = block0[5];
- memcpy(rATQA, &block0[6], sizeof(rATQA));
- }
- // Check for 7 bytes UID: double size uid bits in ATQA
- else if ((block0[8] & 0xc0) == 0x40) {
- flags |= FLAG_7B_UID_IN_DATA;
- memcpy(datain, block0, 7);
- rSAK[0] = block0[7];
- memcpy(rATQA, &block0[8], sizeof(rATQA));
- } else {
- Dbprintf("[-] ERROR: Invalid dump. UID/SAK/ATQA not found");
- return false;
- }
- }
-
- }
-
- // Tune tag type, if defined directly
- // Otherwise use defined by default or extracted from EMUL
- if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) {
- memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
- rSAK[0] = rSAK_Mini;
- if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
- } else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) {
- memcpy(rATQA, rATQA_1k, sizeof(rATQA));
- rSAK[0] = rSAK_1k;
- if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
- } else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) {
- memcpy(rATQA, rATQA_2k, sizeof(rATQA));
- rSAK[0] = rSAK_2k;
- *rats = rRATS;
- *rats_len = sizeof(rRATS);
- if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support");
- } else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) {
- memcpy(rATQA, rATQA_4k, sizeof(rATQA));
- rSAK[0] = rSAK_4k;
- if (DBGLEVEL > DBG_NONE) Dbprintf("Enforcing Mifare 4K ATQA/SAK");
- }
-
- // Prepare UID arrays
- if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain
- memcpy(rUIDBCC1, datain, 4);
- *uid_len = 4;
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MifareSimInit - FLAG_4B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_4B_UID_IN_DATA, flags, rUIDBCC1);
-
-
- // save CUID
- *cuid = bytes_to_num(rUIDBCC1, 4);
- // BCC
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
- if (DBGLEVEL > DBG_NONE) {
- Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
- }
-
- // Correct uid size bits in ATQA
- rATQA[0] = (rATQA[0] & 0x3f) | 0x00; // single size uid
-
- } else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
- memcpy(&rUIDBCC1[1], datain, 3);
- memcpy(rUIDBCC2, datain + 3, 4);
- *uid_len = 7;
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1);
-
- // save CUID
- *cuid = bytes_to_num(rUIDBCC2, 4);
- // CascadeTag, CT
- rUIDBCC1[0] = MIFARE_SELECT_CT;
- // BCC
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
- rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
- if (DBGLEVEL > DBG_NONE) {
- Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
- rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
- }
-
- // Correct uid size bits in ATQA
- rATQA[0] = (rATQA[0] & 0x3f) | 0x40; // double size uid
-
- } else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
- memcpy(&rUIDBCC1[1], datain, 3);
- memcpy(&rUIDBCC2[1], datain + 3, 3);
- memcpy(rUIDBCC3, datain + 6, 4);
- *uid_len = 10;
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1);
-
- // save CUID
- *cuid = bytes_to_num(rUIDBCC3, 4);
- // CascadeTag, CT
- rUIDBCC1[0] = MIFARE_SELECT_CT;
- rUIDBCC2[0] = MIFARE_SELECT_CT;
- // BCC
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
- rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
- rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
-
- if (DBGLEVEL > DBG_NONE) {
- Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
- rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
- rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3],
- rUIDBCC3[0], rUIDBCC3[1], rUIDBCC3[2], rUIDBCC3[3]
- );
- }
-
- // Correct uid size bits in ATQA
- rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid
- } else {
- Dbprintf("[-] ERROR: UID size not defined");
- return false;
- }
- if (flags & FLAG_FORCED_ATQA) {
- rATQA[0] = atqa >> 8;
- rATQA[1] = atqa & 0xff;
- }
- if (flags & FLAG_FORCED_SAK) {
- rSAK[0] = sak;
- }
- if (DBGLEVEL > DBG_NONE) {
- Dbprintf("ATQA : %02X %02X", rATQA[1], rATQA[0]);
- Dbprintf("SAK : %02X", rSAK[0]);
- }
-
- // clone UIDs for byte-frame anti-collision multiple tag selection procedure
- memcpy(rUIDBCC1b4, &rUIDBCC1[1], 4);
- memcpy(rUIDBCC1b3, &rUIDBCC1[2], 3);
- memcpy(rUIDBCC1b2, &rUIDBCC1[3], 2);
- memcpy(rUIDBCC1b1, &rUIDBCC1[4], 1);
- if (*uid_len >= 7) {
- memcpy(rUIDBCC2b4, &rUIDBCC2[1], 4);
- memcpy(rUIDBCC2b3, &rUIDBCC2[2], 3);
- memcpy(rUIDBCC2b2, &rUIDBCC2[3], 2);
- memcpy(rUIDBCC2b1, &rUIDBCC2[4], 1);
- }
- if (*uid_len == 10) {
- memcpy(rUIDBCC3b4, &rUIDBCC3[1], 4);
- memcpy(rUIDBCC3b3, &rUIDBCC3[2], 3);
- memcpy(rUIDBCC3b2, &rUIDBCC3[3], 2);
- memcpy(rUIDBCC3b1, &rUIDBCC3[4], 1);
- }
-
- // Calculate actual CRC
- AddCrc14A(rSAK, sizeof(rSAK) - 2);
-
-#define TAG_RESPONSE_COUNT 18
- static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
- { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
- { .response = rSAK, .response_n = sizeof(rSAK) }, //
- { .response = rSAKuid, .response_n = sizeof(rSAKuid) }, //
- // Do not reorder. Block used via relative index of rUIDBCC1
- { .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid
- { .response = rUIDBCC1b4, .response_n = sizeof(rUIDBCC1b4)},
- { .response = rUIDBCC1b3, .response_n = sizeof(rUIDBCC1b3)},
- { .response = rUIDBCC1b2, .response_n = sizeof(rUIDBCC1b2)},
- { .response = rUIDBCC1b1, .response_n = sizeof(rUIDBCC1b1)},
- // Do not reorder. Block used via relative index of rUIDBCC2
- { .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid
- { .response = rUIDBCC2b4, .response_n = sizeof(rUIDBCC2b4)},
- { .response = rUIDBCC2b3, .response_n = sizeof(rUIDBCC2b3)},
- { .response = rUIDBCC2b2, .response_n = sizeof(rUIDBCC2b2)},
- { .response = rUIDBCC2b1, .response_n = sizeof(rUIDBCC2b1)},
- // Do not reorder. Block used via relative index of rUIDBCC3
- { .response = rUIDBCC3, .response_n = sizeof(rUIDBCC3) }, // Anticollision cascade3 - respond with 3th part of uid
- { .response = rUIDBCC3b4, .response_n = sizeof(rUIDBCC3b4)},
- { .response = rUIDBCC3b3, .response_n = sizeof(rUIDBCC3b3)},
- { .response = rUIDBCC3b2, .response_n = sizeof(rUIDBCC3b2)},
- { .response = rUIDBCC3b1, .response_n = sizeof(rUIDBCC3b1)}
- };
-
- // Prepare ("precompile") the responses of the anticollision phase.
- // There will be not enough time to do this at the moment the reader sends its REQA or SELECT
- // There are 18 predefined responses with a total of 53 bytes data to transmit.
- // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
- // 53 * 8 data bits, 53 * 1 parity bits, 18 start bits, 18 stop bits, 18 correction bits -> need 571 bytes buffer
-#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 571
-
- uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
- // modulation buffer pointer and current buffer free space size
- uint8_t *free_buffer_pointer = free_buffer;
- size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
-
- for (size_t i = 0; i < TAG_RESPONSE_COUNT; i++) {
- if (prepare_allocated_tag_modulation(&responses_init[i], &free_buffer_pointer, &free_buffer_size) == false) {
- Dbprintf("Not enough modulation buffer size, exit after %d elements", i);
- return false;
- }
- }
-
- *responses = responses_init;
-
- // indices into responses array:
-#define ATQA 0
-#define SAK 1
-#define SAKuid 2
-#define UIDBCC1 3
-#define UIDBCC2 8
-#define UIDBCC3 13
-
- return true;
-}
-
-/**
-*MIFARE 1K simulate.
-*
-*@param flags :
-* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
-* FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
-* FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
-* FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished
-* FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later
-*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ...
-* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
-*/
-void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) {
- tag_response_info_t *responses;
- uint8_t cardSTATE = MFEMUL_NOFIELD;
- uint8_t uid_len = 0; // 4,7, 10
- uint32_t cuid = 0;
-
- int vHf = 0; // in mV
-
- uint32_t selTimer = 0;
- uint32_t authTimer = 0;
-
- uint8_t blockNo;
-
- uint32_t nr;
- uint32_t ar;
-
- bool encrypted_data;
-
- uint8_t cardWRBL = 0;
- uint8_t cardAUTHSC = 0;
- uint8_t cardAUTHKEY = AUTHKEYNONE; // no authentication
- uint32_t cardRr = 0;
- uint32_t ans = 0;
-
- uint32_t cardINTREG = 0;
- uint8_t cardINTBLOCK = 0;
- struct Crypto1State mpcs = {0, 0};
- struct Crypto1State *pcs;
- pcs = &mpcs;
-
- uint32_t numReads = 0; //Counts numer of times reader reads a block
- uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedCmd_dec[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
- uint16_t receivedCmd_len;
-
- uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- uint8_t *rats = NULL;
- uint8_t rats_len = 0;
-
- //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
- // This will be used in the reader-only attack.
-
- //allow collecting up to 7 sets of nonces to allow recovery of up to 7 keys
-#define ATTACK_KEY_COUNT 7 // keep same as define in cmdhfmf.c -> readerAttack() (Cannot be more than 7)
- nonces_t ar_nr_resp[ATTACK_KEY_COUNT * 2]; // *2 for 2 separate attack types (nml, moebius) 36 * 7 * 2 bytes = 504 bytes
- memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
-
- uint8_t ar_nr_collected[ATTACK_KEY_COUNT * 2]; // *2 for 2nd attack type (moebius)
- memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected));
- uint8_t nonce1_count = 0;
- uint8_t nonce2_count = 0;
- uint8_t moebius_n_count = 0;
- bool gettingMoebius = false;
- uint8_t mM = 0; //moebius_modifier for collection storage
-
- // Authenticate response - nonce
- uint8_t rAUTH_NT[4];
- uint8_t rAUTH_NT_keystream[4];
- uint32_t nonce = 0;
-
- tUart14a *uart = GetUart14a();
-
- // free eventually allocated BigBuf memory but keep Emulator Memory
- BigBuf_free_keep_EM();
-
- if (MifareSimInit(flags, datain, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) {
- BigBuf_free_keep_EM();
- return;
- }
-
- // We need to listen to the high-frequency, peak-detected path.
- iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
-
- // clear trace
- clear_trace();
- set_tracing(true);
- LED_D_ON();
- ResetSspClk();
-
- bool finished = false;
- bool button_pushed = BUTTON_PRESS();
-
- while (!button_pushed && !finished && !data_available()) {
- WDT_HIT();
-
- // find reader field
- if (cardSTATE == MFEMUL_NOFIELD) {
- vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF)) >> 10;
- if (vHf > MF_MINFIELDV) {
- cardSTATE_TO_IDLE();
- LED_A_ON();
- }
- button_pushed = BUTTON_PRESS();
- continue;
- }
-
- FpgaEnableTracing();
- //Now, get data
- int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par);
-
- if (res == 2) { //Field is off!
- FpgaDisableTracing();
- LEDsoff();
- cardSTATE = MFEMUL_NOFIELD;
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("cardSTATE = MFEMUL_NOFIELD");
- continue;
- } else if (res == 1) { // button pressed
- FpgaDisableTracing();
- button_pushed = true;
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Button pressed");
- break;
- }
-
- // WUPA in HALTED state or REQA or WUPA in any other state
- if (receivedCmd_len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) {
- selTimer = GetTickCount();
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("EmSendPrecompiledCmd(&responses[ATQA]);");
- EmSendPrecompiledCmd(&responses[ATQA]);
-
- FpgaDisableTracing();
-
- // init crypto block
- crypto1_deinit(pcs);
- cardAUTHKEY = AUTHKEYNONE;
- nonce = prng_successor(selTimer, 32);
- // prepare NT for nested authentication
- num_to_bytes(nonce, 4, rAUTH_NT);
- num_to_bytes(cuid ^ nonce, 4, rAUTH_NT_keystream);
-
- LED_B_OFF();
- LED_C_OFF();
- cardSTATE = MFEMUL_SELECT;
- continue;
- }
-
- switch (cardSTATE) {
- case MFEMUL_NOFIELD:
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MFEMUL_NOFIELD");
- break;
- case MFEMUL_HALTED:
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MFEMUL_HALTED");
- break;
- case MFEMUL_IDLE: {
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MFEMUL_IDLE");
- break;
- }
-
- // The anti-collision sequence, which is a mandatory part of the card activation sequence.
- // It auto with 4-byte UID (= Single Size UID),
- // 7 -byte UID (= Double Size UID) or 10-byte UID (= Triple Size UID).
- // For details see chapter 2 of AN10927.pdf
- //
- // This case is used for all Cascade Levels, because:
- // 1) Any devices (under Android for example) after full select procedure completed,
- // when UID is known, uses "fast-selection" method. In this case reader ignores
- // first cascades and tries to select tag by last bytes of UID of last cascade
- // 2) Any readers (like ACR122U) uses bit oriented anti-collision frames during selectin,
- // same as multiple tags. For details see chapter 6.1.5.3 of ISO/IEC 14443-3
- case MFEMUL_SELECT: {
- int uid_index = -1;
- // Extract cascade level
- if (receivedCmd_len >= 2) {
- switch (receivedCmd[0]) {
- case ISO14443A_CMD_ANTICOLL_OR_SELECT:
- uid_index = UIDBCC1;
- break;
- case ISO14443A_CMD_ANTICOLL_OR_SELECT_2:
- uid_index = UIDBCC2;
- break;
- case ISO14443A_CMD_ANTICOLL_OR_SELECT_3:
- uid_index = UIDBCC3;
- break;
- }
- }
- if (uid_index < 0) {
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardSTATE_TO_IDLE();
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT] Incorrect cascade level received");
- break;
- }
-
- // Incoming SELECT ALL for any cascade level
- if (receivedCmd_len == 2 && receivedCmd[1] == 0x20) {
- EmSendPrecompiledCmd(&responses[uid_index]);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SELECT ALL - EmSendPrecompiledCmd(%02x)", &responses[uid_index]);
- break;
- }
-
- // Incoming SELECT CLx for any cascade level
- if (receivedCmd_len == 9 && receivedCmd[1] == 0x70) {
- if (memcmp(&receivedCmd[2], responses[uid_index].response, 4) == 0) {
- bool cl_finished = (uid_len == 4 && uid_index == UIDBCC1) ||
- (uid_len == 7 && uid_index == UIDBCC2) ||
- (uid_len == 10 && uid_index == UIDBCC3);
- EmSendPrecompiledCmd(&responses[cl_finished ? SAK : SAKuid]);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SELECT CLx %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]);
- if (cl_finished) {
- LED_B_ON();
- cardSTATE = MFEMUL_WORK;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT] cardSTATE = MFEMUL_WORK");
- }
- } else {
- // IDLE, not our UID
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardSTATE_TO_IDLE();
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT] cardSTATE = MFEMUL_IDLE");
- }
- break;
- }
-
- // Incoming anti-collision frame
- // receivedCmd[1] indicates number of byte and bit collision, supports only for bit collision is zero
- if (receivedCmd_len >= 3 && receivedCmd_len <= 6 && (receivedCmd[1] & 0x0f) == 0) {
- // we can process only full-byte frame anti-collision procedure
- if (memcmp(&receivedCmd[2], responses[uid_index].response, receivedCmd_len - 2) == 0) {
- // response missing part of UID via relative array index
- EmSendPrecompiledCmd(&responses[uid_index + receivedCmd_len - 2]);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SELECT ANTICOLLISION - EmSendPrecompiledCmd(%02x)", &responses[uid_index]);
- } else {
- // IDLE, not our UID or split-byte frame anti-collision (not supports)
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardSTATE_TO_IDLE();
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT] cardSTATE = MFEMUL_IDLE");
- }
- break;
- }
-
- // Unknown selection procedure
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardSTATE_TO_IDLE();
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT] Unknown selection procedure");
- break;
- }
-
- // WORK
- case MFEMUL_WORK: {
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_WORK] Enter in case");
-
- if (receivedCmd_len == 0) {
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received");
- break;
- }
-
- encrypted_data = (cardAUTHKEY != AUTHKEYNONE);
- if (encrypted_data) {
- // decrypt seqence
- mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Decrypt seqence");
- } else {
- // Data in clear
- memcpy(receivedCmd_dec, receivedCmd, receivedCmd_len);
- }
-
- if (!CheckCrc14A(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC
- EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len);
- break;
- }
-
- if (receivedCmd_len == 4 && (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB)) {
-
- // Reader asks for AUTH: 6X XX
- // RCV: 60 XX => Using KEY A
- // RCV: 61 XX => Using KEY B
- // XX: Block number
-
- // iceman, u8 can never be larger than 256
- // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack
- if (((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]);
- break;
- }
-
- authTimer = GetTickCount();
-
- // received block num -> sector
- // Example: 6X [00]
- // 4K tags have 16 blocks per sector 32..39
- cardAUTHSC = MifareBlockToSector(receivedCmd_dec[1]);
-
- // cardAUTHKEY: 60 => Auth use Key A
- // cardAUTHKEY: 61 => Auth use Key B
- cardAUTHKEY = receivedCmd_dec[0] & 0x01;
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY %c: %012" PRIx64, (cardAUTHKEY == 0) ? 'A' : 'B', emlGetKey(cardAUTHSC, cardAUTHKEY));
-
- // first authentication
- crypto1_deinit(pcs);
-
- // Load key into crypto
- crypto1_init(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
-
- if (!encrypted_data) {
- // Receive Cmd in clear txt
- // Update crypto state (UID ^ NONCE)
- crypto1_word(pcs, cuid ^ nonce, 0);
- // rAUTH_NT contains prepared nonce for authenticate
- EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT));
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader authenticating for block %d (0x%02x) with key %c - nonce: %02X - ciud: %02X", receivedCmd_dec[1], receivedCmd_dec[1], (cardAUTHKEY == 0) ? 'A' : 'B', rAUTH_NT, cuid);
- } else {
- // nested authentication
- /*
- ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
- num_to_bytes(ans, 4, rAUTH_AT);
- */
- // rAUTH_NT, rAUTH_NT_keystream contains prepared nonce and keystream for nested authentication
- // we need calculate parity bits for non-encrypted sequence
- mf_crypto1_encryptEx(pcs, rAUTH_NT, rAUTH_NT_keystream, response, 4, response_par);
- EmSendCmdPar(response, 4, response_par);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd_dec[1], receivedCmd_dec[1], (cardAUTHKEY == 0) ? 'A' : 'B');
- }
-
- cardSTATE = MFEMUL_AUTH1;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_AUTH1 - rAUTH_NT: %02X", rAUTH_NT);
- break;
- }
-
- // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
- // BUT... ACK --> NACK
- if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_ACK) {
- EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
- FpgaDisableTracing();
- break;
- }
-
- // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK)
- if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_NACK_NA) {
- EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_ACK) : CARD_ACK);
- FpgaDisableTracing();
- break;
- }
-
- // case MFEMUL_WORK => if Cmd is Read, Write, Inc, Dec, Restore, Transfert
- if (receivedCmd_len == 4 && (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK
- || receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK
- || receivedCmd_dec[0] == MIFARE_CMD_INC
- || receivedCmd_dec[0] == MIFARE_CMD_DEC
- || receivedCmd_dec[0] == MIFARE_CMD_RESTORE
- || receivedCmd_dec[0] == MIFARE_CMD_TRANSFER)) {
- // all other commands must be encrypted (authenticated)
- if (!encrypted_data) {
- EmSend4bit(CARD_NACK_NA);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Commands must be encrypted (authenticated)");
- break;
- }
-
- // iceman, u8 can never be larger the MIFARE_4K_MAXBLOCK (256)
- // Check if Block num is not too far
- /*
- if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]);
- break;
- }
- */
-
- if (MifareBlockToSector(receivedCmd_dec[1]) != cardAUTHSC) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC);
- break;
- }
- }
-
- // case MFEMUL_WORK => CMD READ block
- if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) {
- blockNo = receivedCmd_dec[1];
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader reading block %d (0x%02x)", blockNo, blockNo);
- emlGetMem(response, blockNo, 1);
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[MFEMUL_WORK - ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo,
- response[0], response[1], response[2], response[3], response[4], response[5], response[6],
- response[7], response[8], response[9], response[10], response[11], response[12], response[13],
- response[14], response[15]);
- }
-
- // Access permission managment:
- //
- // Sector Trailer:
- // - KEY A access
- // - KEY B access
- // - AC bits access
- //
- // Data block:
- // - Data access
-
- // If permission is not allowed, data is cleared (00) in emulator memeory.
- // ex: a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5
-
-
- // Check if selected Block is a Sector Trailer
- if (IsSectorTrailer(blockNo)) {
-
- if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) {
- memset(response, 0x00, 6); // keyA can never be read
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo);
- }
- if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) {
- memset(response + 10, 0x00, 6); // keyB cannot be read
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo);
- }
- if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) {
- memset(response + 6, 0x00, 4); // AC bits cannot be read
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo);
- }
- } else {
- if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) {
- memset(response, 0x00, 16); // datablock cannot be read
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo);
- }
- }
- AddCrc14A(response, 16);
- mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par);
- EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[MFEMUL_WORK - EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo,
- response[0], response[1], response[2], response[3], response[4], response[5], response[6],
- response[7], response[8], response[9], response[10], response[11], response[12], response[13],
- response[14], response[15]);
- }
- numReads++;
-
- if (exitAfterNReads > 0 && numReads == exitAfterNReads) {
- Dbprintf("[MFEMUL_WORK] %d reads done, exiting", numReads);
- finished = true;
- }
- break;
-
- } // End receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK
-
- // case MFEMUL_WORK => CMD WRITEBLOCK
- if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) {
- blockNo = receivedCmd_dec[1];
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0xA0 write block %d (%02x)", blockNo, blockNo);
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
- FpgaDisableTracing();
-
- cardWRBL = blockNo;
- cardSTATE = MFEMUL_WRITEBL2;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_WRITEBL2");
- break;
- }
-
- // case MFEMUL_WORK => CMD INC/DEC/REST
- if (receivedCmd_len == 4 && (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE)) {
- blockNo = receivedCmd_dec[1];
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo);
- if (emlCheckValBl(blockNo)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate on block, but emlCheckValBl failed, nacking");
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
- break;
- }
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
- FpgaDisableTracing();
- cardWRBL = blockNo;
-
- // INC
- if (receivedCmd_dec[0] == MIFARE_CMD_INC) {
- cardSTATE = MFEMUL_INTREG_INC;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_INC");
- }
-
- // DEC
- if (receivedCmd_dec[0] == MIFARE_CMD_DEC) {
- cardSTATE = MFEMUL_INTREG_DEC;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_DEC");
- }
-
- // REST
- if (receivedCmd_dec[0] == MIFARE_CMD_RESTORE) {
- cardSTATE = MFEMUL_INTREG_REST;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_REST");
- }
- break;
-
- } // End case MFEMUL_WORK => CMD INC/DEC/REST
-
-
- // case MFEMUL_WORK => CMD TRANSFER
- if (receivedCmd_len == 4 && receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) {
- blockNo = receivedCmd_dec[1];
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0x%02x transfer block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo);
- if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1]))
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- else
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
-
- FpgaDisableTracing();
- break;
- }
-
- // case MFEMUL_WORK => CMD HALT
- if (receivedCmd_len > 1 && receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd_dec[1] == 0x00) {
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- LED_B_OFF();
- LED_C_OFF();
- cardSTATE = MFEMUL_HALTED;
- cardAUTHKEY = AUTHKEYNONE;
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_HALTED");
- break;
- }
-
- // case MFEMUL_WORK => CMD RATS
- if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_RATS && receivedCmd_dec[1] == 0x80) {
- if (rats && rats_len) {
- if (encrypted_data) {
- memcpy(response, rats, rats_len);
- mf_crypto1_encrypt(pcs, response, rats_len, response_par);
- EmSendCmdPar(response, rats_len, response_par);
- } else {
- EmSendCmd(rats, rats_len);
- }
- FpgaDisableTracing();
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
- } else {
- EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
- FpgaDisableTracing();
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
- }
- break;
- }
-
- // case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT
- if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) {
- if (rats && rats_len) {
- // response back NXP_DESELECT
- if (encrypted_data) {
- memcpy(response, receivedCmd_dec, receivedCmd_len);
- mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par);
- EmSendCmdPar(response, receivedCmd_len, response_par);
- } else
- EmSendCmd(receivedCmd_dec, receivedCmd_len);
-
- FpgaDisableTracing();
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
- } else {
- EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
- }
- break;
- }
-
- // case MFEMUL_WORK => command not allowed
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Received command not allowed, nacking");
- EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
- FpgaDisableTracing();
- break;
- }
-
- // AUTH1
- case MFEMUL_AUTH1: {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("[MFEMUL_AUTH1] Enter case");
-
- if (receivedCmd_len != 8) {
- cardSTATE_TO_IDLE();
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
- break;
- }
-
- nr = bytes_to_num(receivedCmd, 4);
- ar = bytes_to_num(&receivedCmd[4], 4);
-
- // Collect AR/NR per keytype & sector
- if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
-
- for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
- if (ar_nr_collected[i + mM] == 0 || ((cardAUTHSC == ar_nr_resp[i + mM].sector) && (cardAUTHKEY == ar_nr_resp[i + mM].keytype) && (ar_nr_collected[i + mM] > 0))) {
- // if first auth for sector, or matches sector and keytype of previous auth
- if (ar_nr_collected[i + mM] < 2) {
- // if we haven't already collected 2 nonces for this sector
- if (ar_nr_resp[ar_nr_collected[i + mM]].ar != ar) {
- // Avoid duplicates... probably not necessary, ar should vary.
- if (ar_nr_collected[i + mM] == 0) {
- // first nonce collect
- ar_nr_resp[i + mM].cuid = cuid;
- ar_nr_resp[i + mM].sector = cardAUTHSC;
- ar_nr_resp[i + mM].keytype = cardAUTHKEY;
- ar_nr_resp[i + mM].nonce = nonce;
- ar_nr_resp[i + mM].nr = nr;
- ar_nr_resp[i + mM].ar = ar;
- nonce1_count++;
- // add this nonce to first moebius nonce
- ar_nr_resp[i + ATTACK_KEY_COUNT].cuid = cuid;
- ar_nr_resp[i + ATTACK_KEY_COUNT].sector = cardAUTHSC;
- ar_nr_resp[i + ATTACK_KEY_COUNT].keytype = cardAUTHKEY;
- ar_nr_resp[i + ATTACK_KEY_COUNT].nonce = nonce;
- ar_nr_resp[i + ATTACK_KEY_COUNT].nr = nr;
- ar_nr_resp[i + ATTACK_KEY_COUNT].ar = ar;
- ar_nr_collected[i + ATTACK_KEY_COUNT]++;
- } else { // second nonce collect (std and moebius)
- ar_nr_resp[i + mM].nonce2 = nonce;
- ar_nr_resp[i + mM].nr2 = nr;
- ar_nr_resp[i + mM].ar2 = ar;
-
- if (!gettingMoebius) {
- nonce2_count++;
- // check if this was the last second nonce we need for std attack
- if (nonce2_count == nonce1_count) {
- // done collecting std test switch to moebius
- // first finish incrementing last sample
- ar_nr_collected[i + mM]++;
- // switch to moebius collection
- gettingMoebius = true;
- mM = ATTACK_KEY_COUNT;
- nonce = nonce * 7;
- break;
- }
- } else {
- moebius_n_count++;
- // if we've collected all the nonces we need - finish.
- if (nonce1_count == moebius_n_count)
- finished = true;
- }
- }
- ar_nr_collected[i + mM]++;
- }
- }
- // we found right spot for this nonce stop looking
- break;
- }
- }
- }
-
- // --- crypto
- crypto1_word(pcs, nr, 1);
- cardRr = ar ^ crypto1_word(pcs, 0, 0);
-
- // test if auth KO
- if (cardRr != prng_successor(nonce, 64)) {
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[MFEMUL_AUTH1] AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]"
- , cardAUTHSC
- , (cardAUTHKEY == 0) ? 'A' : 'B'
- , nr
- , cardRr
- , nonce // nt
- , prng_successor(nonce, 64)
- );
- }
- cardAUTHKEY = AUTHKEYNONE; // not authenticated
- cardSTATE_TO_IDLE();
- // Really tags not respond NACK on invalid authentication
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- break;
- }
-
- ans = prng_successor(nonce, 96);
- num_to_bytes(ans, 4, response);
- mf_crypto1_encrypt(pcs, response, 4, response_par);
- EmSendCmdPar(response, 4, response_par);
- FpgaDisableTracing();
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("[MFEMUL_AUTH1] AUTH COMPLETED for sector %d with key %c. time=%d",
- cardAUTHSC,
- cardAUTHKEY == 0 ? 'A' : 'B',
- GetTickCountDelta(authTimer)
- );
- }
- LED_C_ON();
- cardSTATE = MFEMUL_WORK;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] cardSTATE = MFEMUL_WORK");
- break;
- }
-
- // WRITE BL2
- case MFEMUL_WRITEBL2: {
- if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
- mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
- if (CheckCrc14A(receivedCmd_dec, receivedCmd_len)) {
- if (IsSectorTrailer(cardWRBL)) {
- emlGetMem(response, cardWRBL, 1);
- if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE)) {
- memcpy(receivedCmd_dec, response, 6); // don't change KeyA
- }
- if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYB_WRITE)) {
- memcpy(receivedCmd_dec + 10, response + 10, 6); // don't change KeyA
- }
- if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_AC_WRITE)) {
- memcpy(receivedCmd_dec + 6, response + 6, 4); // don't change AC bits
- }
- } else {
- if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_DATA_WRITE)) {
- memcpy(receivedCmd_dec, response, 16); // don't change anything
- }
- }
- emlSetMem(receivedCmd_dec, cardWRBL, 1);
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
- FpgaDisableTracing();
-
- cardSTATE = MFEMUL_WORK;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_WORK");
- break;
- }
- }
- cardSTATE_TO_IDLE();
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_IDLE");
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- break;
- }
-
- // INC
- case MFEMUL_INTREG_INC: {
- if (receivedCmd_len == 6) {
- mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans);
- if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
-
- cardSTATE_TO_IDLE();
- break;
- }
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardINTREG = cardINTREG + ans;
-
- cardSTATE = MFEMUL_WORK;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_INC] cardSTATE = MFEMUL_WORK");
- break;
- }
- }
-
- // DEC
- case MFEMUL_INTREG_DEC: {
- if (receivedCmd_len == 6) { // Data is encrypted
- // Decrypted cmd
- mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans);
- if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
-
- cardSTATE_TO_IDLE();
- break;
- }
- }
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardINTREG = cardINTREG - ans;
- cardSTATE = MFEMUL_WORK;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_DEC] cardSTATE = MFEMUL_WORK");
- break;
- }
-
- // REST
- case MFEMUL_INTREG_REST: {
- mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans);
- if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- FpgaDisableTracing();
-
- cardSTATE_TO_IDLE();
- break;
- }
- LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
- cardSTATE = MFEMUL_WORK;
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_REST] cardSTATE = MFEMUL_WORK");
- break;
- }
-
- } // End Switch Loop
-
- button_pushed = BUTTON_PRESS();
-
- } // End While Loop
-
-
- // NR AR ATTACK
- if (((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) && (DBGLEVEL >= DBG_INFO)) {
- for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
- if (ar_nr_collected[i] == 2) {
- Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
- Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
- ar_nr_resp[i].cuid, //UID
- ar_nr_resp[i].nonce, //NT
- ar_nr_resp[i].nr, //NR1
- ar_nr_resp[i].ar, //AR1
- ar_nr_resp[i].nr2, //NR2
- ar_nr_resp[i].ar2 //AR2
- );
- }
- }
- }
-
- for (uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT * 2; i++) {
- if (ar_nr_collected[i] == 2) {
- Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
- Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
- ar_nr_resp[i].cuid, //UID
- ar_nr_resp[i].nonce, //NT
- ar_nr_resp[i].nr, //NR1
- ar_nr_resp[i].ar, //AR1
- ar_nr_resp[i].nonce2,//NT2
- ar_nr_resp[i].nr2, //NR2
- ar_nr_resp[i].ar2 //AR2
- );
- }
- }
-
- if (DBGLEVEL >= DBG_ERROR) {
- Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
- }
-
-
- if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to write ACK
- //Send the collected ar_nr in the response
- reply_mix(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
- set_tracing(false);
- BigBuf_free_keep_EM();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresim.h b/pm3rdv4rrg/src/main/cpp/armsrc/mifaresim.h
deleted file mode 100644
index d8c15aee..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresim.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011, 2012
-// Gerhard de Koning Gans - May 2008
-// Hagen Fritsch - June 2010
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Mifare Classic Card Simulation
-//-----------------------------------------------------------------------------
-
-#ifndef __MIFARESIM_H
-#define __MIFARESIM_H
-
-#include "common.h"
-
-#ifndef CheckCrc14A
-# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
-#endif
-
-#define AC_DATA_READ 0
-#define AC_DATA_WRITE 1
-#define AC_DATA_INC 2
-#define AC_DATA_DEC_TRANS_REST 3
-#define AC_KEYA_READ 0
-#define AC_KEYA_WRITE 1
-#define AC_KEYB_READ 2
-#define AC_KEYB_WRITE 3
-#define AC_AC_READ 4
-#define AC_AC_WRITE 5
-
-#define AUTHKEYA 0
-#define AUTHKEYB 1
-#define AUTHKEYNONE 0xff
-
-void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresniff_disabled.c b/pm3rdv4rrg/src/main/cpp/armsrc/mifaresniff_disabled.c
deleted file mode 100644
index 23e854d0..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresniff_disabled.c
+++ /dev/null
@@ -1,327 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - 2012
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support mifare classic sniffer.
-//-----------------------------------------------------------------------------
-
-#include "mifaresniff.h"
-
-#ifndef CheckCrc14A
-# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
-#endif
-
-//static int sniffState = SNF_INIT;
-static uint8_t sniffUIDType = 0;
-static uint8_t sniffUID[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static uint8_t sniffATQA[2] = {0, 0};
-static uint8_t sniffSAK = 0;
-static uint8_t sniffBuf[17];
-static uint32_t timerData = 0;
-
-//-----------------------------------------------------------------------------
-// MIFARE sniffer.
-//
-// if no activity for 2sec, it sends the collected data to the client.
-//-----------------------------------------------------------------------------
-// "hf mf sniff"
-void RAMFUNC SniffMifare(uint8_t param) {
- // param:
- // bit 0 - trigger from first card answer
- // bit 1 - trigger from first reader 7-bit request
-
- // C(red) A(yellow) B(green)
- LEDsoff();
- iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
-
- // Allocate memory from BigBuf for some buffers
- // free all previous allocations first
- BigBuf_free();
- BigBuf_Clear_ext(false);
- clear_trace();
- set_tracing(true);
-
- // The command (reader -> tag) that we're receiving.
- uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- // The response (tag -> reader) that we're receiving.
- uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- // allocate the DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
- uint8_t *data = dmaBuf;
- uint8_t previous_data = 0;
- int dataLen, maxDataLen = 0;
- bool ReaderIsActive = false;
- bool TagIsActive = false;
-
- // We won't start recording the frames that we acquire until we trigger;
- // a good trigger condition to get started is probably when we see a
- // response from the tag.
- // triggered == false -- to wait first for card
- //bool triggered = !(param & 0x03);
-
-
- // Set up the demodulator for tag -> reader responses.
- Demod14aInit(receivedResp, receivedRespPar);
-
- // Set up the demodulator for the reader -> tag commands
- Uart14aInit(receivedCmd, receivedCmdPar);
-
- // Setup and start DMA.
- // set transfer address and number of bytes. Start transfer.
- if (!FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE)) {
- if (DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
- return;
- }
-
- tUart14a *uart = GetUart14a();
- tDemod14a *demod = GetDemod14a();
-
- MfSniffInit();
-
- uint32_t sniffCounter = 0;
- // loop and listen
- while (!BUTTON_PRESS()) {
- WDT_HIT();
- LED_A_ON();
- /*
- if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time
- // check if a transaction is completed (timeout after 2000ms).
- // if yes, stop the DMA transfer and write what we have so far to the client
- if (BigBuf_get_traceLen()) {
- MfSniffSend();
- // Reset everything - we missed some sniffed data anyway while the DMA was stopped
- sniffCounter = 0;
- dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
- data = dmaBuf;
- maxDataLen = 0;
- ReaderIsActive = false;
- TagIsActive = false;
- FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer.
- }
- }
- */
-
- // number of bytes we have processed so far
- int register readBufDataP = data - dmaBuf;
- // number of bytes already transferred
- int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
- if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred
- dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed
- else
- dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed
-
- // test for length of buffer
- if (dataLen > maxDataLen) { // we are more behind than ever...
- maxDataLen = dataLen;
- if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
- Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
- break;
- }
- }
- if (dataLen < 1) continue;
-
- // primary buffer was stopped ( <-- we lost data!
- if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
- AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
- Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
- }
- // secondary buffer sets as primary, secondary buffer was stopped
- if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
- }
-
- LED_A_OFF();
-
- // Need two samples to feed Miller and Manchester-Decoder
- if (sniffCounter & 0x01) {
-
- // no need to try decoding tag data if the reader is sending
- if (!TagIsActive) {
- uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
- if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) {
- LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
- Demod14aReset();
- Uart14aReset();
- }
- ReaderIsActive = (uart->state != STATE_14A_UNSYNCD);
- }
-
- // no need to try decoding tag data if the reader is sending
- if (!ReaderIsActive) {
- uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F);
- if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) {
- LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
- Demod14aReset();
- Uart14aReset();
- }
- TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
- }
- }
- previous_data = *data;
- sniffCounter++;
- data++;
-
- if (data == dmaBuf + DMA_BUFFER_SIZE)
- data = dmaBuf;
-
- } // main cycle
-
- MfSniffEnd();
- switch_off();
-}
-
-void MfSniffInit(void) {
- memset(sniffUID, 0x00, sizeof(sniffUID));
- memset(sniffATQA, 0x00, sizeof(sniffATQA));
- memset(sniffBuf, 0x00, sizeof(sniffBuf));
- sniffSAK = 0;
- sniffUIDType = SNF_UID_4;
- timerData = 0;
-}
-
-void MfSniffEnd(void) {
- LED_B_ON();
- reply_old(CMD_ACK, 0, 0, 0, 0, 0);
- LED_B_OFF();
-}
-
-/*
-bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) {
-
- // reset on 7-Bit commands from reader
- if (reader && (len == 1) && (bitCnt == 7)) {
- sniffState = SNF_INIT;
- }
-
-
-
- switch (sniffState) {
- case SNF_INIT:{
- // REQA,WUPA or MAGICWUP from reader
- if ((len == 1) && (reader) && (bitCnt == 7) ) {
- MfSniffInit();
- sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA;
- }
- break;
- }
- case SNF_MAGIC_WUPC2: {
- if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) {
- sniffState = SNF_CARD_IDLE;
- }
- break;
- }
- case SNF_ATQA:{
- // ATQA from tag
- if ((!reader) && (len == 2)) {
- sniffATQA[0] = data[0];
- sniffATQA[1] = data[1];
- sniffState = SNF_UID;
- }
- break;
- }
- case SNF_UID: {
-
- if ( !reader ) break;
- if ( len != 9 ) break;
- if ( !CheckCrc14A(data, 9)) break;
- if ( data[1] != 0x70 ) break;
-
- Dbprintf("[!] UID | %x", data[0]);
-
- if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) {
- // UID_4 - select 4 Byte UID from reader
- memcpy(sniffUID, data+2, 4);
- sniffUIDType = SNF_UID_4;
- sniffState = SNF_SAK;
- } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) {
- // UID_7 - Select 2nd part of 7 Byte UID
-
- // get rid of 0x88
- sniffUID[0] = sniffUID[1];
- sniffUID[1] = sniffUID[2];
- sniffUID[2] = sniffUID[3];
- //new uid bytes
- memcpy(sniffUID+3, data+2, 4);
- sniffUIDType = SNF_UID_7;
- sniffState = SNF_SAK;
- } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) {
- // UID_10 - Select 3nd part of 10 Byte UID
- // 3+3+4 = 10.
- // get ride of previous 0x88
- sniffUID[3] = sniffUID[4];
- sniffUID[4] = sniffUID[5];
- sniffUID[5] = sniffUID[6];
- // new uid bytes
- memcpy(sniffUID+6, data+2, 4);
- sniffUIDType = SNF_UID_10;
- sniffState = SNF_SAK;
- }
- break;
- }
- case SNF_SAK:{
- // SAK from card?
- if ((!reader) && (len == 3) && (CheckCrc14A(data, 3))) {
- sniffSAK = data[0];
- // CL2 UID part to be expected
- if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) {
- sniffState = SNF_UID;
- // CL3 UID part to be expected
- } else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) {
- sniffState = SNF_UID;
- } else {
- // select completed
- sniffState = SNF_CARD_IDLE;
- }
- }
- break;
- }
- case SNF_CARD_IDLE:{ // trace the card select sequence
- sniffBuf[0] = 0xFF;
- sniffBuf[1] = 0xFF;
- memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID));
- memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA));
- sniffBuf[14] = sniffSAK;
- sniffBuf[15] = 0xFF;
- sniffBuf[16] = 0xFF;
- LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true);
- sniffState = SNF_CARD_CMD;
- } // intentionally no break;
- case SNF_CARD_CMD:{
- LogTrace(data, len, 0, 0, NULL, reader);
- timerData = GetTickCount();
- break;
- }
- default:
- sniffState = SNF_INIT;
- break;
- }
- return false;
-}
-*/
-
-void RAMFUNC MfSniffSend() {
- uint16_t tracelen = BigBuf_get_traceLen();
- int packlen = tracelen; // total number of bytes to write
- uint8_t *data = BigBuf_get_addr();
-
- while (packlen > 0) {
- LED_B_ON();
- uint16_t chunksize = MIN(PM3_CMD_DATA_SIZE, packlen); // chunk size 512
- reply_old(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize);
- packlen -= chunksize;
- LED_B_OFF();
- }
-
- LED_B_ON();
- reply_old(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished.
- LED_B_OFF();
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresniff_disabled.h b/pm3rdv4rrg/src/main/cpp/armsrc/mifaresniff_disabled.h
deleted file mode 100644
index 426e5ccf..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifaresniff_disabled.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2012
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support mifare classic sniffer.
-//-----------------------------------------------------------------------------
-
-#ifndef __MIFARESNIFF_H
-#define __MIFARESNIFF_H
-
-#include "common.h"
-
-#define SNF_INIT 0
-#define SNF_NO_FIELD 1
-#define SNF_ATQA 2
-#define SNF_UID 3
-#define SNF_SAK 4
-#define SNF_CARD_IDLE 5
-#define SNF_CARD_CMD 6
-#define SNF_MAGIC_WUPC2 7
-
-#define SNF_UID_4 0
-#define SNF_UID_7 0
-#define SNF_UID_10 0
-
-void MfSniffInit(void);
-bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader);
-void RAMFUNC MfSniffSend(void);
-void MfSniffEnd(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifareutil.c b/pm3rdv4rrg/src/main/cpp/armsrc/mifareutil.c
deleted file mode 100644
index 18df3aa1..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifareutil.c
+++ /dev/null
@@ -1,725 +0,0 @@
-// Merlok, May 2011, 2012
-// Many authors, whom made it possible
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Work with mifare cards.
-//-----------------------------------------------------------------------------
-#include "mifareutil.h"
-
-#include "string.h"
-#include "BigBuf.h"
-#include "iso14443a.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "parity.h"
-#include "commonutil.h"
-#include "crc16.h"
-#include "protocols.h"
-#include "des.h"
-
-int DBGLEVEL = DBG_ERROR;
-
-// crypto1 helpers
-void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out) {
- if (len != 1) {
- for (int i = 0; i < len; i++)
- data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i];
- } else {
- uint8_t bt = 0;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 3)) << 3;
- data_out[0] = bt;
- }
- return;
-}
-
-void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len) {
- mf_crypto1_decryptEx(pcs, data, len, data);
-}
-
-void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
- mf_crypto1_encryptEx(pcs, data, NULL, data, len, par);
-}
-
-void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par) {
- int i;
- par[0] = 0;
-
- for (i = 0; i < len; i++) {
- uint8_t bt = data_in[i];
- data_out[i] = crypto1_byte(pcs, keystream ? keystream[i] : 0x00, 0) ^ data_in[i];
- if ((i & 0x0007) == 0)
- par[ i >> 3 ] = 0;
- par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01) << (7 - (i & 0x0007)));
- }
-}
-
-uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
- uint8_t bt = 0;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 2)) << 2;
- bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 3)) << 3;
- return bt;
-}
-
-// write X byte basic commands
-int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
- uint8_t dcmd[data_size + 3];
- dcmd[0] = cmd;
- memcpy(dcmd + 1, data, data_size);
- AddCrc14A(dcmd, data_size + 1);
- ReaderTransmit(dcmd, sizeof(dcmd), timing);
- int len = ReaderReceive(answer, answer_parity);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd);
- len = ReaderReceive(answer, answer_parity);
- }
- return len;
-}
-
-// write 2 byte commands
-int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
- uint16_t pos;
- uint8_t dcmd[4] = {cmd, data, 0x00, 0x00};
- uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00};
- uint8_t par[1] = {0x00}; // 1 Byte parity is enough here
- AddCrc14A(dcmd, 2);
- memcpy(ecmd, dcmd, sizeof(dcmd));
-
- if (pcs && crypted) {
- par[0] = 0;
- for (pos = 0; pos < 4; pos++) {
- ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
- par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7 - pos));
- }
- ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
- } else {
- ReaderTransmit(dcmd, sizeof(dcmd), timing);
- }
-
- int len = ReaderReceive(answer, par);
-
- if (answer_parity) *answer_parity = par[0];
-
- if (crypted == CRYPT_ALL) {
- if (len == 1) {
- uint16_t res = 0;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3;
- answer[0] = res;
- } else {
- for (pos = 0; pos < len; pos++)
- answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos];
- }
- }
- return len;
-}
-
-// mifare classic commands
-int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) {
- return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
-}
-
-int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
- int len;
- uint32_t pos, nt, ntpp; // Supplied tag nonce
- uint8_t par[1] = {0x00};
- uint8_t nr[4];
- uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- // "random" reader nonce:
- num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
-
- // Transmit MIFARE_CLASSIC_AUTH
- len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
- if (len != 4) return 1;
-
- // Save the tag nonce (nt)
- nt = bytes_to_num(receivedAnswer, 4);
-
- // ----------------------------- crypto1 create
- if (isNested)
- crypto1_deinit(pcs);
-
- // Init cipher with key
- crypto1_init(pcs, ui64Key);
-
- if (isNested == AUTH_NESTED) {
- // decrypt nt with help of new key
- nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt;
- } else {
- // Load (plain) uid^nt into the cipher
- crypto1_word(pcs, nt ^ uid, 0);
- }
-
- // some statistic
- if (!ntptr && (DBGLEVEL >= DBG_EXTENDED))
- Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt);
-
- // save Nt
- if (ntptr)
- *ntptr = nt;
-
- // Generate (encrypted) nr+parity by loading it into the cipher (Nr)
- par[0] = 0;
- for (pos = 0; pos < 4; pos++) {
- mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
- par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7 - pos));
- }
-
- // Skip 32 bits in pseudo random generator
- nt = prng_successor(nt, 32);
-
- // ar+parity
- for (pos = 4; pos < 8; pos++) {
- nt = prng_successor(nt, 8);
- mf_nr_ar[pos] = crypto1_byte(pcs, 0x00, 0) ^ (nt & 0xff);
- par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7 - pos));
- }
-
- // Transmit reader nonce and reader answer
- ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
-
- // save standard timeout
- uint32_t save_timeout = iso14a_get_timeout();
-
- // set timeout for authentication response
- if (save_timeout > 103)
- iso14a_set_timeout(103);
-
- // Receive 4 byte tag answer
- len = ReaderReceive(receivedAnswer, receivedAnswerPar);
-
- iso14a_set_timeout(save_timeout);
-
- if (!len) {
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout.");
- return 2;
- }
-
- ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
-
- if (ntpp != bytes_to_num(receivedAnswer, 4)) {
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response.");
- return 3;
- }
- return 0;
-}
-
-int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
-
- int len;
- uint8_t bt[2] = {0x00, 0x00};
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
- if (len == 1) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
- return 1;
- }
- if (len != 18) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len);
- return 2;
- }
-
- memcpy(bt, receivedAnswer + 16, 2);
- AddCrc14A(receivedAnswer, 16);
- if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
- if (DBGLEVEL >= DBG_INFO) Dbprintf("Cmd CRC response error.");
- return 3;
- }
-
- memcpy(blockData, receivedAnswer, 16);
- return 0;
-}
-
-// mifare ultralight commands
-int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack) {
-
- uint16_t len = 0;
- uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00};
- uint8_t respPar[1] = {0x00};
- uint8_t key[4] = {0x00, 0x00, 0x00, 0x00};
- memcpy(key, keybytes, 4);
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);
-
- len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL);
-
- if (len != 4) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);
- return 0;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0], resp[1], resp[2], resp[3]);
-
- memcpy(pack, resp, 4);
- return 1;
-}
-
-int mifare_ultra_auth(uint8_t *keybytes) {
-
- /// 3des2k
- uint8_t random_a[8] = {1, 1, 1, 1, 1, 1, 1, 1};
- uint8_t random_b[8] = {0x00};
- uint8_t enc_random_b[8] = {0x00};
- uint8_t rnd_ab[16] = {0x00};
- uint8_t IV[8] = {0x00};
- uint8_t key[16] = {0x00};
- memcpy(key, keybytes, 16);
-
- uint16_t len = 0;
- uint8_t resp[19] = {0x00};
- uint8_t respPar[3] = {0, 0, 0};
-
- // REQUEST AUTHENTICATION
- len = mifare_sendcmd_short(NULL, CRYPT_NONE, MIFARE_ULC_AUTH_1, 0x00, resp, respPar, NULL);
- if (len != 11) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
- return 0;
- }
-
- // tag nonce.
- memcpy(enc_random_b, resp + 1, 8);
-
- // decrypt nonce.
- tdes_2key_dec((void *)random_b, (void *)enc_random_b, sizeof(random_b), (const void *)key, IV);
- rol(random_b, 8);
- memcpy(rnd_ab, random_a, 8);
- memcpy(rnd_ab + 8, random_b, 8);
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x",
- enc_random_b[0], enc_random_b[1], enc_random_b[2], enc_random_b[3], enc_random_b[4], enc_random_b[5], enc_random_b[6], enc_random_b[7]);
-
- Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x",
- random_b[0], random_b[1], random_b[2], random_b[3], random_b[4], random_b[5], random_b[6], random_b[7]);
-
- Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
- rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3], rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
-
- Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
- rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11], rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
- }
-
- // encrypt out, in, length, key, iv
- tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);
-
- len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
- if (len != 11) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
- return 0;
- }
-
- uint8_t enc_resp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- uint8_t resp_random_a[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- memcpy(enc_resp, resp + 1, 8);
-
- // decrypt out, in, length, key, iv
- tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);
- if (memcmp(resp_random_a, random_a, 8) != 0) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("failed authentication");
- return 0;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
- rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3],
- rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
-
- Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
- rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11],
- rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
-
- Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",
- random_a[0], random_a[1], random_a[2], random_a[3],
- random_a[4], random_a[5], random_a[6], random_a[7]);
-
- Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x",
- resp_random_a[0], resp_random_a[1], resp_random_a[2], resp_random_a[3],
- resp_random_a[4], resp_random_a[5], resp_random_a[6], resp_random_a[7]);
- }
- return 1;
-}
-
-int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) {
- uint16_t len = 0;
- uint8_t bt[2] = {0x00, 0x00};
- uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
-
- len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
- if (len == 1) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
- return 1;
- }
- if (len != 18) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);
- return 2;
- }
-
- memcpy(bt, receivedAnswer + 16, 2);
- AddCrc14A(receivedAnswer, 16);
- if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd CRC response error.");
- return 3;
- }
-
- memcpy(blockData, receivedAnswer, 16);
- return 0;
-}
-int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
-#define MFU_MAX_RETRIES 5
- uint8_t res;
-
- for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) {
- res = mifare_ultra_readblockEx(blockNo, blockData);
-
- // break if OK, or NACK.
- switch (res) {
- case 0:
- case 1:
- return res;
- default:
- continue;
- }
- }
- return res;
-}
-
-int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
- // variables
- uint16_t len = 0;
- uint32_t pos = 0;
- uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to write
- uint8_t res = 0;
-
- uint8_t d_block[18], d_block_enc[18];
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- // command MIFARE_CLASSIC_WRITEBLOCK
- len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
-
- if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
- return 1;
- }
-
- memcpy(d_block, blockData, 16);
- AddCrc14A(d_block, 16);
-
- // crypto
- for (pos = 0; pos < 18; pos++) {
- d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
- par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
- }
-
- ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
-
- // Receive the response
- len = ReaderReceive(receivedAnswer, receivedAnswerPar);
-
- res = 0;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
- res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
-
- if ((len != 1) || (res != 0x0A)) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd write data2 Error: %02x", res);
- return 2;
- }
- return 0;
-}
-
-/* // command not needed, but left for future testing
-int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
- uint16_t len;
- uint8_t par[3] = {0}; // enough for 18 parity bits
- uint8_t d_block[18] = {0x00};
- uint8_t receivedAnswer[MAX_FRAME_SIZE];
- uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
-
- len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
-
- if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
- if (DBGLEVEL >= DBG_ERROR)
- Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
- return 1;
- }
-
- memcpy(d_block, blockData, 16);
- AddCrc14A(d_block, 16);
-
- ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
-
- len = ReaderReceive(receivedAnswer, receivedAnswerPar);
-
- if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
- if (DBGLEVEL >= DBG_ERROR)
- Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
- return 2;
- }
- return 0;
-}
-*/
-
-int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
- uint16_t len = 0;
- uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 };
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
-
- // command MIFARE_CLASSIC_WRITEBLOCK
- memcpy(block + 1, blockData, 4);
-
- len = mifare_sendcmd(MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL);
-
- if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
- if (DBGLEVEL >= DBG_ERROR)
- Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
- return 1;
- }
- return 0;
-}
-int mifare_classic_halt_ex(struct Crypto1State *pcs) {
- uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
- uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
- if (len != 0) {
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len);
- return 1;
- }
- return 0;
-}
-int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) {
- return mifare_classic_halt_ex(pcs);
-}
-
-int mifare_ultra_halt() {
- uint16_t len = 0;
- uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
- len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
- if (len != 0) {
- if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len);
- return 1;
- }
- return 0;
-}
-
-
-// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
-// plus evtl. 8 sectors with 16 blocks each (4k cards)
-uint8_t NumBlocksPerSector(uint8_t sectorNo) {
- return (sectorNo < 32) ? 4 : 16;
-}
-
-uint8_t FirstBlockOfSector(uint8_t sectorNo) {
- if (sectorNo < 32)
- return sectorNo * 4;
- else
- return 32 * 4 + (sectorNo - 32) * 16;
-
-}
-
-// work with emulator memory
-void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
- emlSetMem_xt(data, blockNum, blocksCount, 16);
-}
-
-void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
- uint8_t *emCARD = BigBuf_get_EM_addr();
- memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);
-}
-
-void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
- uint8_t *emCARD = BigBuf_get_EM_addr();
- memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
-}
-
-void emlGetMemBt(uint8_t *data, int offset, int byteCount) {
- uint8_t *emCARD = BigBuf_get_EM_addr();
- memcpy(data, emCARD + offset, byteCount);
-}
-
-int emlCheckValBl(int blockNum) {
- uint8_t *emCARD = BigBuf_get_EM_addr();
- uint8_t *data = emCARD + blockNum * 16;
-
- if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
- (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) ||
- (data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) ||
- (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) ||
- (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) ||
- (data[12] != (data[15] ^ 0xff))
- )
- return 1;
- return 0;
-}
-
-int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
- uint8_t *emCARD = BigBuf_get_EM_addr();
- uint8_t *data = emCARD + blockNum * 16;
-
- if (emlCheckValBl(blockNum))
- return 1;
-
- memcpy(blReg, data, 4);
- *blBlock = data[12];
- return 0;
-}
-
-int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
- uint8_t *emCARD = BigBuf_get_EM_addr();
- uint8_t *data = emCARD + blockNum * 16;
-
- memcpy(data + 0, &blReg, 4);
- memcpy(data + 8, &blReg, 4);
- blReg = blReg ^ 0xffffffff;
- memcpy(data + 4, &blReg, 4);
-
- data[12] = blBlock;
- data[13] = blBlock ^ 0xff;
- data[14] = blBlock;
- data[15] = blBlock ^ 0xff;
-
- return 0;
-}
-
-uint64_t emlGetKey(int sectorNum, int keyType) {
- uint8_t key[6] = {0x00};
- uint8_t *emCARD = BigBuf_get_EM_addr();
- memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
- return bytes_to_num(key, 6);
-}
-
-void emlClearMem(void) {
- const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
- uint8_t *emCARD = BigBuf_get_EM_addr();
- memset(emCARD, 0, CARD_MEMORY_SIZE);
-
- // fill sectors trailer data
- for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK) ? (b += 4) : (b += 16)))
- emlSetMem((uint8_t *)trailer, b, 1);
-
- // uid
- emlSetMem((uint8_t *)uid, 0, 1);
- return;
-}
-
-uint8_t SectorTrailer(uint8_t blockNo) {
- if (blockNo <= MIFARE_2K_MAXBLOCK) {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
- return (blockNo | 0x03);
- } else {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
- return (blockNo | 0x0f);
- }
-}
-
-bool IsSectorTrailer(uint8_t blockNo) {
- return (blockNo == SectorTrailer(blockNo));
-}
-
-// Mifare desfire commands
-int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
- uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00};
- AddCrc14A(dcmd, 3);
-
- ReaderTransmit(dcmd, sizeof(dcmd), NULL);
- int len = ReaderReceive(answer, answer_parity);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
- return 1;
- }
- return len;
-}
-
-int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
- uint8_t dcmd[20] = {0x00};
- dcmd[0] = cmd;
- memcpy(dcmd + 1, data, 17);
- AddCrc14A(dcmd, 18);
-
- ReaderTransmit(dcmd, sizeof(dcmd), NULL);
- int len = ReaderReceive(answer, answer_parity);
- if (!len) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
- return 1;
- }
- return len;
-}
-
-int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData) {
-
- int len;
- // load key, keynumber
- uint8_t data[2] = {MFDES_AUTHENTICATE, 0x00};
- uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
-
- len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer, receivedAnswerPar, NULL);
- if (len == 1) {
- if (DBGLEVEL >= DBG_ERROR)
- Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
- return 1;
- }
-
- if (len == 12) {
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
- receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
- receivedAnswer[10], receivedAnswer[11]);
- }
- memcpy(blockData, receivedAnswer, 12);
- return 0;
- }
- return 1;
-}
-
-int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) {
-
- int len;
- uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME};
- memcpy(data + 1, key, 16);
-
- uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
- uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
-
- len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar, NULL);
-
- if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) {
- if (DBGLEVEL >= DBG_ERROR)
- Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]);
- return 1;
- }
-
- if (len == 12) {
- if (DBGLEVEL >= DBG_EXTENDED) {
- Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
- receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
- receivedAnswer[10], receivedAnswer[11]);
- }
- memcpy(blockData, receivedAnswer, 12);
- return 0;
- }
- return 1;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/mifareutil.h b/pm3rdv4rrg/src/main/cpp/armsrc/mifareutil.h
deleted file mode 100644
index 64eb0454..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/mifareutil.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok, May 2011
-// Many authors, that makes it possible
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// code for work with mifare cards.
-//-----------------------------------------------------------------------------
-
-#ifndef __MIFAREUTIL_H
-#define __MIFAREUTIL_H
-
-#include "common.h"
-#include "crapto1/crapto1.h"
-
-// mifare authentication
-#define CRYPT_NONE 0
-#define CRYPT_ALL 1
-#define CRYPT_REQUEST 2
-#define AUTH_FIRST 0
-#define AUTH_NESTED 2
-
-#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
-#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
-
-// reader voltage field detector
-#define MF_MINFIELDV 4000
-
-// Mifare 4k/2k/1k/mini Max Block / Max Sector
-#define MIFARE_4K_MAXBLOCK 256
-#define MIFARE_2K_MAXBLOCK 128
-#define MIFARE_1K_MAXBLOCK 64
-#define MIFARE_MINI_MAXBLOCK 20
-
-#define MIFARE_MINI_MAXSECTOR 5
-#define MIFARE_1K_MAXSECTOR 16
-#define MIFARE_2K_MAXSECTOR 32
-#define MIFARE_4K_MAXSECTOR 40
-
-//mifare emulator states
-#define MFEMUL_NOFIELD 0
-#define MFEMUL_IDLE 1
-#define MFEMUL_SELECT 2
-#define MFEMUL_AUTH1 3
-#define MFEMUL_WORK 4
-#define MFEMUL_WRITEBL2 5
-#define MFEMUL_INTREG_INC 6
-#define MFEMUL_INTREG_DEC 7
-#define MFEMUL_INTREG_REST 8
-#define MFEMUL_HALTED 9
-
-#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
-
-#ifndef MifareBlockToSector
-#define MifareBlockToSector(block) (block < 128 ? block / 4 : (block - 128) / 16 + 32)
-#endif
-
-//functions
-int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
-int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
-
-// mifare classic
-int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
-int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
-int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
-int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
-int mifare_classic_halt_ex(struct Crypto1State *pcs);
-int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
-
-// Ultralight/NTAG...
-int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
-int mifare_ultra_auth(uint8_t *keybytes);
-int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
-//int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
-int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
-int mifare_ultra_halt();
-
-// desfire
-int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
-int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
-int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
-int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);
-
-// crypto functions
-void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len);
-void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out);
-void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);
-void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par);
-uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
-
-// Mifare memory structure
-uint8_t NumBlocksPerSector(uint8_t sectorNo);
-uint8_t FirstBlockOfSector(uint8_t sectorNo);
-
-bool IsSectorTrailer(uint8_t blockNo);
-uint8_t SectorTrailer(uint8_t blockNo);
-
-// emulator functions
-void emlClearMem(void);
-void emlSetMem(uint8_t *data, int blockNum, int blocksCount);
-void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
-void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
-void emlGetMemBt(uint8_t *data, int offset, int byteCount);
-uint64_t emlGetKey(int sectorNum, int keyType);
-int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
-int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
-int emlCheckValBl(int blockNum);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/nprintf.c b/pm3rdv4rrg/src/main/cpp/armsrc/nprintf.c
deleted file mode 100644
index 645454b4..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/nprintf.c
+++ /dev/null
@@ -1,894 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// \author (c) Marco Paland (info@paland.com)
-// 2014-2019, PALANDesign Hannover, Germany
-//
-// \license The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
-// embedded systems with a very limited resources. These routines are thread
-// safe and reentrant!
-// Use this instead of the bloated standard/newlib printf cause these use
-// malloc for printf (and may not be thread safe).
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "nprintf.h"
-
-
-// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
-// printf_config.h header file
-// default: undefined
-#ifdef PRINTF_INCLUDE_CONFIG_H
-#include "printf_config.h"
-#endif
-
-
-// 'ntoa' conversion buffer size, this must be big enough to hold one converted
-// numeric number including padded zeros (dynamically created on stack)
-// default: 32 byte
-#ifndef PRINTF_NTOA_BUFFER_SIZE
-#define PRINTF_NTOA_BUFFER_SIZE 32U
-#endif
-
-// 'ftoa' conversion buffer size, this must be big enough to hold one converted
-// float number including padded zeros (dynamically created on stack)
-// default: 32 byte
-#ifndef PRINTF_FTOA_BUFFER_SIZE
-#define PRINTF_FTOA_BUFFER_SIZE 32U
-#endif
-
-// support for the floating point type (%f)
-// default: activated
-#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
-#define PRINTF_SUPPORT_FLOAT
-#endif
-
-// support for exponential floating point notation (%e/%g)
-// default: activated
-#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
-#define PRINTF_SUPPORT_EXPONENTIAL
-#endif
-
-// define the default floating point precision
-// default: 6 digits
-#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
-#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
-#endif
-
-// define the largest float suitable to print with %f
-// default: 1e9
-#ifndef PRINTF_MAX_FLOAT
-#define PRINTF_MAX_FLOAT 1e9
-#endif
-
-// support for the long long types (%llu or %p)
-// default: activated
-#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
-#define PRINTF_SUPPORT_LONG_LONG
-#endif
-
-// support for the ptrdiff_t type (%t)
-// ptrdiff_t is normally defined in as long or long long type
-// default: activated
-#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
-#define PRINTF_SUPPORT_PTRDIFF_T
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
-// internal flag definitions
-#define FLAGS_ZEROPAD (1U << 0U)
-#define FLAGS_LEFT (1U << 1U)
-#define FLAGS_PLUS (1U << 2U)
-#define FLAGS_SPACE (1U << 3U)
-#define FLAGS_HASH (1U << 4U)
-#define FLAGS_UPPERCASE (1U << 5U)
-#define FLAGS_CHAR (1U << 6U)
-#define FLAGS_SHORT (1U << 7U)
-#define FLAGS_LONG (1U << 8U)
-#define FLAGS_LONG_LONG (1U << 9U)
-#define FLAGS_PRECISION (1U << 10U)
-#define FLAGS_ADAPT_EXP (1U << 11U)
-
-
-// import float.h for DBL_MAX
-#if defined(PRINTF_SUPPORT_FLOAT)
-#include
-#endif
-
-
-// output function type
-typedef void (*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);
-
-
-// wrapper (used as buffer) for output function type
-typedef struct {
- void (*fct)(char character, void *arg);
- void *arg;
-} out_fct_wrap_type;
-
-
-// internal buffer output
-static inline void _out_buffer(char character, void *buffer, size_t idx, size_t maxlen) {
- if (idx < maxlen) {
- ((char *)buffer)[idx] = character;
- }
-}
-
-
-// internal null output
-static inline void _out_null(char character, void *buffer, size_t idx, size_t maxlen) {
- (void)character;
- (void)buffer;
- (void)idx;
- (void)maxlen;
-}
-
-
-// internal _putchar wrapper
-static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) {
- (void)buffer;
- (void)idx;
- (void)maxlen;
- if (character) {
- _putchar(character);
- }
-}
-
-
-// internal output function wrapper
-static inline void _out_fct(char character, void *buffer, size_t idx, size_t maxlen) {
- (void)idx;
- (void)maxlen;
- if (character) {
- // buffer is the output fct pointer
- ((out_fct_wrap_type *)buffer)->fct(character, ((out_fct_wrap_type *)buffer)->arg);
- }
-}
-
-
-// internal secure strlen
-// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
-static inline unsigned int _strnlen_s(const char *str, size_t maxsize) {
- const char *s;
- for (s = str; *s && maxsize--; ++s);
- return (unsigned int)(s - str);
-}
-
-
-// internal test if char is a digit (0-9)
-// \return true if char is a digit
-static inline bool _is_digit(char ch) {
- return (ch >= '0') && (ch <= '9');
-}
-
-
-// internal ASCII string to unsigned int conversion
-static unsigned int _atoi(const char **str) {
- unsigned int i = 0U;
- while (_is_digit(**str)) {
- i = i * 10U + (unsigned int)(*((*str)++) - '0');
- }
- return i;
-}
-
-
-// output the specified string in reverse, taking care of any zero-padding
-static size_t _out_rev(out_fct_type out, char *buffer, size_t idx, size_t maxlen, const char *buf, size_t len, unsigned int width, unsigned int flags) {
- const size_t start_idx = idx;
-
- // pad spaces up to given width
- if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
- for (size_t i = len; i < width; i++) {
- out(' ', buffer, idx++, maxlen);
- }
- }
-
- // reverse string
- while (len) {
- out(buf[--len], buffer, idx++, maxlen);
- }
-
- // append pad spaces up to given width
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
-
- return idx;
-}
-
-
-// internal itoa format
-static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx, size_t maxlen, char *buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) {
- // pad leading zeros
- if (!(flags & FLAGS_LEFT)) {
- if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
- width--;
- }
- while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
- while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
- }
-
- // handle hash
- if (flags & FLAGS_HASH) {
- if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
- len--;
- if (len && (base == 16U)) {
- len--;
- }
- }
- if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'x';
- } else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'X';
- } else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'b';
- }
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- buf[len++] = '0';
- }
- }
-
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
- } else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
- } else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
- }
- }
-
- return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
-}
-
-
-// internal itoa for 'long' type
-static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) {
- char buf[PRINTF_NTOA_BUFFER_SIZE];
- size_t len = 0U;
-
- // no hash for 0 values
- if (!value) {
- flags &= ~FLAGS_HASH;
- }
-
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
- do {
- const char digit = (char)(value % base);
- buf[len++] = digit < 10 ? '0' + digit : ((flags & FLAGS_UPPERCASE) ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
-}
-
-
-// internal itoa for 'long long' type
-#if defined(PRINTF_SUPPORT_LONG_LONG)
-static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) {
- char buf[PRINTF_NTOA_BUFFER_SIZE];
- size_t len = 0U;
-
- // no hash for 0 values
- if (!value) {
- flags &= ~FLAGS_HASH;
- }
-
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
- do {
- const char digit = (char)(value % base);
- buf[len++] = digit < 10 ? '0' + digit : ((flags & FLAGS_UPPERCASE) ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
-}
-#endif // PRINTF_SUPPORT_LONG_LONG
-
-
-#if defined(PRINTF_SUPPORT_FLOAT)
-
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
-// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
-static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
-#endif
-
-
-// internal ftoa for fixed decimal floating point
-static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) {
- char buf[PRINTF_FTOA_BUFFER_SIZE];
- size_t len = 0U;
- double diff = 0.0;
-
- // powers of 10
- static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
-
- // test for special values
- if (value != value)
- return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
- if (value < -DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
- if (value > DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
-
- // test for very large values
- // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
- if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
- return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
-#else
- return 0U;
-#endif
- }
-
- // test for negative
- bool negative = false;
- if (value < 0) {
- negative = true;
- value = 0 - value;
- }
-
- // set default precision, if not set explicitly
- if (!(flags & FLAGS_PRECISION)) {
- prec = PRINTF_DEFAULT_FLOAT_PRECISION;
- }
- // limit precision to 9, cause a prec >= 10 can lead to overflow errors
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
- buf[len++] = '0';
- prec--;
- }
-
- int whole = (int)value;
- double tmp = (value - whole) * pow10[prec];
- unsigned long frac = (unsigned long)tmp;
- diff = tmp - frac;
-
- if (diff > 0.5) {
- ++frac;
- // handle rollover, e.g. case 0.99 with prec 1 is 1.0
- if (frac >= pow10[prec]) {
- frac = 0;
- ++whole;
- }
- } else if (diff < 0.5) {
- } else if ((frac == 0U) || (frac & 1U)) {
- // if halfway, round up if odd OR if last digit is 0
- ++frac;
- }
-
- if (prec == 0U) {
- diff = value - (double)whole;
- if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
- // exactly 0.5 and ODD, then round up
- // 1.5 -> 2, but 2.5 -> 2
- ++whole;
- }
- } else {
- unsigned int count = prec;
- // now do fractional part, as an unsigned number
- while (len < PRINTF_FTOA_BUFFER_SIZE) {
- --count;
- buf[len++] = (char)(48U + (frac % 10U));
- if (!(frac /= 10U)) {
- break;
- }
- }
- // add extra 0s
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
- buf[len++] = '0';
- }
- if (len < PRINTF_FTOA_BUFFER_SIZE) {
- // add decimal
- buf[len++] = '.';
- }
- }
-
- // do whole part, number is reversed
- while (len < PRINTF_FTOA_BUFFER_SIZE) {
- buf[len++] = (char)(48 + (whole % 10));
- if (!(whole /= 10)) {
- break;
- }
- }
-
- // pad leading zeros
- if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
- if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
- width--;
- }
- while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
- }
-
- if (len < PRINTF_FTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
- } else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
- } else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
- }
- }
-
- return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
-}
-
-
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
-// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse
-static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) {
- // check for NaN and special values
- if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
- return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
- }
-
- // determine the sign
- const bool negative = value < 0;
- if (negative) {
- value = -value;
- }
-
- // default precision
- if (!(flags & FLAGS_PRECISION)) {
- prec = PRINTF_DEFAULT_FLOAT_PRECISION;
- }
-
- // determine the decimal exponent
- // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
- union {
- uint64_t U;
- double F;
- } conv;
-
- conv.F = value;
- int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
- conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
- // now approximate log10 from the log2 integer part and an expansion of ln around 1.5
- int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
- // now we want to compute 10^expval but we want to be sure it won't overflow
- exp2 = (int)(expval * 3.321928094887362 + 0.5);
- const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
- const double z2 = z * z;
- conv.U = (uint64_t)(exp2 + 1023) << 52U;
- // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
- conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
- // correct for rounding errors
- if (value < conv.F) {
- expval--;
- conv.F /= 10;
- }
-
- // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
- unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
-
- // in "%g" mode, "prec" is the number of *significant figures* not decimals
- if (flags & FLAGS_ADAPT_EXP) {
- // do we want to fall-back to "%f" mode?
- if ((value >= 1e-4) && (value < 1e6)) {
- if ((int)prec > expval) {
- prec = (unsigned)((int)prec - expval - 1);
- } else {
- prec = 0;
- }
- flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
- // no characters in exponent
- minwidth = 0U;
- expval = 0;
- } else {
- // we use one sigfig for the whole part
- if ((prec > 0) && (flags & FLAGS_PRECISION)) {
- --prec;
- }
- }
- }
-
- // will everything fit?
- unsigned int fwidth = width;
- if (width > minwidth) {
- // we didn't fall-back so subtract the characters required for the exponent
- fwidth -= minwidth;
- } else {
- // not enough characters, so go back to default sizing
- fwidth = 0U;
- }
- if ((flags & FLAGS_LEFT) && minwidth) {
- // if we're padding on the right, DON'T pad the floating part
- fwidth = 0U;
- }
-
- // rescale the float value
- if (expval) {
- value /= conv.F;
- }
-
- // output the floating part
- const size_t start_idx = idx;
- idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
-
- // output the exponent part
- if (minwidth) {
- // output the exponential symbol
- out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
- // output the exponent value
- idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS);
- // might need to right-pad spaces
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
- }
- }
- return idx;
-}
-#endif // PRINTF_SUPPORT_EXPONENTIAL
-#endif // PRINTF_SUPPORT_FLOAT
-
-
-// internal vsnprintf
-static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, const char *format, va_list va) {
- unsigned int flags, width, precision, n;
- size_t idx = 0U;
-
- if (!buffer) {
- // use null output function
- out = _out_null;
- }
-
- while (*format) {
- // format specifier? %[flags][width][.precision][length]
- if (*format != '%') {
- // no
- out(*format, buffer, idx++, maxlen);
- format++;
- continue;
- } else {
- // yes, evaluate it
- format++;
- }
-
- // evaluate flags
- flags = 0U;
- do {
- switch (*format) {
- case '0':
- flags |= FLAGS_ZEROPAD;
- format++;
- n = 1U;
- break;
- case '-':
- flags |= FLAGS_LEFT;
- format++;
- n = 1U;
- break;
- case '+':
- flags |= FLAGS_PLUS;
- format++;
- n = 1U;
- break;
- case ' ':
- flags |= FLAGS_SPACE;
- format++;
- n = 1U;
- break;
- case '#':
- flags |= FLAGS_HASH;
- format++;
- n = 1U;
- break;
- default :
- n = 0U;
- break;
- }
- } while (n);
-
- // evaluate width field
- width = 0U;
- if (_is_digit(*format)) {
- width = _atoi(&format);
- } else if (*format == '*') {
- const int w = va_arg(va, int);
- if (w < 0) {
- flags |= FLAGS_LEFT; // reverse padding
- width = (unsigned int) - w;
- } else {
- width = (unsigned int)w;
- }
- format++;
- }
-
- // evaluate precision field
- precision = 0U;
- if (*format == '.') {
- flags |= FLAGS_PRECISION;
- format++;
- if (_is_digit(*format)) {
- precision = _atoi(&format);
- } else if (*format == '*') {
- const int prec = (int)va_arg(va, int);
- precision = prec > 0 ? (unsigned int)prec : 0U;
- format++;
- }
- }
-
- // evaluate length field
- switch (*format) {
- case 'l' :
- flags |= FLAGS_LONG;
- format++;
- if (*format == 'l') {
- flags |= FLAGS_LONG_LONG;
- format++;
- }
- break;
- case 'h' :
- flags |= FLAGS_SHORT;
- format++;
- if (*format == 'h') {
- flags |= FLAGS_CHAR;
- format++;
- }
- break;
-#if defined(PRINTF_SUPPORT_PTRDIFF_T)
- case 't' :
- flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
-#endif
- case 'j' :
- flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
- case 'z' :
- flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
- default :
- break;
- }
-
- // evaluate specifier
- switch (*format) {
- case 'd' :
- case 'i' :
- case 'u' :
- case 'x' :
- case 'X' :
- case 'o' :
- case 'b' : {
- // set the base
- unsigned int base;
- if (*format == 'x' || *format == 'X') {
- base = 16U;
- } else if (*format == 'o') {
- base = 8U;
- } else if (*format == 'b') {
- base = 2U;
- } else {
- base = 10U;
- flags &= ~FLAGS_HASH; // no hash for dec format
- }
- // uppercase
- if (*format == 'X') {
- flags |= FLAGS_UPPERCASE;
- }
-
- // no plus or space flag for u, x, X, o, b
- if ((*format != 'i') && (*format != 'd')) {
- flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
- }
-
- // ignore '0' flag when precision is given
- if (flags & FLAGS_PRECISION) {
- flags &= ~FLAGS_ZEROPAD;
- }
-
- // convert the integer
- if ((*format == 'i') || (*format == 'd')) {
- // signed
- if (flags & FLAGS_LONG_LONG) {
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- const long long value = va_arg(va, long long);
- idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
-#endif
- } else if (flags & FLAGS_LONG) {
- const long value = va_arg(va, long);
- idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
- } else {
- const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
- idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
- }
- } else {
- // unsigned
- if (flags & FLAGS_LONG_LONG) {
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
-#endif
- } else if (flags & FLAGS_LONG) {
- idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
- } else {
- const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
- idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
- }
- }
- format++;
- break;
- }
-#if defined(PRINTF_SUPPORT_FLOAT)
- case 'f' :
- case 'F' :
- if (*format == 'F') flags |= FLAGS_UPPERCASE;
- idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
- format++;
- break;
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- if ((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP;
- if ((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE;
- idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
- format++;
- break;
-#endif // PRINTF_SUPPORT_EXPONENTIAL
-#endif // PRINTF_SUPPORT_FLOAT
- case 'c' : {
- unsigned int l = 1U;
- // pre padding
- if (!(flags & FLAGS_LEFT)) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- // char output
- out((char)va_arg(va, int), buffer, idx++, maxlen);
- // post padding
- if (flags & FLAGS_LEFT) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- format++;
- break;
- }
-
- case 's' : {
- const char *p = va_arg(va, char *);
- unsigned int l = _strnlen_s(p, precision ? precision : (size_t) - 1);
- // pre padding
- if (flags & FLAGS_PRECISION) {
- l = (l < precision ? l : precision);
- }
- if (!(flags & FLAGS_LEFT)) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- // string output
- while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
- out(*(p++), buffer, idx++, maxlen);
- }
- // post padding
- if (flags & FLAGS_LEFT) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- format++;
- break;
- }
-
- case 'p' : {
- width = sizeof(void *) * 2U;
- flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
- if (is_ll) {
- idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void *), false, 16U, precision, width, flags);
- } else {
-#endif
- idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void *)), false, 16U, precision, width, flags);
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- }
-#endif
- format++;
- break;
- }
-
- case '%' :
- out('%', buffer, idx++, maxlen);
- format++;
- break;
-
- default :
- out(*format, buffer, idx++, maxlen);
- format++;
- break;
- }
- }
-
- // termination
- out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
-
- // return written chars without terminating \0
- return (int)idx;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-int printf_(const char *format, ...) {
- va_list va;
- va_start(va, format);
- char buffer[1];
- const int ret = _vsnprintf(_out_char, buffer, (size_t) - 1, format, va);
- va_end(va);
- return ret;
-}
-
-
-int sprintf_(char *buffer, const char *format, ...) {
- va_list va;
- va_start(va, format);
- const int ret = _vsnprintf(_out_buffer, buffer, (size_t) - 1, format, va);
- va_end(va);
- return ret;
-}
-
-
-int snprintf_(char *buffer, size_t count, const char *format, ...) {
- va_list va;
- va_start(va, format);
- const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
- va_end(va);
- return ret;
-}
-
-
-int vprintf_(const char *format, va_list va) {
- char buffer[1];
- return _vsnprintf(_out_char, buffer, (size_t) - 1, format, va);
-}
-
-
-int vsnprintf_(char *buffer, size_t count, const char *format, va_list va) {
- return _vsnprintf(_out_buffer, buffer, count, format, va);
-}
-
-
-int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...) {
- va_list va;
- va_start(va, format);
- const out_fct_wrap_type out_fct_wrap = { out, arg };
- const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, (size_t) - 1, format, va);
- va_end(va);
- return ret;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/nprintf.h b/pm3rdv4rrg/src/main/cpp/armsrc/nprintf.h
deleted file mode 100644
index 5c83384b..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/nprintf.h
+++ /dev/null
@@ -1,107 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// \author (c) Marco Paland (info@paland.com)
-// 2014-2019, PALANDesign Hannover, Germany
-//
-// \license The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
-// embedded systems with a very limited resources.
-// Use this instead of bloated standard/newlib printf.
-// These routines are thread safe and reentrant.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _PRINTF_H_
-#define _PRINTF_H_
-
-#include
-#include
-#include
-#include
-
-/**
- * Output a character to a custom device like UART, used by the printf() function
- * This function is declared here only. You have to write your custom implementation somewhere
- * \param character Character to output
- */
-void _putchar(char character);
-
-
-/**
- * Tiny printf implementation
- * You have to implement _putchar if you use printf()
- * To avoid conflicts with the regular printf() API it is overridden by macro defines
- * and internal underscore-appended functions like printf_() are used
- * \param format A string that specifies the format of the output
- * \return The number of characters that are written into the array, not counting the terminating null character
- */
-#define printf printf_
-int printf_(const char *format, ...);
-
-
-/**
- * Tiny sprintf implementation
- * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
- * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
- * \param format A string that specifies the format of the output
- * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
- */
-#define sprintf sprintf_
-int sprintf_(char *buffer, const char *format, ...);
-
-
-/**
- * Tiny snprintf/vsnprintf implementation
- * \param buffer A pointer to the buffer where to store the formatted string
- * \param count The maximum number of characters to store in the buffer, including a terminating null character
- * \param format A string that specifies the format of the output
- * \param va A value identifying a variable arguments list
- * \return The number of characters that COULD have been written into the buffer, not counting the terminating
- * null character. A value equal or larger than count indicates truncation. Only when the returned value
- * is non-negative and less than count, the string has been completely written.
- */
-#define snprintf snprintf_
-#define vsnprintf vsnprintf_
-int snprintf_(char *buffer, size_t count, const char *format, ...);
-int vsnprintf_(char *buffer, size_t count, const char *format, va_list va);
-
-
-/**
- * Tiny vprintf implementation
- * \param format A string that specifies the format of the output
- * \param va A value identifying a variable arguments list
- * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
- */
-#define vprintf vprintf_
-int vprintf_(const char *format, va_list va);
-
-
-/**
- * printf with output function
- * You may use this as dynamic alternative to printf() with its fixed _putchar() output
- * \param out An output function which takes one character and an argument pointer
- * \param arg An argument pointer for user data passed to output function
- * \param format A string that specifies the format of the output
- * \return The number of characters that are sent to the output function, not counting the terminating null character
- */
-int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...);
-
-#endif // _PRINTF_H_
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/obj/.dummy b/pm3rdv4rrg/src/main/cpp/armsrc/obj/.dummy
deleted file mode 100644
index e69de29b..00000000
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/obj/Standalone/.dummy b/pm3rdv4rrg/src/main/cpp/armsrc/obj/Standalone/.dummy
deleted file mode 100644
index e69de29b..00000000
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/optimized_cipher.c b/pm3rdv4rrg/src/main/cpp/armsrc/optimized_cipher.c
deleted file mode 100644
index 0f762a8d..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/optimized_cipher.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*****************************************************************************
- * WARNING
- *
- * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
- *
- * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
- * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
- * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
- *
- * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
- *
- *****************************************************************************
- *
- * This file is part of loclass. It is a reconstructon of the cipher engine
- * used in iClass, and RFID techology.
- *
- * The implementation is based on the work performed by
- * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
- * Milosch Meriac in the paper "Dismantling IClass".
- *
- * Copyright (C) 2014 Martin Holst Swende
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation, or, at your option, any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with loclass. If not, see .
- *
- *
- *
- ****************************************************************************/
-
-/**
-
- This file contains an optimized version of the MAC-calculation algorithm. Some measurements on
- a std laptop showed it runs in about 1/3 of the time:
-
- Std: 0.428962
- Opt: 0.151609
-
- Additionally, it is self-reliant, not requiring e.g. bitstreams from the cipherutils, thus can
- be easily dropped into a code base.
-
- The optimizations have been performed in the following steps:
- * Parameters passed by reference instead of by value.
- * Iteration instead of recursion, un-nesting recursive loops into for-loops.
- * Handling of bytes instead of individual bits, for less shuffling and masking
- * Less creation of "objects", structs, and instead reuse of alloc:ed memory
- * Inlining some functions via #define:s
-
- As a consequence, this implementation is less generic. Also, I haven't bothered documenting this.
- For a thorough documentation, check out the MAC-calculation within cipher.c instead.
-
- -- MHS 2015
-**/
-
-/**
-
- The runtime of opt_doTagMAC_2() with the MHS optimized version was 403 microseconds on Proxmark3.
- This was still to slow for some newer readers which didn't want to wait that long.
-
- Further optimizations to speedup the MAC calculations:
- * Optimized opt_Tt logic
- * Look up table for opt_select
- * Removing many unnecessary bit maskings (& 0x1)
- * updating state in place instead of alternating use of a second state structure
- * remove the necessity to reverse bits of input and output bytes
-
- opt_doTagMAC_2() now completes in 270 microseconds.
-
- -- piwi 2019
-**/
-
-#include "optimized_cipher.h"
-
-static const uint8_t opt_select_LUT[256] = {
- 00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04,
- 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04,
- 06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06,
- 07, 04, 05, 06, 04, 05, 06, 07, 07, 04, 04, 07, 04, 05, 07, 06,
- 06, 05, 04, 07, 04, 05, 06, 07, 02, 01, 01, 02, 00, 01, 03, 02,
- 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06,
- 00, 03, 02, 01, 02, 03, 00, 01, 00, 03, 03, 00, 02, 03, 01, 00,
- 05, 06, 07, 04, 06, 07, 04, 05, 05, 06, 06, 05, 06, 07, 05, 04,
- 02, 01, 00, 03, 00, 01, 02, 03, 06, 05, 05, 06, 04, 05, 07, 06,
- 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06,
- 02, 01, 00, 03, 00, 01, 02, 03, 02, 01, 01, 02, 00, 01, 03, 02,
- 03, 00, 01, 02, 00, 01, 02, 03, 03, 00, 00, 03, 00, 01, 03, 02,
- 04, 07, 06, 05, 06, 07, 04, 05, 00, 03, 03, 00, 02, 03, 01, 00,
- 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04,
- 04, 07, 06, 05, 06, 07, 04, 05, 04, 07, 07, 04, 06, 07, 05, 04,
- 01, 02, 03, 00, 02, 03, 00, 01, 01, 02, 02, 01, 02, 03, 01, 00
-};
-
-/********************** the table above has been generated with this code: ********
-#include "util.h"
-static void init_opt_select_LUT(void) {
- for (int r = 0; r < 256; r++) {
- uint8_t r_ls2 = r << 2;
- uint8_t r_and_ls2 = r & r_ls2;
- uint8_t r_or_ls2 = r | r_ls2;
- uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
- uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r;
- uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r;
- opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1);
- }
- print_result("", opt_select_LUT, 256);
-}
-***********************************************************************************/
-
-#define opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\
- |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\
- |(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x))
-
-/*
- * Some background on the expression above can be found here...
-uint8_t xopt__select(bool x, bool y, uint8_t r)
-{
-
- //r: r0 r1 r2 r3 r4 r5 r6 r7
- //r_ls2: r2 r3 r4 r5 r6 r7 0 0
- // z0
- // z1
-
-// uint8_t z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4); // <-- original
- uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
-
-// uint8_t z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y; // <-- original
- uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1);
-
-// uint8_t z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x; // <-- original
- uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r ^ x;
-
- return (z0 & 4) | (z1 & 2) | (z2 & 1);
-}
-*/
-
-static void opt_successor(const uint8_t *k, State *s, uint8_t y) {
-// #define opt_T(s) (0x1 & ((s->t >> 15) ^ (s->t >> 14) ^ (s->t >> 10) ^ (s->t >> 8) ^ (s->t >> 5) ^ (s->t >> 4)^ (s->t >> 1) ^ s->t))
- // uint8_t Tt = opt_T(s);
- uint16_t Tt = s->t & 0xc533;
- Tt = Tt ^ (Tt >> 1);
- Tt = Tt ^ (Tt >> 4);
- Tt = Tt ^ (Tt >> 10);
- Tt = Tt ^ (Tt >> 8);
-
- s->t = (s->t >> 1);
- s->t |= (Tt ^ (s->r >> 7) ^ (s->r >> 3)) << 15;
-
- uint8_t opt_B = s->b;
- opt_B ^= s->b >> 6;
- opt_B ^= s->b >> 5;
- opt_B ^= s->b >> 4;
-
- s->b = s->b >> 1;
- s->b |= (opt_B ^ s->r) << 7;
-
- uint8_t opt_select = opt_select_LUT[s->r] & 0x04;
- opt_select |= (opt_select_LUT[s->r] ^ ((Tt ^ y) << 1)) & 0x02;
- opt_select |= (opt_select_LUT[s->r] ^ Tt) & 0x01;
-
- uint8_t r = s->r;
- s->r = (k[opt_select] ^ s->b) + s->l ;
- s->l = s->r + r;
-}
-
-static void opt_suc(const uint8_t *k, State *s, uint8_t *in, uint8_t length, bool add32Zeroes) {
- for (int i = 0; i < length; i++) {
- uint8_t head;
- head = in[i];
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
-
- head >>= 1;
- opt_successor(k, s, head);
- }
- //For tag MAC, an additional 32 zeroes
- if (add32Zeroes) {
- for (int i = 0; i < 16; i++) {
- opt_successor(k, s, 0);
- opt_successor(k, s, 0);
- }
- }
-}
-
-static void opt_output(const uint8_t *k, State *s, uint8_t *buffer) {
- for (uint8_t times = 0; times < 4; times++) {
- uint8_t bout = 0;
- bout |= (s->r & 0x4) >> 2;
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4) >> 1;
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4);
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4) << 1;
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4) << 2;
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4) << 3;
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4) << 4;
- opt_successor(k, s, 0);
- bout |= (s->r & 0x4) << 5;
- opt_successor(k, s, 0);
- buffer[times] = bout;
- }
-}
-
-static void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) {
- State _init = {
- ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
- ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
- 0x4c, // b
- 0xE012 // t
- };
-
- opt_suc(k, &_init, input, 12, false);
- opt_output(k, &_init, out);
-}
-
-void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
- uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
- opt_MAC(div_key_p, cc_nr_p, dest);
- memcpy(mac, dest, 4);
- return;
-}
-
-void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
- State _init = {
- ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
- ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
- 0x4c, // b
- 0xE012 // t
- };
- opt_suc(div_key_p, &_init, cc_p, 12, true);
- opt_output(div_key_p, &_init, mac);
- return;
-}
-
-/**
- * The tag MAC can be divided (both can, but no point in dividing the reader mac) into
- * two functions, since the first 8 bytes are known, we can pre-calculate the state
- * reached after feeding CC to the cipher.
- * @param cc_p
- * @param div_key_p
- * @return the cipher state
- */
-State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
- State _init = {
- ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
- ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
- 0x4c, // b
- 0xE012 // t
- };
- opt_suc(div_key_p, &_init, cc_p, 8, false);
- return _init;
-}
-
-/**
- * The second part of the tag MAC calculation, since the CC is already calculated into the state,
- * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag
- * MAC response.
- * @param _init - precalculated cipher state
- * @param nr - the reader challenge
- * @param mac - where to store the MAC
- * @param div_key_p - the key to use
- */
-void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) {
- opt_suc(div_key_p, &_init, nr, 4, true);
- opt_output(div_key_p, &_init, mac);
- return;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/optimized_cipher.h b/pm3rdv4rrg/src/main/cpp/armsrc/optimized_cipher.h
deleted file mode 100644
index c6df25ab..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/optimized_cipher.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef OPTIMIZED_CIPHER_H
-#define OPTIMIZED_CIPHER_H
-
-#include "common.h"
-#include "string.h"
-/**
-* Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2
-* consisting of the following four components:
-* 1. the left register l = (l 0 . . . l 7 ) ∈ F 8/2 ;
-* 2. the right register r = (r 0 . . . r 7 ) ∈ F 8/2 ;
-* 3. the top register t = (t 0 . . . t 15 ) ∈ F 16/2 .
-* 4. the bottom register b = (b 0 . . . b 7 ) ∈ F 8/2 .
-**/
-typedef struct {
- uint8_t l;
- uint8_t r;
- uint8_t b;
- uint16_t t;
-} State;
-
-/** The reader MAC is MAC(key, CC * NR )
- **/
-void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
-/**
- * The tag MAC is MAC(key, CC * NR * 32x0))
- */
-void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]);
-
-/**
- * The tag MAC can be divided (both can, but no point in dividing the reader mac) into
- * two functions, since the first 8 bytes are known, we can pre-calculate the state
- * reached after feeding CC to the cipher.
- * @param cc_p
- * @param div_key_p
- * @return the cipher state
- */
-State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p);
-/**
- * The second part of the tag MAC calculation, since the CC is already calculated into the state,
- * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag
- * MAC response.
- * @param _init - precalculated cipher state
- * @param nr - the reader challenge
- * @param mac - where to store the MAC
- * @param div_key_p - the key to use
- */
-void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
-
-#endif // OPTIMIZED_CIPHER_H
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/pcf7931.c b/pm3rdv4rrg/src/main/cpp/armsrc/pcf7931.c
deleted file mode 100644
index 21a739f4..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/pcf7931.c
+++ /dev/null
@@ -1,564 +0,0 @@
-#include "pcf7931.h"
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "BigBuf.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-#include "lfsampling.h"
-#include "string.h"
-
-#define T0_PCF 8 //period for the pcf7931 in us
-#define ALLOC 16
-
-size_t DemodPCF7931(uint8_t **outBlocks) {
- uint8_t bits[256] = {0x00};
- uint8_t blocks[8][16];
- uint8_t *dest = BigBuf_get_addr();
-
- int GraphTraceLen = BigBuf_max_traceLen();
- if (GraphTraceLen > 18000)
- GraphTraceLen = 18000;
-
- int i = 2, j, lastval, bitidx, half_switch;
- int clock = 64;
- int tolerance = clock / 8;
- int pmc, block_done;
- int lc, warnings = 0;
- size_t num_blocks = 0;
- int lmin = 64, lmax = 192;
- uint8_t dir;
-
- BigBuf_Clear_keep_EM();
- LFSetupFPGAForADC(LF_DIVISOR_125, true);
- DoAcquisition_default(0, true);
-
- /* Find first local max/min */
- if (dest[1] > dest[0]) {
- while (i < GraphTraceLen) {
- if (!(dest[i] > dest[i - 1]) && dest[i] > lmax)
- break;
- i++;
- }
- dir = 0;
- } else {
- while (i < GraphTraceLen) {
- if (!(dest[i] < dest[i - 1]) && dest[i] < lmin)
- break;
- i++;
- }
- dir = 1;
- }
-
- lastval = i++;
- half_switch = 0;
- pmc = 0;
- block_done = 0;
-
- for (bitidx = 0; i < GraphTraceLen; i++) {
- if ((dest[i - 1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i - 1] < dest[i] && dir == 0 && dest[i] < lmin)) {
- lc = i - lastval;
- lastval = i;
-
- // Switch depending on lc length:
- // Tolerance is 1/8 of clock rate (arbitrary)
- if (ABS(lc - clock / 4) < tolerance) {
- // 16T0
- if ((i - pmc) == lc) { /* 16T0 was previous one */
- /* It's a PMC ! */
- i += (128 + 127 + 16 + 32 + 33 + 16) - 1;
- lastval = i;
- pmc = 0;
- block_done = 1;
- } else {
- pmc = i;
- }
- } else if (ABS(lc - clock / 2) < tolerance) {
- // 32TO
- if ((i - pmc) == lc) { /* 16T0 was previous one */
- /* It's a PMC ! */
- i += (128 + 127 + 16 + 32 + 33) - 1;
- lastval = i;
- pmc = 0;
- block_done = 1;
- } else if (half_switch == 1) {
- bits[bitidx++] = 0;
- half_switch = 0;
- } else
- half_switch++;
- } else if (ABS(lc - clock) < tolerance) {
- // 64TO
- bits[bitidx++] = 1;
- } else {
- // Error
- if (++warnings > 10) {
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Error: too many detection errors, aborting.");
-
- return 0;
- }
- }
-
- if (block_done == 1) {
- if (bitidx == 128) {
- for (j = 0; j < 16; ++j) {
- blocks[num_blocks][j] =
- 128 * bits[j * 8 + 7] +
- 64 * bits[j * 8 + 6] +
- 32 * bits[j * 8 + 5] +
- 16 * bits[j * 8 + 4] +
- 8 * bits[j * 8 + 3] +
- 4 * bits[j * 8 + 2] +
- 2 * bits[j * 8 + 1] +
- bits[j * 8]
- ;
- }
- num_blocks++;
- }
- bitidx = 0;
- block_done = 0;
- half_switch = 0;
- }
- if (i < GraphTraceLen)
- dir = (dest[i - 1] > dest[i]) ? 0 : 1;
- }
- if (bitidx == 255)
- bitidx = 0;
- warnings = 0;
- if (num_blocks == 4) break;
- }
- memcpy(outBlocks, blocks, 16 * num_blocks);
- return num_blocks;
-}
-
-bool IsBlock0PCF7931(uint8_t *block) {
- // assuming all RFU bits are set to 0
- // if PAC is enabled password is set to 0
- if (block[7] == 0x01) {
- if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7)
- && !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) {
- return true;
- }
- } else if (block[7] == 0x00) {
- if (!memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) {
- return true;
- }
- }
- return false;
-}
-
-bool IsBlock1PCF7931(uint8_t *block) {
- // assuming all RFU bits are set to 0
-
- uint8_t rb1 = block[14] & 0x80;
- uint8_t rfb = block[14] & 0x7f;
- uint8_t rlb = block[15];
-
- if (block[10] == 0
- && block[11] == 0
- && block[12] == 0
- && block[13] == 0) {
- // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled
- if (rfb <= rlb
- && rfb <= 9
- && rlb <= 9
- && ((rfb <= 1 && rlb >= 1) || rb1)) {
- return true;
- }
- }
-
- return false;
-}
-
-void ReadPCF7931() {
- int found_blocks = 0; // successfully read blocks
- int max_blocks = 8; // readable blocks
- uint8_t memory_blocks[8][17]; // PCF content
- uint8_t single_blocks[8][17]; // PFC blocks with unknown position
- int single_blocks_cnt = 0;
-
- size_t n = 0; // transmitted blocks
- uint8_t tmp_blocks[4][16]; // temporary read buffer
-
- uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
- int errors = 0; // error counter
- int tries = 0; // tries counter
-
- memset(memory_blocks, 0, 8 * 17 * sizeof(uint8_t));
- memset(single_blocks, 0, 8 * 17 * sizeof(uint8_t));
-
- int i = 0, j = 0;
-
- do {
- i = 0;
-
- memset(tmp_blocks, 0, 4 * 16 * sizeof(uint8_t));
- n = DemodPCF7931((uint8_t **)tmp_blocks);
- if (!n)
- ++errors;
-
- // exit if no block is received
- if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) {
-
- if (DBGLEVEL >= DBG_INFO)
- Dbprintf("[!!] Error, no tag or bad tag");
-
- return;
- }
- // exit if too many errors during reading
- if (tries > 50 && (2 * errors > tries)) {
-
- if (DBGLEVEL >= DBG_INFO)
- Dbprintf("[!!] Error reading the tag, only partial content");
-
- goto end;
- }
-
- // our logic breaks if we don't get at least two blocks
- if (n < 2) {
- // skip if all 0s block or no blocks
- if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
- continue;
-
- // add block to single blocks list
- if (single_blocks_cnt < max_blocks) {
- for (i = 0; i < single_blocks_cnt; ++i) {
- if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
- j = 1;
- break;
- }
- }
- if (j != 1) {
- memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
- print_result("got single block", single_blocks[single_blocks_cnt], 16);
- single_blocks_cnt++;
- }
- j = 0;
- }
- ++tries;
- continue;
- }
-
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
-
- for (i = 0; i < n; ++i) {
- print_result("got consecutive blocks", tmp_blocks[i], 16);
- }
-
- i = 0;
- if (!found_0_1) {
- while (i < n - 1) {
- if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i + 1])) {
- found_0_1 = 1;
- memcpy(memory_blocks[0], tmp_blocks[i], 16);
- memcpy(memory_blocks[1], tmp_blocks[i + 1], 16);
- memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
- // block 1 tells how many blocks are going to be sent
- max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
- found_blocks = 2;
-
- Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks);
-
- // handle the following blocks
- for (j = i + 2; j < n; ++j) {
- memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16);
- memory_blocks[found_blocks][ALLOC] = 1;
- ++found_blocks;
- }
- break;
- }
- ++i;
- }
- } else {
- // Trying to re-order blocks
- // Look for identical block in memory blocks
- while (i < n - 1) {
- // skip all zeroes blocks
- if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
- for (j = 1; j < max_blocks - 1; ++j) {
- if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j + 1][ALLOC]) {
- memcpy(memory_blocks[j + 1], tmp_blocks[i + 1], 16);
- memory_blocks[j + 1][ALLOC] = 1;
- if (++found_blocks >= max_blocks) goto end;
- }
- }
- }
- if (memcmp(tmp_blocks[i + 1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
- for (j = 0; j < max_blocks; ++j) {
- if (!memcmp(tmp_blocks[i + 1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) - 1][ALLOC]) {
- if (j == 0) {
- memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16);
- memory_blocks[max_blocks - 1][ALLOC] = 1;
- } else {
- memcpy(memory_blocks[j - 1], tmp_blocks[i], 16);
- memory_blocks[j - 1][ALLOC] = 1;
- }
- if (++found_blocks >= max_blocks) goto end;
- }
- }
- }
- ++i;
- }
- }
- ++tries;
- if (BUTTON_PRESS()) {
- if (DBGLEVEL >= DBG_EXTENDED)
- Dbprintf("Button pressed, stopping.");
-
- goto end;
- }
- } while (found_blocks < max_blocks);
-
-end:
- Dbprintf("-----------------------------------------");
- Dbprintf("Memory content:");
- Dbprintf("-----------------------------------------");
- for (i = 0; i < max_blocks; ++i) {
- if (memory_blocks[i][ALLOC])
- print_result("Block", memory_blocks[i], 16);
- else
- Dbprintf("", i);
- }
- Dbprintf("-----------------------------------------");
-
- if (found_blocks < max_blocks) {
- Dbprintf("-----------------------------------------");
- Dbprintf("Blocks with unknown position:");
- Dbprintf("-----------------------------------------");
- for (i = 0; i < single_blocks_cnt; ++i)
- print_result("Block", single_blocks[i], 16);
-
- Dbprintf("-----------------------------------------");
- }
- reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
-}
-
-static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
- uint32_t tab[1024] = {0}; // data times frame
- uint32_t u = 0;
- uint8_t parity = 0;
- bool comp = 0;
-
- //BUILD OF THE DATA FRAME
- //alimentation of the tag (time for initializing)
- AddPatternPCF7931(init_delay, 0, 8192 / 2 * T0_PCF, tab);
- AddPatternPCF7931(8192 / 2 * T0_PCF + 319 * T0_PCF + 70, 3 * T0_PCF, 29 * T0_PCF, tab);
- //password indication bit
- AddBitPCF7931(1, tab, l, p);
- //password (on 56 bits)
- AddBytePCF7931(pass[0], tab, l, p);
- AddBytePCF7931(pass[1], tab, l, p);
- AddBytePCF7931(pass[2], tab, l, p);
- AddBytePCF7931(pass[3], tab, l, p);
- AddBytePCF7931(pass[4], tab, l, p);
- AddBytePCF7931(pass[5], tab, l, p);
- AddBytePCF7931(pass[6], tab, l, p);
- //programming mode (0 or 1)
- AddBitPCF7931(0, tab, l, p);
-
- //block adress on 6 bits
- for (u = 0; u < 6; ++u) {
- if (address & (1 << u)) { // bit 1
- ++parity;
- AddBitPCF7931(1, tab, l, p);
- } else { // bit 0
- AddBitPCF7931(0, tab, l, p);
- }
- }
-
- //byte address on 4 bits
- for (u = 0; u < 4; ++u) {
- if (byte & (1 << u)) { // bit 1
- parity++;
- AddBitPCF7931(1, tab, l, p);
- } else // bit 0
- AddBitPCF7931(0, tab, l, p);
- }
-
- //data on 8 bits
- for (u = 0; u < 8; u++) {
- if (data & (1 << u)) { // bit 1
- parity++;
- AddBitPCF7931(1, tab, l, p);
- } else //bit 0
- AddBitPCF7931(0, tab, l, p);
- }
-
- //parity bit
- if ((parity % 2) == 0)
- AddBitPCF7931(0, tab, l, p); //even parity
- else
- AddBitPCF7931(1, tab, l, p);//odd parity
-
- //time access memory
- AddPatternPCF7931(5120 + 2680, 0, 0, tab);
-
- //conversion of the scale time
- for (u = 0; u < 500; ++u)
- tab[u] = (tab[u] * 3) / 2;
-
- //compensation of the counter reload
- while (!comp) {
- comp = 1;
- for (u = 0; tab[u] != 0; ++u)
- if (tab[u] > 0xFFFF) {
- tab[u] -= 0xFFFF;
- comp = 0;
- }
- }
-
- SendCmdPCF7931(tab);
-}
-
-/* Write on a byte of a PCF7931 tag
- * @param address : address of the block to write
- @param byte : address of the byte to write
- @param data : data to write
- */
-void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
-
- if (DBGLEVEL >= DBG_INFO) {
- Dbprintf("Initialization delay : %d us", init_delay);
- Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
- }
-
- Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7);
- Dbprintf("Block address : %02x", address);
- Dbprintf("Byte address : %02x", byte);
- Dbprintf("Data : %02x", data);
-
- uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7};
-
- RealWritePCF7931(password, init_delay, l, p, address, byte, data);
-}
-
-
-/* Send a trame to a PCF7931 tags
- * @param tab : array of the data frame
- */
-
-void SendCmdPCF7931(uint32_t *tab) {
- uint16_t u = 0, tempo = 0;
-
- if (DBGLEVEL >= DBG_INFO) {
- Dbprintf("Sending data frame...");
- }
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
-
- LED_A_ON();
-
- // steal this pin from the SSP and use it to control the modulation
- AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
-
- //initialization of the timer
- AT91C_BASE_PMC->PMC_PCER |= (0x1 << AT91C_ID_TC0);
- AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
- AT91C_BASE_TCB->TCB_BCR = 1;
-
- tempo = AT91C_BASE_TC0->TC_CV;
- for (u = 0; tab[u] != 0; u += 3) {
- // modulate antenna
- HIGH(GPIO_SSC_DOUT);
- while (tempo != tab[u])
- tempo = AT91C_BASE_TC0->TC_CV;
-
- // stop modulating antenna
- LOW(GPIO_SSC_DOUT);
- while (tempo != tab[u + 1])
- tempo = AT91C_BASE_TC0->TC_CV;
-
- // modulate antenna
- HIGH(GPIO_SSC_DOUT);
- while (tempo != tab[u + 2])
- tempo = AT91C_BASE_TC0->TC_CV;
- }
-
- LED_A_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(200);
-
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
-}
-
-
-/* Add a byte for building the data frame of PCF7931 tags
- * @param b : byte to add
- * @param tab : array of the data frame
- * @param l : offset on low pulse width
- * @param p : offset on low pulse positioning
- */
-bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p) {
- uint32_t u;
- for (u = 0; u < 8; ++u) {
- if (byte & (1 << u)) { //bit is 1
- if (AddBitPCF7931(1, tab, l, p) == 1) return true;
- } else { //bit is 0
- if (AddBitPCF7931(0, tab, l, p) == 1) return true;
- }
- }
-
- return false;
-}
-
-/* Add a bits for building the data frame of PCF7931 tags
- * @param b : bit to add
- * @param tab : array of the data frame
- * @param l : offset on low pulse width
- * @param p : offset on low pulse positioning
- */
-bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p) {
- uint8_t u = 0;
-
- //we put the cursor at the last value of the array
- for (u = 0; tab[u] != 0; u += 3) { };
-
- if (b == 1) { //add a bit 1
- if (u == 0)
- tab[u] = 34 * T0_PCF + p;
- else
- tab[u] = 34 * T0_PCF + tab[u - 1] + p;
-
- tab[u + 1] = 6 * T0_PCF + tab[u] + l;
- tab[u + 2] = 88 * T0_PCF + tab[u + 1] - l - p;
- return false;
- } else { //add a bit 0
-
- if (u == 0)
- tab[u] = 98 * T0_PCF + p;
- else
- tab[u] = 98 * T0_PCF + tab[u - 1] + p;
-
- tab[u + 1] = 6 * T0_PCF + tab[u] + l;
- tab[u + 2] = 24 * T0_PCF + tab[u + 1] - l - p;
- return false;
- }
- return true;
-}
-
-/* Add a custom pattern in the data frame
- * @param a : delay of the first high pulse
- * @param b : delay of the low pulse
- * @param c : delay of the last high pulse
- * @param tab : array of the data frame
- */
-bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab) {
- uint32_t u = 0;
- for (u = 0; tab[u] != 0; u += 3) {} //we put the cursor at the last value of the array
-
- tab[u] = (u == 0) ? a : a + tab[u - 1];
- tab[u + 1] = b + tab[u];
- tab[u + 2] = c + tab[u + 1];
-
- return true;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/pcf7931.h b/pm3rdv4rrg/src/main/cpp/armsrc/pcf7931.h
deleted file mode 100644
index 67a11f5f..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/pcf7931.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __PCF7931_H
-#define __PCF7931_H
-
-#include "common.h"
-
-size_t DemodPCF7931(uint8_t **outBlocks);
-bool IsBlock0PCF7931(uint8_t *block);
-bool IsBlock1PCF7931(uint8_t *block);
-void ReadPCF7931();
-void SendCmdPCF7931(uint32_t *tab);
-bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p);
-bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p);
-bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab);
-void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/printf.c b/pm3rdv4rrg/src/main/cpp/armsrc/printf.c
deleted file mode 100644
index 0dffbb03..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/printf.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*-
- * Copyright (c) 1986, 1988, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
- */
-#include "printf.h"
-
-#include "string.h"
-
-typedef unsigned char u_char;
-typedef unsigned int u_int;
-typedef unsigned long long u_quad_t;
-typedef long long quad_t;
-typedef unsigned long u_long;
-typedef unsigned short u_short;
-typedef int ssize_t;
-
-#define NBBY 8 /* number of bits in a byte */
-
-char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-#define hex2ascii(hex) (hex2ascii_data[hex])
-#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
-
-/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
-#define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
-
-/*
- * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
- * order; return an optional length and a pointer to the last character
- * written in the buffer (i.e., the first character of the string).
- * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
- */
-static char *
-ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) {
- char *p = nbuf;
- *p = '\0';
- do {
- char c = hex2ascii(num % base);
- *++p = upper ? toupper(c) : c;
- } while (num /= base);
- if (lenp)
- *lenp = p - nbuf;
- return (p);
-}
-
-/*
- * Scaled down version of printf(3).
- *
- * Two additional formats:
- *
- * The format %b is supported to decode error registers.
- * Its usage is:
- *
- * printf("reg=%b\n", regval, "*");
- *
- * where is the output base expressed as a control character, e.g.
- * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
- * the first of which gives the bit number to be inspected (origin 1), and
- * the next characters (up to a control character, i.e. a character <= 32),
- * give the name of the register. Thus:
- *
- * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
- *
- * would produce output:
- *
- * reg=3
- *
- * XXX: %D -- Hexdump, takes pointer and separator string:
- * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
- * ("%*D", len, ptr, " " -> XX XX XX XX ...
- */
-int
-kvsprintf(char const *fmt, void *arg, int radix, va_list ap) {
-#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
- char nbuf[MAXNBUF];
- char *d;
- const char *p, *percent, *q;
- u_char *up;
- int ch, n;
- uintmax_t num;
- int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
- int cflag, hflag, jflag, tflag, zflag;
- int dwidth, upper;
- char padc;
- int stop = 0, retval = 0;
-
- num = 0;
- d = (char *) arg;
-
- if (fmt == NULL)
- fmt = "(fmt null)\n";
-
- if (radix < 2 || radix > 36)
- radix = 10;
-
- for (;;) {
- padc = ' ';
- width = 0;
- while ((ch = (u_char) * fmt++) != '%' || stop) {
- PCHAR(ch);
- if (ch == '\0')
- return (retval);
- }
- percent = fmt - 1;
- qflag = 0;
- lflag = 0;
- ladjust = 0;
- sharpflag = 0;
- neg = 0;
- sign = 0;
- dot = 0;
- dwidth = 0;
- upper = 0;
- cflag = 0;
- hflag = 0;
- jflag = 0;
- tflag = 0;
- zflag = 0;
-reswitch:
- switch (ch = (u_char) * fmt++) {
- case '.':
- dot = 1;
- goto reswitch;
- case '#':
- sharpflag = 1;
- goto reswitch;
- case '+':
- sign = 1;
- goto reswitch;
- case '-':
- ladjust = 1;
- goto reswitch;
- case '%':
- PCHAR(ch);
- break;
- case '*':
- if (!dot) {
- width = va_arg(ap, int);
- if (width < 0) {
- ladjust = !ladjust;
- width = -width;
- }
- } else {
- dwidth = va_arg(ap, int);
- }
- goto reswitch;
- case '0':
- if (!dot) {
- padc = '0';
- goto reswitch;
- }
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- for (n = 0;; ++fmt) {
- n = n * 10 + ch - '0';
- ch = *fmt;
- if (ch < '0' || ch > '9')
- break;
- }
- if (dot)
- dwidth = n;
- else
- width = n;
- goto reswitch;
- case 'b':
- num = (u_int)va_arg(ap, int);
- p = va_arg(ap, char *);
- for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
- PCHAR(*q--);
-
- if (num == 0)
- break;
-
- for (tmp = 0; *p;) {
- n = *p++;
- if (num & (1 << (n - 1))) {
- PCHAR(tmp ? ',' : '<');
- for (; (n = *p) > ' '; ++p)
- PCHAR(n);
- tmp = 1;
- } else
- for (; *p > ' '; ++p)
- continue;
- }
- if (tmp)
- PCHAR('>');
- break;
- case 'c':
- PCHAR(va_arg(ap, int));
- break;
- case 'D':
- up = va_arg(ap, u_char *);
- p = va_arg(ap, char *);
- if (!width)
- width = 16;
- while (width--) {
- PCHAR(hex2ascii(*up >> 4));
- PCHAR(hex2ascii(*up & 0x0f));
- up++;
- if (width)
- for (q = p; *q; q++)
- PCHAR(*q);
- }
- break;
- case 'd':
- case 'i':
- base = 10;
- sign = 1;
- goto handle_sign;
- case 'h':
- if (hflag) {
- hflag = 0;
- cflag = 1;
- } else
- hflag = 1;
- goto reswitch;
- case 'j':
- jflag = 1;
- goto reswitch;
- case 'l':
- if (lflag) {
- lflag = 0;
- qflag = 1;
- } else
- lflag = 1;
- goto reswitch;
- case 'n':
- if (jflag)
- *(va_arg(ap, intmax_t *)) = retval;
- else if (qflag)
- *(va_arg(ap, quad_t *)) = retval;
- else if (lflag)
- *(va_arg(ap, long *)) = retval;
- else if (zflag)
- *(va_arg(ap, size_t *)) = retval;
- else if (hflag)
- *(va_arg(ap, short *)) = retval;
- else if (cflag)
- *(va_arg(ap, char *)) = retval;
- else
- *(va_arg(ap, int *)) = retval;
- break;
- case 'o':
- base = 8;
- goto handle_nosign;
- case 'p':
- base = 16;
- sharpflag = (width == 0);
- sign = 0;
- num = (uintptr_t)va_arg(ap, void *);
- goto number;
- case 'q':
- qflag = 1;
- goto reswitch;
- case 'r':
- base = radix;
- if (sign)
- goto handle_sign;
- goto handle_nosign;
- case 's':
- p = va_arg(ap, char *);
- if (p == NULL)
- p = "(null)";
- if (!dot)
- n = strlen(p);
- else
- for (n = 0; n < dwidth && p[n]; n++)
- continue;
-
- width -= n;
-
- if (!ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- while (n--)
- PCHAR(*p++);
- if (ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- break;
- case 't':
- tflag = 1;
- goto reswitch;
- case 'u':
- base = 10;
- goto handle_nosign;
- case 'X':
- upper = 1;
- case 'x':
- base = 16;
- goto handle_nosign;
- case 'y':
- base = 16;
- sign = 1;
- goto handle_sign;
- case 'z':
- zflag = 1;
- goto reswitch;
-handle_nosign:
- sign = 0;
- if (jflag)
- num = va_arg(ap, uintmax_t);
- else if (qflag)
- num = va_arg(ap, u_quad_t);
- else if (tflag)
- num = va_arg(ap, ptrdiff_t);
- else if (lflag)
- num = va_arg(ap, u_long);
- else if (zflag)
- num = va_arg(ap, size_t);
- else if (hflag)
- num = (u_short)va_arg(ap, int);
- else if (cflag)
- num = (u_char)va_arg(ap, int);
- else
- num = va_arg(ap, u_int);
- goto number;
-handle_sign:
- if (jflag)
- num = va_arg(ap, intmax_t);
- else if (qflag)
- num = va_arg(ap, quad_t);
- else if (tflag)
- num = va_arg(ap, ptrdiff_t);
- else if (lflag)
- num = va_arg(ap, long);
- else if (zflag)
- num = va_arg(ap, ssize_t);
- else if (hflag)
- num = (short)va_arg(ap, int);
- else if (cflag)
- num = (char)va_arg(ap, int);
- else
- num = va_arg(ap, int);
-number:
- if (sign && (intmax_t)num < 0) {
- neg = 1;
- num = -(intmax_t)num;
- }
- p = ksprintn(nbuf, num, base, &tmp, upper);
- if (sharpflag && num != 0) {
- if (base == 8)
- tmp++;
- else if (base == 16)
- tmp += 2;
- }
- if (neg)
- tmp++;
-
- if (!ladjust && padc != '0' && width
- && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
- if (neg)
- PCHAR('-');
- if (sharpflag && num != 0) {
- if (base == 8) {
- PCHAR('0');
- } else if (base == 16) {
- PCHAR('0');
- PCHAR('x');
- }
- }
- if (!ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
-
- while (*p)
- PCHAR(*p--);
-
- if (ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
-
- break;
- default:
- while (percent < fmt)
- PCHAR(*percent++);
- /*
- * Since we ignore an formatting argument it is no
- * longer safe to obey the remaining formatting
- * arguments as the arguments will no longer match
- * the format specs.
- */
- stop = 1;
- break;
- }
- }
- PCHAR(0);
- return retval;
-#undef PCHAR
-}
-
-int vsprintf(char *dest, const char *fmt, va_list ap) {
- return kvsprintf(fmt, dest, 10, ap);
-}
-
-int
-sprintf(char *dest, const char *fmt, ...) {
- /* http://www.pagetable.com/?p=298 */
- int retval;
- va_list ap;
- va_start(ap, fmt);
- retval = kvsprintf(fmt, dest, 10, ap);
- va_end(ap);
- return retval;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/printf.h b/pm3rdv4rrg/src/main/cpp/armsrc/printf.h
deleted file mode 100644
index bd0a6e2c..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/printf.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2010 Hector Martin "marcan"
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Common *printf() functions
-//-----------------------------------------------------------------------------
-
-#ifndef __PRINTF_H
-#define __PRINTF_H
-
-#include "common.h"
-#include // va_list
-
-int kvsprintf(const char *fmt, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0)));
-int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0)));
-int sprintf(char *dest, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/radixsort.c b/pm3rdv4rrg/src/main/cpp/armsrc/radixsort.c
deleted file mode 100644
index 83b26d60..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/radixsort.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include "radixsort.h"
-
-uint64_t *radixSort(uint64_t *array, uint32_t size) {
- rscounts_t counts;
- memset(&counts, 0, 256 * 8 * sizeof(uint32_t));
- uint64_t *cpy = (uint64_t *)calloc(size * sizeof(uint64_t), sizeof(uint8_t));
- uint32_t o8 = 0, o7 = 0, o6 = 0, o5 = 0, o4 = 0, o3 = 0, o2 = 0, o1 = 0;
- uint32_t t8, t7, t6, t5, t4, t3, t2, t1;
- uint32_t x;
- // calculate counts
- for (x = 0; x < size; ++x) {
- t8 = array[x] & 0xff;
- t7 = (array[x] >> 8) & 0xff;
- t6 = (array[x] >> 16) & 0xff;
- t5 = (array[x] >> 24) & 0xff;
- t4 = (array[x] >> 32) & 0xff;
- t3 = (array[x] >> 40) & 0xff;
- t2 = (array[x] >> 48) & 0xff;
- t1 = (array[x] >> 56) & 0xff;
- counts.c8[t8]++;
- counts.c7[t7]++;
- counts.c6[t6]++;
- counts.c5[t5]++;
- counts.c4[t4]++;
- counts.c3[t3]++;
- counts.c2[t2]++;
- counts.c1[t1]++;
- }
- // convert counts to offsets
- for (x = 0; x < 256; ++x) {
- t8 = o8 + counts.c8[x];
- t7 = o7 + counts.c7[x];
- t6 = o6 + counts.c6[x];
- t5 = o5 + counts.c5[x];
- t4 = o4 + counts.c4[x];
- t3 = o3 + counts.c3[x];
- t2 = o2 + counts.c2[x];
- t1 = o1 + counts.c1[x];
- counts.c8[x] = o8;
- counts.c7[x] = o7;
- counts.c6[x] = o6;
- counts.c5[x] = o5;
- counts.c4[x] = o4;
- counts.c3[x] = o3;
- counts.c2[x] = o2;
- counts.c1[x] = o1;
- o8 = t8;
- o7 = t7;
- o6 = t6;
- o5 = t5;
- o4 = t4;
- o3 = t3;
- o2 = t2;
- o1 = t1;
- }
- // radix
- for (x = 0; x < size; ++x) {
- t8 = array[x] & 0xff;
- cpy[counts.c8[t8]] = array[x];
- counts.c8[t8]++;
- }
- for (x = 0; x < size; ++x) {
- t7 = (cpy[x] >> 8) & 0xff;
- array[counts.c7[t7]] = cpy[x];
- counts.c7[t7]++;
- }
- for (x = 0; x < size; ++x) {
- t6 = (array[x] >> 16) & 0xff;
- cpy[counts.c6[t6]] = array[x];
- counts.c6[t6]++;
- }
- for (x = 0; x < size; ++x) {
- t5 = (cpy[x] >> 24) & 0xff;
- array[counts.c5[t5]] = cpy[x];
- counts.c5[t5]++;
- }
- for (x = 0; x < size; ++x) {
- t4 = (array[x] >> 32) & 0xff;
- cpy[counts.c4[t4]] = array[x];
- counts.c4[t4]++;
- }
- for (x = 0; x < size; ++x) {
- t3 = (cpy[x] >> 40) & 0xff;
- array[counts.c3[t3]] = cpy[x];
- counts.c3[t3]++;
- }
- for (x = 0; x < size; ++x) {
- t2 = (array[x] >> 48) & 0xff;
- cpy[counts.c2[t2]] = array[x];
- counts.c2[t2]++;
- }
- for (x = 0; x < size; ++x) {
- t1 = (cpy[x] >> 56) & 0xff;
- array[counts.c1[t1]] = cpy[x];
- counts.c1[t1]++;
- }
- free(cpy);
- return array;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/radixsort.h b/pm3rdv4rrg/src/main/cpp/armsrc/radixsort.h
deleted file mode 100644
index fb2bcc04..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/radixsort.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef RADIXSORT_H__
-#define RADIXSORT_H__
-
-#include "common.h"
-
-typedef union {
- struct {
- uint32_t c8[256];
- uint32_t c7[256];
- uint32_t c6[256];
- uint32_t c5[256];
- uint32_t c4[256];
- uint32_t c3[256];
- uint32_t c2[256];
- uint32_t c1[256];
- };
- uint32_t counts[256 * 8];
-} rscounts_t;
-
-uint64_t *radixSort(uint64_t *array, uint32_t size);
-
-#endif // RADIXSORT_H__
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs.c b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs.c
deleted file mode 100644
index 6aed8038..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs.c
+++ /dev/null
@@ -1,641 +0,0 @@
-//-----------------------------------------------------------------------------
-// Colin J. Brigato, 2019 - [colin@brigato.fr]
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// SPIFFS api for RDV40 Integration by Colin Brigato
-//-----------------------------------------------------------------------------
-
-#define SPIFFS_CFG_PHYS_SZ (1024 * 128)
-#define SPIFFS_CFG_PHYS_ERASE_SZ (4 * 1024)
-#define SPIFFS_CFG_PHYS_ADDR (0)
-#define SPIFFS_CFG_LOG_PAGE_SZ (256)
-#define SPIFFS_CFG_LOG_BLOCK_SZ (4 * 1024)
-#define LOG_PAGE_SIZE 256
-#define RDV40_SPIFFS_WORKBUF_SZ (LOG_PAGE_SIZE * 2)
-// Experimental : 4 full pages(LOG_PAGE_SIZE + file descript size) of cache for
-// Reading and writing if reading cache is stable, writing cache may need more
-// testing regarding power loss, page consistency checks, Garbage collector
-// Flushing handling... in doubt, use maximal safetylevel as, in most of the
-// case, will ensure a flush by rollbacking to previous Unmounted state
-#define RDV40_SPIFFS_CACHE_SZ ((LOG_PAGE_SIZE + 32) * 4)
-#define SPIFFS_FD_SIZE (32)
-#define RDV40_SPIFFS_MAX_FD (3)
-#define RDV40_SPIFFS_FDBUF_SZ (SPIFFS_FD_SIZE * RDV40_SPIFFS_MAX_FD)
-
-#define RDV40_LLERASE_BLOCKSIZE (64*1024)
-
-#define RDV40_SPIFFS_LAZY_HEADER \
- int changed = 0; \
- if ((level == RDV40_SPIFFS_SAFETY_LAZY) || (level == RDV40_SPIFFS_SAFETY_SAFE)) { \
- changed = rdv40_spiffs_lazy_mount(); \
- }
-
-#define RDV40_SPIFFS_SAFE_FOOTER \
- if (level == RDV40_SPIFFS_SAFETY_SAFE) { \
- changed = rdv40_spiffs_lazy_mount_rollback(changed); \
- } \
- return changed;
-
-#define RDV40_SPIFFS_SAFE_FUNCTION(RDV40_SPIFFS_LLFUNCT) \
- RDV40_SPIFFS_LAZY_HEADER \
- RDV40_SPIFFS_LLFUNCT \
- RDV40_SPIFFS_SAFE_FOOTER
-
-#include "spiffs.h"
-#include "BigBuf.h"
-#include "dbprint.h"
-
-///// FLASH LEVEL R/W/E operations for feeding SPIFFS Driver/////////////////
-static s32_t rdv40_spiffs_llread(u32_t addr, u32_t size, u8_t *dst) {
-
- if (!Flash_ReadData(addr, dst, size)) {
- return 128;
- }
- return SPIFFS_OK;
-}
-
-static s32_t rdv40_spiffs_llwrite(u32_t addr, u32_t size, u8_t *src) {
-
- if (!FlashInit()) {
- return 129;
- }
- Flash_Write(addr, src, size);
- return SPIFFS_OK;
-}
-
-static s32_t rdv40_spiffs_llerase(u32_t addr, u32_t size) {
-
-
- uint8_t erased = 0;
-
- if (!FlashInit()) {
- return 130;
- }
- if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Orig addr : %d\n", addr);
- uint8_t block, sector = 0;
- block = addr / RDV40_LLERASE_BLOCKSIZE;
- if (block) {
- addr = addr - (block * RDV40_LLERASE_BLOCKSIZE);
- }
- if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : Result addr : %d\n", addr);
- sector = addr / SPIFFS_CFG_LOG_BLOCK_SZ;
- Flash_CheckBusy(BUSY_TIMEOUT);
- Flash_WriteEnable();
- if (DBGLEVEL > 2) Dbprintf("LLERASEDBG : block : %d, sector : %d \n", block, sector);
- erased = Flash_Erase4k(block, sector);
-
- Flash_CheckBusy(BUSY_TIMEOUT);
- FlashStop();
-
- return SPIFFS_OK == erased ;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-////// SPIFFS LOW LEVEL OPERATIONS /////////////////////////////////////////////
-static u8_t spiffs_work_buf[RDV40_SPIFFS_WORKBUF_SZ] __attribute__((aligned));
-static u8_t spiffs_fds[RDV40_SPIFFS_FDBUF_SZ] __attribute__((aligned));
-static u8_t spiffs_cache_buf[RDV40_SPIFFS_CACHE_SZ] __attribute__((aligned));
-
-static spiffs fs;
-
-static enum spiffs_mount_status {
- RDV40_SPIFFS_UNMOUNTED,
- RDV40_SPIFFS_MOUNTED,
- RDV40_SPIFFS_UNKNOWN
-} RDV40_SPIFFS_MOUNT_STATUS;
-
-int rdv40_spiffs_mounted() {
- int ret = 0;
-
- switch (RDV40_SPIFFS_MOUNT_STATUS) {
- case RDV40_SPIFFS_MOUNTED:
- ret = 1;
- break;
- case RDV40_SPIFFS_UNMOUNTED:
- case RDV40_SPIFFS_UNKNOWN:
- default:
- ret = 0;
- }
-
- return ret;
-}
-
-int rdv40_spiffs_mount() {
- if (rdv40_spiffs_mounted()) {
- Dbprintf("ERR: SPIFFS already mounted !");
- return SPIFFS_ERR_MOUNTED;
- }
-
- spiffs_config cfg;
- cfg.hal_read_f = rdv40_spiffs_llread;
- cfg.hal_write_f = rdv40_spiffs_llwrite;
- cfg.hal_erase_f = rdv40_spiffs_llerase;
-
- // uncached version
- // int ret = SPIFFS_mount(&fs, &cfg, spiffs_work_buf, spiffs_fds,
- // sizeof(spiffs_fds), 0, 0, 0); cached version, experimental
- int ret = SPIFFS_mount(&fs, &cfg, spiffs_work_buf, spiffs_fds, sizeof(spiffs_fds), spiffs_cache_buf,
- sizeof(spiffs_cache_buf), 0);
- if (ret == SPIFFS_OK) {
- RDV40_SPIFFS_MOUNT_STATUS = RDV40_SPIFFS_MOUNTED;
- }
- return ret;
-}
-
-int rdv40_spiffs_unmount() {
- if (!rdv40_spiffs_mounted()) {
- Dbprintf("ERR: SPIFFS not mounted !");
- return SPIFFS_ERR_NOT_MOUNTED;
- }
-
- SPIFFS_clearerr(&fs);
- SPIFFS_unmount(&fs);
-
- int ret = SPIFFS_errno(&fs);
- if (ret == SPIFFS_OK) {
- RDV40_SPIFFS_MOUNT_STATUS = RDV40_SPIFFS_UNMOUNTED;
- }
- return ret;
-}
-
-int rdv40_spiffs_check() {
- rdv40_spiffs_lazy_mount();
- SPIFFS_check(&fs);
- SPIFFS_gc_quick(&fs, 0);
- rdv40_spiffs_lazy_unmount();
- rdv40_spiffs_lazy_mount();
- return SPIFFS_gc(&fs, 8192) == SPIFFS_OK;
-}
-////////////////////////////////////////////////////////////////////////////////
-
-///// Base RDV40_SPIFFS_SAFETY_NORMAL operations////////////////////////////////
-
-void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size) {
- spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
- if (SPIFFS_write(&fs, fd, src, size) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
- SPIFFS_close(&fs, fd);
-}
-
-void append_to_spiffs(const char *filename, uint8_t *src, uint32_t size) {
- spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_APPEND | SPIFFS_RDWR, 0);
- if (SPIFFS_write(&fs, fd, src, size) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
- SPIFFS_close(&fs, fd);
-}
-
-void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size) {
- spiffs_file fd = SPIFFS_open(&fs, filename, SPIFFS_RDWR, 0);
- if (SPIFFS_read(&fs, fd, dst, size) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
- SPIFFS_close(&fs, fd);
-}
-
-void rename_in_spiffs(const char *old_filename, const char *new_filename) {
- if (SPIFFS_rename(&fs, old_filename, new_filename) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
-}
-
-void remove_from_spiffs(const char *filename) {
- if (SPIFFS_remove(&fs, filename) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
-}
-
-spiffs_stat stat_in_spiffs(const char *filename) {
- spiffs_stat s;
- if (SPIFFS_stat(&fs, filename, &s) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
- return s;
-}
-
-uint32_t size_in_spiffs(const char *filename) {
- spiffs_stat s = stat_in_spiffs(filename);
- return s.size;
-}
-
-rdv40_spiffs_fsinfo info_of_spiffs() {
- rdv40_spiffs_fsinfo fsinfo;
- fsinfo.blockSize = SPIFFS_CFG_LOG_BLOCK_SZ;
- fsinfo.pageSize = LOG_PAGE_SIZE;
- fsinfo.maxOpenFiles = RDV40_SPIFFS_MAX_FD;
- fsinfo.maxPathLength = SPIFFS_OBJ_NAME_LEN;
- if (SPIFFS_info(&fs, &fsinfo.totalBytes, &fsinfo.usedBytes) < 0)
- Dbprintf("errno %i\n", SPIFFS_errno(&fs));
- fsinfo.freeBytes = fsinfo.totalBytes - fsinfo.usedBytes;
- // Rounding without float may be improved
- fsinfo.usedPercent = ((100 * fsinfo.usedBytes) + (fsinfo.totalBytes / 2)) / fsinfo.totalBytes;
- fsinfo.freePercent = (100 - fsinfo.usedPercent);
- return fsinfo;
-}
-
-int exists_in_spiffs(const char *filename) {
- spiffs_stat stat;
- int rc = SPIFFS_stat(&fs, filename, &stat);
- return rc == SPIFFS_OK;
-}
-
-RDV40SpiFFSFileType filetype_in_spiffs(const char *filename) {
- RDV40SpiFFSFileType filetype = RDV40_SPIFFS_FILETYPE_UNKNOWN;
- char symlinked[SPIFFS_OBJ_NAME_LEN];
- sprintf(symlinked, "%s.lnk", filename);
- if (exists_in_spiffs(filename)) {
- filetype = RDV40_SPIFFS_FILETYPE_REAL;
- }
- if (exists_in_spiffs(symlinked)) {
- if (filetype != RDV40_SPIFFS_FILETYPE_UNKNOWN) {
- filetype = RDV40_SPIFFS_FILETYPE_BOTH;
- } else {
- filetype = RDV40_SPIFFS_FILETYPE_SYMLINK;
- }
- }
- if (DBGLEVEL > 1) {
- switch (filetype) {
- case RDV40_SPIFFS_FILETYPE_REAL:
- Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_REAL");
- break;
- case RDV40_SPIFFS_FILETYPE_SYMLINK:
- Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_SYMLINK");
- break;
- case RDV40_SPIFFS_FILETYPE_BOTH:
- Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_BOTH");
- break;
- case RDV40_SPIFFS_FILETYPE_UNKNOWN:
- Dbprintf("Filetype is : RDV40_SPIFFS_FILETYPE_UNKNOWN");
- break;
- }
- }
- return filetype;
-}
-
-int is_valid_filename(const char *filename) {
- if (filename == NULL) {
- return false;
- }
- uint32_t len = strlen(filename);
- return len > 0 && len < SPIFFS_OBJ_NAME_LEN;
-}
-
-void copy_in_spiffs(const char *src, const char *dst) {
- uint32_t size = size_in_spiffs((char *)src);
- uint8_t *mem = BigBuf_malloc(size);
- read_from_spiffs((char *)src, (uint8_t *)mem, size);
- write_to_spiffs((char *)dst, (uint8_t *)mem, size);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-////// Abstract Operations for base Safetyness /////////////////////////////////
-//
-// mount if not already
-// As an "hint" to the behavior one should adopt after his or her lazyness
-// it will return 0 if the call was a noop, either because it did not need to
-// change OR because it wasn't ABLE to change :)
-// 1 if the mount status actually changed
-// so you know what to do IN CASE you wished to set things "back to previous
-// state"
-int rdv40_spiffs_lazy_mount() {
- int changed = 0;
- if (!rdv40_spiffs_mounted()) {
- changed = rdv40_spiffs_mount();
- /* if changed = 0 = SPIFFS_OK then all went well then the change
- * actually occurred :)*/
- changed = !changed;
- }
- return changed;
-}
-
-// unmount if not already
-int rdv40_spiffs_lazy_unmount() {
- int changed = 0;
- if (rdv40_spiffs_mounted()) {
- changed = rdv40_spiffs_unmount();
- changed = !changed;
- }
- return changed;
-}
-
-// Before further Reading, it is required to have in mind that UNMOUTING is
-// important in some ways Because it is the ONLY operation which ensure that
-// -> all Caches and writings are flushed to the FS
-// -> all FD are properly closed
-// -> Every best effort has been done to ensure consistency and integrity of the
-// state reputated to be the actual state of the Filesystem.
-//---
-
-// This will "toggle" mount status
-// on "changement" conditional
-// so it is for the former lazy_ mounting function to actually rollback or not
-// depending on the result of the previous This is super lazy implementation as
-// it is either a toggle to previous state or again a noop as everything was a
-// nonevent If you have a function which NEEDS mounting but you want to exit
-// this function in the very state mounting was before your intervention all
-// things can now be transparent like
-/*
-void my_lazy_spiffs_act(){
- uint8_t changed = rdv40_spiffs_lazy_mount();
- [..] Do what you have to do with spiffs
- rdv40_spiffs_lazy_rollback(changed)
-}
-*/
-// The exact same goes for needed unmouting with eventual rollback, you just
-// have to use lazy_unmount insted of lazy mount This way, you can ensure
-// consistency in operation even with complex chain of mounting and unmounting
-// Lets's say you are in a function which needs to mount if not already, and in
-// the middle of itself calls function which indeed will need to unmount if not
-// already. Well you better use safe or wrapped function which are made to
-// rollback to previous state, so you can continue right after to do your
-// things.
-//
-// As an extreme example: let's imagine that we have a function which is made
-// to FORMAT the whole SPIFFS if a SPECIFIC content is written in the 4 first
-// byte of that file. Also in such a case it should quickly create a bunch of
-// skkeleton to get itself back to a known and wanted state. This behavior has
-// to be done at every "manual" (not a lazy or internal event) mounting, just
-// like an action upon boot.
-/*
- void my_spiffs_boot(){
- uint8_t resetret[4];
- // this lazy_mount since needed and can also report back the change on
-state implied by eventual mount, if needed rdv40_spiffs_lazy_read((const char
-*)".SHOULDRESET",(uint8_t *)resetret,4); if( resetret == "YESS" ) { uint8_t
-changed = rdv40_spiffs_lazy_format(); // this will imply change only if we where
-already mounted beforehand, was the case after our reading without further
-rollback rdv40_spiffs_lazy_mount_rollback(changed); // so if we were mounted
-just get back to this state. If not, just don't.
- [...]
- }
- [...]
-}
-*/
-// Again : This will "toggle" spiffs mount status only if a "change" occurred
-// (and should be fed by the result of a spiffs_lazy* function) If everything
-// went well, it will return SPIFFS_OK if everything went well, and a report
-// back the chain a SPI_ERRNO if not.
-int rdv40_spiffs_lazy_mount_rollback(int changed) {
- if (!changed)
- return SPIFFS_OK;
- if (rdv40_spiffs_mounted())
- return rdv40_spiffs_unmount();
- return rdv40_spiffs_mount();
-}
-///////////////////////////////////////////////////////////////////////////////
-
-// High level functions with SatefetyLevel
-// Beware that different safety level makes different return behavior
-//
-// RDV40_SPIFFS_SAFETY_NORMAL : will operate withtout further change on mount
-// status RDV40_SPIFFS_SAFETY_LAZY : will ensure mount status already being in
-// correct state before ops,
-// will return !false if mount state had to change
-// RDV40_SPIFFS_SAFETY_SAFE : will do same as RDV40_SPIFFS_SAFETY_LAZY
-// will also safely rollback to previous state IF
-// mount state had to change will return SPIFFS_OK /
-// 0 / false if everything went well
-
-// TODO : this functions are common enought to be unified with a switchcase
-// statement or some function taking function parameters
-// TODO : forbid writing to a filename which already exists as lnk !
-// TODO : forbid writing to a filename.lnk which already exists without lnk !
-int rdv40_spiffs_write(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION(
- write_to_spiffs(filename, src, size);
- )
-}
-
-int rdv40_spiffs_append(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION(
- append_to_spiffs(filename, src, size);
- )
-}
-
-// todo integrate reading symlinks transparently
-int rdv40_spiffs_read(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION(
- read_from_spiffs(filename, dst, size);
- )
-}
-
-// TODO : forbid writing to a filename which already exists as lnk !
-// TODO : forbid writing to a filename.lnk which already exists without lnk !
-int rdv40_spiffs_rename(char *old_filename, char *new_filename, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- rename_in_spiffs((char *)old_filename, (char *)new_filename); //
- )
-}
-int rdv40_spiffs_remove(char *filename, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- remove_from_spiffs((char *)filename); //
- )
-}
-
-int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- copy_in_spiffs((char *)src, (char *)dst); //
- )
-}
-
-int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- *buf = size_in_spiffs((char *)filename); //
- )
-}
-
-int rdv40_spiffs_getfsinfo(rdv40_spiffs_fsinfo *fsinfo, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- *fsinfo = info_of_spiffs(); //
- )
-}
-
-// test for symlink from filename
-int rdv40_spiffs_is_symlink(const char *s) {
- int ret = 0;
-
- if (s != NULL) {
- size_t size = strlen(s);
-
- if (size >= 4 && s[size - 4] == '.' && s[size - 3] == 'l' && s[size - 2] == 'n' && s[size - 1] == 'k') {
- ret = 1;
- }
- }
-
- return ret;
-}
-
-// since FILENAME can't be longer than 32Bytes as of hard configuration, we're
-// safe with Such maximum. So the "size" variable is actually the known/intended
-// size of DESTINATION file, may it be known (may we provide a "stat from
-// symlinkk ?")
-// ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension)
-// TODO : integrate in read_function
-int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- char linkdest[SPIFFS_OBJ_NAME_LEN]; //
- char linkfilename[SPIFFS_OBJ_NAME_LEN]; //
- sprintf(linkfilename, "%s.lnk", filename);
- if (DBGLEVEL > 1) Dbprintf("Linkk real filename is destination is : %s", linkfilename);
- read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
- if (DBGLEVEL > 1) Dbprintf("Symlink destination is : %s", linkdest);
- read_from_spiffs((char *)linkdest, (uint8_t *)dst, size); //
- )
- }
-
-// BEWARE ! This function is DESTRUCTIVE as it will UPDATE an existing symlink
-// Since it creates a .lnk extension file it may be minor to mistake the order of arguments
-// Still please use this function with care.
-// Also, remind that it will NOT check if destination filename actually exists
-// As a mnenotechnic, think about the "ln" unix command, which order is the same as "cp" unix command
-// in regard of arguments orders.
-// Eg :
-// rdv40_spiffs_make_symlink((uint8_t *)"hello", (uint8_t *)"world", RDV40_SPIFFS_SAFETY_SAFE)
-// will generate a file named "world.lnk" with the path to file "hello" written in
-// wich you can then read back with :
-// rdv40_spiffs_read_as_symlink((uint8_t *)"world",(uint8_t *) buffer, orig_file_size, RDV40_SPIFFS_SAFETY_SAFE);
-// TODO : FORBID creating a symlink with a basename (before.lnk) which already exists as a file !
-int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- char linkfilename[SPIFFS_OBJ_NAME_LEN]; //
- sprintf(linkfilename, "%s.lnk", filename);
- write_to_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN); //
- )
-}
-
-// filename and filename.lnk will both the existence-checked
-// if filename exists, read will be used, if filename.lnk exists, read_as_symlink will be used
-// Both existence is not handled right now and should not happen or create a default fallback behavior
-// Still, this case won't happend when the write(s) functions will check for both symlink and real file
-// preexistance, avoiding a link being created if filename exists, or avoiding a file being created if
-// symlink exists with same name
-int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
- RDV40_SPIFFS_SAFE_FUNCTION( //
- RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename); //
- switch (filetype) {
- case RDV40_SPIFFS_FILETYPE_REAL:
- rdv40_spiffs_read((char *)filename, (uint8_t *)dst, size, level);
- break;
- case RDV40_SPIFFS_FILETYPE_SYMLINK:
- rdv40_spiffs_read_as_symlink((char *)filename, (uint8_t *)dst, size, level);
- break;
- case RDV40_SPIFFS_FILETYPE_BOTH:
- case RDV40_SPIFFS_FILETYPE_UNKNOWN:
- default:
- ;
- } //
- )
-}
-
-// TODO regarding reads/write and symlinks :
-// Provide a higher level readFile function which
-// - don't need a size to be provided, getting it from STAT call and using bigbuff malloc
-// - write back the whole readed file as return Result
-// Maybe a good think to implement a VFS api here.
-
-////////////////////////////////////////////////////////////////////////////////
-
-///////// MISC HIGH LEVEL FUNCTIONS ////////////////////////////////////////////
-#define SPIFFS_BANNER DbpString(_BLUE_("Flash Memory FileSystem tree (SPIFFS)"));
-
-void rdv40_spiffs_safe_print_fsinfo() {
- rdv40_spiffs_fsinfo fsinfo;
- rdv40_spiffs_getfsinfo(&fsinfo, RDV40_SPIFFS_SAFETY_SAFE);
-
- DbpString(_BLUE_("Flash Memory FileSystem Info (SPIFFS)"));
-
-
- Dbprintf(" Logical Block Size........." _YELLOW_("%d")"bytes", fsinfo.blockSize);
- Dbprintf(" Logical Page Size.........." _YELLOW_("%d")"bytes", fsinfo.pageSize);
- Dbprintf("");
- Dbprintf(" Max Open Files............." _YELLOW_("%d")"file descriptors", fsinfo.maxOpenFiles);
- Dbprintf(" Max Path Length............" _YELLOW_("%d")"chars", fsinfo.maxPathLength);
- DbpString("");
- Dbprintf(" filesystem size used available use% mounted");
- Dbprintf(" spiffs %6d B %6d B %6d B"_YELLOW_("%2d%")" /"
- , fsinfo.totalBytes
- , fsinfo.usedBytes
- , fsinfo.freeBytes
- , fsinfo.usedPercent
- );
-}
-
-// this function is safe and WILL rollback since it is only a PRINTING function,
-// not a function intended to give any sort of struct to manipulate the FS
-// objects
-// TODO : Fake the Directory availability by spliting strings , buffering,
-// maintaining prefix list sorting, unique_checking, THEN outputing precomputed
-// tree Other solutio nwould be to add directory support to SPIFFS, but that we
-// dont want, as prefix are way easier and lighter in every aspect.
-void rdv40_spiffs_safe_print_tree(uint8_t banner) {
-
- if (banner) {
- DbpString(_BLUE_("Flash Memory FileSystem tree (SPIFFS)"));
- Dbprintf("-------------------------------------");
- }
-
- int changed = rdv40_spiffs_lazy_mount();
- spiffs_DIR d;
- struct spiffs_dirent e;
- struct spiffs_dirent *pe = &e;
-
- SPIFFS_opendir(&fs, "/", &d);
- Dbprintf(" \t \t/");
- while ((pe = SPIFFS_readdir(&d, pe))) {
-
- char resolvedlink[11 + SPIFFS_OBJ_NAME_LEN];
- if (rdv40_spiffs_is_symlink((const char *)pe->name)) {
- char linkdest[SPIFFS_OBJ_NAME_LEN];
- read_from_spiffs((char *)pe->name, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
- sprintf(resolvedlink, "(.lnk) --> %s", linkdest);
- // Kind of stripping the .lnk extension
- strtok((char *)pe->name, ".");
- } else {
- memset(resolvedlink, 0, sizeof(resolvedlink));
- }
-
- Dbprintf("[%04x]\t %ibytes \t|-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink);
- }
- SPIFFS_closedir(&d);
-
- rdv40_spiffs_lazy_mount_rollback(changed);
-}
-
-
-// Selftest function
-void test_spiffs() {
- Dbprintf("----------------------------------------------");
- Dbprintf("Testing SPIFFS operations");
- Dbprintf("----------------------------------------------");
- Dbprintf("-- all test are made using lazy safetylevel");
-
- Dbprintf(" Mounting filesystem (lazy).......");
- int changed = rdv40_spiffs_lazy_mount();
-
- Dbprintf(" Printing tree..............");
- rdv40_spiffs_safe_print_tree(false);
-
- Dbprintf(" Writing 'I love Proxmark3 RDV4' in a testspiffs.txt");
-
- // Since We lazy_mounted manually before hand, the wrte safety level will
- // just imply noops
- rdv40_spiffs_write((char *)"testspiffs.txt", (uint8_t *)"I love Proxmark3 RDV4", 21, RDV40_SPIFFS_SAFETY_SAFE);
-
- Dbprintf(" Printing tree again.......");
- rdv40_spiffs_safe_print_tree(false);
-
- Dbprintf(" Making a symlink to testspiffs.txt");
- rdv40_spiffs_make_symlink((char *)"testspiffs.txt", (char *)"linktotestspiffs.txt", RDV40_SPIFFS_SAFETY_SAFE);
-
- Dbprintf(" Printing tree again.......");
- rdv40_spiffs_safe_print_tree(false);
-
- // TODO READBACK, rename,print tree read back, remove, print tree;
- Dbprintf(" Rollbacking The mount status IF things have changed");
- rdv40_spiffs_lazy_mount_rollback(changed);
-
- Dbprintf(_GREEN_("All done"));
- return;
-}
-
-///////////////////////////////////////////////////////////////////////////////
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs.h b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs.h
deleted file mode 100644
index f10c86db..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs.h
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- * spiffs.h
- *
- * Created on: May 26, 2013
- * Author: petera
- */
-
-#ifndef SPIFFS_H_
-#define SPIFFS_H_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include "spiffs_config.h"
-
-typedef enum spiffs_safety_level { RDV40_SPIFFS_SAFETY_NORMAL, RDV40_SPIFFS_SAFETY_LAZY, RDV40_SPIFFS_SAFETY_SAFE } RDV40SpiFFSSafetyLevel;
-
-typedef enum spiffs_file_type {
- RDV40_SPIFFS_FILETYPE_REAL,
- RDV40_SPIFFS_FILETYPE_SYMLINK,
- RDV40_SPIFFS_FILETYPE_BOTH,
- RDV40_SPIFFS_FILETYPE_UNKNOWN
-} RDV40SpiFFSFileType;
-
-typedef struct rdv40_spiffs_fsinfo {
- uint32_t blockSize;
- uint32_t pageSize;
- uint32_t maxOpenFiles;
- uint32_t maxPathLength;
- uint32_t totalBytes, usedBytes, freeBytes;
- uint32_t usedPercent, freePercent;
-} rdv40_spiffs_fsinfo;
-
-int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
-
-int rdv40_spiffs_check();
-int rdv40_spiffs_lazy_unmount();
-int rdv40_spiffs_lazy_mount();
-int rdv40_spiffs_lazy_mount_rollback(int changed);
-int rdv40_spiffs_write(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
-int rdv40_spiffs_read(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
-int rdv40_spiffs_rename(char *old_filename, char *new_filename, RDV40SpiFFSSafetyLevel level);
-int rdv40_spiffs_remove(char *filename, RDV40SpiFFSSafetyLevel level);
-int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level);
-void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size);
-void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size);
-void test_spiffs();
-void rdv40_spiffs_safe_print_tree(uint8_t banner);
-int rdv40_spiffs_unmount();
-int rdv40_spiffs_mount();
-int rdv40_spiffs_is_symlink(const char *s);
-void rdv40_spiffs_safe_print_fsinfo();
-int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyLevel level);
-void append_to_spiffs(const char *filename, uint8_t *src, uint32_t size);
-int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level);
-int rdv40_spiffs_append(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
-int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level);
-uint32_t size_in_spiffs(const char *filename);
-int exists_in_spiffs(const char *filename);
-
-#define SPIFFS_OK 0
-#define SPIFFS_ERR_NOT_MOUNTED -10000
-#define SPIFFS_ERR_FULL -10001
-#define SPIFFS_ERR_NOT_FOUND -10002
-#define SPIFFS_ERR_END_OF_OBJECT -10003
-#define SPIFFS_ERR_DELETED -10004
-#define SPIFFS_ERR_NOT_FINALIZED -10005
-#define SPIFFS_ERR_NOT_INDEX -10006
-#define SPIFFS_ERR_OUT_OF_FILE_DESCS -10007
-#define SPIFFS_ERR_FILE_CLOSED -10008
-#define SPIFFS_ERR_FILE_DELETED -10009
-#define SPIFFS_ERR_BAD_DESCRIPTOR -10010
-#define SPIFFS_ERR_IS_INDEX -10011
-#define SPIFFS_ERR_IS_FREE -10012
-#define SPIFFS_ERR_INDEX_SPAN_MISMATCH -10013
-#define SPIFFS_ERR_DATA_SPAN_MISMATCH -10014
-#define SPIFFS_ERR_INDEX_REF_FREE -10015
-#define SPIFFS_ERR_INDEX_REF_LU -10016
-#define SPIFFS_ERR_INDEX_REF_INVALID -10017
-#define SPIFFS_ERR_INDEX_FREE -10018
-#define SPIFFS_ERR_INDEX_LU -10019
-#define SPIFFS_ERR_INDEX_INVALID -10020
-#define SPIFFS_ERR_NOT_WRITABLE -10021
-#define SPIFFS_ERR_NOT_READABLE -10022
-#define SPIFFS_ERR_CONFLICTING_NAME -10023
-#define SPIFFS_ERR_NOT_CONFIGURED -10024
-
-#define SPIFFS_ERR_NOT_A_FS -10025
-#define SPIFFS_ERR_MOUNTED -10026
-#define SPIFFS_ERR_ERASE_FAIL -10027
-#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
-
-#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
-
-#define SPIFFS_ERR_FILE_EXISTS -10030
-
-#define SPIFFS_ERR_NOT_A_FILE -10031
-#define SPIFFS_ERR_RO_NOT_IMPL -10032
-#define SPIFFS_ERR_RO_ABORTED_OPERATION -10033
-#define SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS -10034
-#define SPIFFS_ERR_PROBE_NOT_A_FS -10035
-#define SPIFFS_ERR_NAME_TOO_LONG -10036
-
-#define SPIFFS_ERR_IX_MAP_UNMAPPED -10037
-#define SPIFFS_ERR_IX_MAP_MAPPED -10038
-#define SPIFFS_ERR_IX_MAP_BAD_RANGE -10039
-
-#define SPIFFS_ERR_SEEK_BOUNDS -10040
-
-
-#define SPIFFS_ERR_INTERNAL -10050
-
-#define SPIFFS_ERR_TEST -10100
-
-
-// spiffs file descriptor index type. must be signed
-typedef s16_t spiffs_file;
-// spiffs file descriptor flags
-typedef u16_t spiffs_flags;
-// spiffs file mode
-typedef u16_t spiffs_mode;
-// object type
-typedef u8_t spiffs_obj_type;
-
-struct spiffs_t;
-
-#if SPIFFS_HAL_CALLBACK_EXTRA
-
-/* spi read call function type */
-typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
-/* spi write call function type */
-typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *src);
-/* spi erase call function type */
-typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
-
-#else // SPIFFS_HAL_CALLBACK_EXTRA
-
-/* spi read call function type */
-typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
-/* spi write call function type */
-typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
-/* spi erase call function type */
-typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
-#endif // SPIFFS_HAL_CALLBACK_EXTRA
-
-/* file system check callback report operation */
-typedef enum {
- SPIFFS_CHECK_LOOKUP = 0,
- SPIFFS_CHECK_INDEX,
- SPIFFS_CHECK_PAGE
-} spiffs_check_type;
-
-/* file system check callback report type */
-typedef enum {
- SPIFFS_CHECK_PROGRESS = 0,
- SPIFFS_CHECK_ERROR,
- SPIFFS_CHECK_FIX_INDEX,
- SPIFFS_CHECK_FIX_LOOKUP,
- SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
- SPIFFS_CHECK_DELETE_PAGE,
- SPIFFS_CHECK_DELETE_BAD_FILE
-} spiffs_check_report;
-
-/* file system check callback function */
-#if SPIFFS_HAL_CALLBACK_EXTRA
-typedef void (*spiffs_check_callback)(struct spiffs_t *fs, spiffs_check_type type, spiffs_check_report report,
- u32_t arg1, u32_t arg2);
-#else // SPIFFS_HAL_CALLBACK_EXTRA
-typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
- u32_t arg1, u32_t arg2);
-#endif // SPIFFS_HAL_CALLBACK_EXTRA
-
-/* file system listener callback operation */
-typedef enum {
- /* the file has been created */
- SPIFFS_CB_CREATED = 0,
- /* the file has been updated or moved to another page */
- SPIFFS_CB_UPDATED,
- /* the file has been deleted */
- SPIFFS_CB_DELETED
-} spiffs_fileop_type;
-
-/* file system listener callback function */
-typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix);
-
-#ifndef SPIFFS_DBG
-#define SPIFFS_DBG(...) \
- printf(__VA_ARGS__)
-#endif
-#ifndef SPIFFS_GC_DBG
-#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
-#endif
-#ifndef SPIFFS_CACHE_DBG
-#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
-#endif
-#ifndef SPIFFS_CHECK_DBG
-#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
-#endif
-
-/* Any write to the filehandle is appended to end of the file */
-#define SPIFFS_APPEND (1<<0)
-#define SPIFFS_O_APPEND SPIFFS_APPEND
-/* If the opened file exists, it will be truncated to zero length before opened */
-#define SPIFFS_TRUNC (1<<1)
-#define SPIFFS_O_TRUNC SPIFFS_TRUNC
-/* If the opened file does not exist, it will be created before opened */
-#define SPIFFS_CREAT (1<<2)
-#define SPIFFS_O_CREAT SPIFFS_CREAT
-/* The opened file may only be read */
-#define SPIFFS_RDONLY (1<<3)
-#define SPIFFS_O_RDONLY SPIFFS_RDONLY
-/* The opened file may only be written */
-#define SPIFFS_WRONLY (1<<4)
-#define SPIFFS_O_WRONLY SPIFFS_WRONLY
-/* The opened file may be both read and written */
-#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY)
-#define SPIFFS_O_RDWR SPIFFS_RDWR
-/* Any writes to the filehandle will never be cached but flushed directly */
-#define SPIFFS_DIRECT (1<<5)
-#define SPIFFS_O_DIRECT SPIFFS_DIRECT
-/* If SPIFFS_O_CREAT and SPIFFS_O_EXCL are set, SPIFFS_open() shall fail if the file exists */
-#define SPIFFS_EXCL (1<<6)
-#define SPIFFS_O_EXCL SPIFFS_EXCL
-
-#define SPIFFS_SEEK_SET (0)
-#define SPIFFS_SEEK_CUR (1)
-#define SPIFFS_SEEK_END (2)
-
-#define SPIFFS_TYPE_FILE (1)
-#define SPIFFS_TYPE_DIR (2)
-#define SPIFFS_TYPE_HARD_LINK (3)
-#define SPIFFS_TYPE_SOFT_LINK (4)
-
-#ifndef SPIFFS_LOCK
-#define SPIFFS_LOCK(fs)
-#endif
-
-#ifndef SPIFFS_UNLOCK
-#define SPIFFS_UNLOCK(fs)
-#endif
-
-// phys structs
-
-// spiffs spi configuration struct
-typedef struct {
- // physical read function
- spiffs_read hal_read_f;
- // physical write function
- spiffs_write hal_write_f;
- // physical erase function
- spiffs_erase hal_erase_f;
-#if SPIFFS_SINGLETON == 0
- // physical size of the spi flash
- u32_t phys_size;
- // physical offset in spi flash used for spiffs,
- // must be on block boundary
- u32_t phys_addr;
- // physical size when erasing a block
- u32_t phys_erase_block;
-
- // logical size of a block, must be on physical
- // block size boundary and must never be less than
- // a physical block
- u32_t log_block_size;
- // logical size of a page, must be at least
- // log_block_size / 8
- u32_t log_page_size;
-
-#endif
-#if SPIFFS_FILEHDL_OFFSET
- // an integer offset added to each file handle
- u16_t fh_ix_offset;
-#endif
-} spiffs_config;
-
-typedef struct spiffs_t {
- // file system configuration
- spiffs_config cfg;
- // number of logical blocks
- u32_t block_count;
-
- // cursor for free blocks, block index
- spiffs_block_ix free_cursor_block_ix;
- // cursor for free blocks, entry index
- int free_cursor_obj_lu_entry;
- // cursor when searching, block index
- spiffs_block_ix cursor_block_ix;
- // cursor when searching, entry index
- int cursor_obj_lu_entry;
-
- // primary work buffer, size of a logical page
- u8_t *lu_work;
- // secondary work buffer, size of a logical page
- u8_t *work;
- // file descriptor memory area
- u8_t *fd_space;
- // available file descriptors
- u32_t fd_count;
-
- // last error
- s32_t err_code;
-
- // current number of free blocks
- u32_t free_blocks;
- // current number of busy pages
- u32_t stats_p_allocated;
- // current number of deleted pages
- u32_t stats_p_deleted;
- // flag indicating that garbage collector is cleaning
- u8_t cleaning;
- // max erase count amongst all blocks
- spiffs_obj_id max_erase_count;
-
-#if SPIFFS_GC_STATS
- u32_t stats_gc_runs;
-#endif
-
-#if SPIFFS_CACHE
- // cache memory
- void *cache;
- // cache size
- u32_t cache_size;
-#if SPIFFS_CACHE_STATS
- u32_t cache_hits;
- u32_t cache_misses;
-#endif
-#endif
-
- // check callback function
- spiffs_check_callback check_cb_f;
- // file callback function
- spiffs_file_callback file_cb_f;
- // mounted flag
- u8_t mounted;
- // user data
- void *user_data;
- // config magic
- u32_t config_magic;
-} spiffs;
-
-/* spiffs file status struct */
-typedef struct {
- spiffs_obj_id obj_id;
- u32_t size;
- spiffs_obj_type type;
- spiffs_page_ix pix;
- u8_t name[SPIFFS_OBJ_NAME_LEN];
-#if SPIFFS_OBJ_META_LEN
- u8_t meta[SPIFFS_OBJ_META_LEN];
-#endif
-} spiffs_stat;
-
-struct spiffs_dirent {
- spiffs_obj_id obj_id;
- u8_t name[SPIFFS_OBJ_NAME_LEN];
- spiffs_obj_type type;
- u32_t size;
- spiffs_page_ix pix;
-#if SPIFFS_OBJ_META_LEN
- u8_t meta[SPIFFS_OBJ_META_LEN];
-#endif
-};
-
-typedef struct {
- spiffs *fs;
- spiffs_block_ix block;
- int entry;
-} spiffs_DIR;
-
-#if SPIFFS_IX_MAP
-
-typedef struct {
- // buffer with looked up data pixes
- spiffs_page_ix *map_buf;
- // precise file byte offset
- u32_t offset;
- // start data span index of lookup buffer
- spiffs_span_ix start_spix;
- // end data span index of lookup buffer
- spiffs_span_ix end_spix;
-} spiffs_ix_map;
-
-#endif
-
-// functions
-
-#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
-/**
- * Special function. This takes a spiffs config struct and returns the number
- * of blocks this file system was formatted with. This function relies on
- * that following info is set correctly in given config struct:
- *
- * phys_addr, log_page_size, and log_block_size.
- *
- * Also, hal_read_f must be set in the config struct.
- *
- * One must be sure of the correct page size and that the physical address is
- * correct in the probed file system when calling this function. It is not
- * checked if the phys_addr actually points to the start of the file system,
- * so one might get a false positive if entering a phys_addr somewhere in the
- * middle of the file system at block boundary. In addition, it is not checked
- * if the page size is actually correct. If it is not, weird file system sizes
- * will be returned.
- *
- * If this function detects a file system it returns the assumed file system
- * size, which can be used to set the phys_size.
- *
- * Otherwise, it returns an error indicating why it is not regarded as a file
- * system.
- *
- * Note: this function is not protected with SPIFFS_LOCK and SPIFFS_UNLOCK
- * macros. It returns the error code directly, instead of as read by
- * SPIFFS_errno.
- *
- * @param config essential parts of the physical and logical
- * configuration of the file system.
- */
-s32_t SPIFFS_probe_fs(spiffs_config *config);
-#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
-
-/**
- * Initializes the file system dynamic parameters and mounts the filesystem.
- * If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
- * if the flash does not contain a recognizable file system.
- * In this case, SPIFFS_format must be called prior to remounting.
- * @param fs the file system struct
- * @param config the physical and logical configuration of the file system
- * @param work a memory work buffer comprising 2*config->log_page_size
- * bytes used throughout all file system operations
- * @param fd_space memory for file descriptors
- * @param fd_space_size memory size of file descriptors
- * @param cache memory for cache, may be null
- * @param cache_size memory size of cache
- * @param check_cb_f callback function for reporting during consistency checks
- */
-s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
- u8_t *fd_space, u32_t fd_space_size,
- void *cache, u32_t cache_size,
- spiffs_check_callback check_cb_f);
-
-/**
- * Unmounts the file system. All file handles will be flushed of any
- * cached writes and closed.
- * @param fs the file system struct
- */
-void SPIFFS_unmount(spiffs *fs);
-
-/**
- * Creates a new file.
- * @param fs the file system struct
- * @param path the path of the new file
- * @param mode ignored, for posix compliance
- */
-s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
-
-/**
- * Opens/creates a file.
- * @param fs the file system struct
- * @param path the path of the new file
- * @param flags the flags for the open command, can be combinations of
- * SPIFFS_O_APPEND, SPIFFS_O_TRUNC, SPIFFS_O_CREAT, SPIFFS_O_RDONLY,
- * SPIFFS_O_WRONLY, SPIFFS_O_RDWR, SPIFFS_O_DIRECT, SPIFFS_O_EXCL
- * @param mode ignored, for posix compliance
- */
-spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode);
-
-/**
- * Opens a file by given dir entry.
- * Optimization purposes, when traversing a file system with SPIFFS_readdir
- * a normal SPIFFS_open would need to traverse the filesystem again to find
- * the file, whilst SPIFFS_open_by_dirent already knows where the file resides.
- * @param fs the file system struct
- * @param e the dir entry to the file
- * @param flags the flags for the open command, can be combinations of
- * SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
- * SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
- * SPIFFS_CREAT will have no effect in this case.
- * @param mode ignored, for posix compliance
- */
-spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode);
-
-/**
- * Opens a file by given page index.
- * Optimization purposes, opens a file by directly pointing to the page
- * index in the spi flash.
- * If the page index does not point to a file header SPIFFS_ERR_NOT_A_FILE
- * is returned.
- * @param fs the file system struct
- * @param page_ix the page index
- * @param flags the flags for the open command, can be combinations of
- * SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
- * SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
- * SPIFFS_CREAT will have no effect in this case.
- * @param mode ignored, for posix compliance
- */
-spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode);
-
-/**
- * Reads from given filehandle.
- * @param fs the file system struct
- * @param fh the filehandle
- * @param buf where to put read data
- * @param len how much to read
- * @returns number of bytes read, or -1 if error
- */
-s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
-
-/**
- * Writes to given filehandle.
- * @param fs the file system struct
- * @param fh the filehandle
- * @param buf the data to write
- * @param len how much to write
- * @returns number of bytes written, or -1 if error
- */
-s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
-
-/**
- * Moves the read/write file offset. Resulting offset is returned or negative if error.
- * lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset.
- * @param fs the file system struct
- * @param fh the filehandle
- * @param offs how much/where to move the offset
- * @param whence if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes
- * if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
- * if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse, which should be negative
- */
-s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
-
-/**
- * Removes a file by path
- * @param fs the file system struct
- * @param path the path of the file to remove
- */
-s32_t SPIFFS_remove(spiffs *fs, const char *path);
-
-/**
- * Removes a file by filehandle
- * @param fs the file system struct
- * @param fh the filehandle of the file to remove
- */
-s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
-
-/**
- * Gets file status by path
- * @param fs the file system struct
- * @param path the path of the file to stat
- * @param s the stat struct to populate
- */
-s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
-
-/**
- * Gets file status by filehandle
- * @param fs the file system struct
- * @param fh the filehandle of the file to stat
- * @param s the stat struct to populate
- */
-s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s);
-
-/**
- * Flushes all pending write operations from cache for given file
- * @param fs the file system struct
- * @param fh the filehandle of the file to flush
- */
-s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
-
-/**
- * Closes a filehandle. If there are pending write operations, these are finalized before closing.
- * @param fs the file system struct
- * @param fh the filehandle of the file to close
- */
-s32_t SPIFFS_close(spiffs *fs, spiffs_file fh);
-
-/**
- * Renames a file
- * @param fs the file system struct
- * @param old path of file to rename
- * @param newPath new path of file
- */
-s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_path);
-
-#if SPIFFS_OBJ_META_LEN
-/**
- * Updates file's metadata
- * @param fs the file system struct
- * @param path path to the file
- * @param meta new metadata. must be SPIFFS_OBJ_META_LEN bytes long.
- */
-s32_t SPIFFS_update_meta(spiffs *fs, const char *name, const void *meta);
-
-/**
- * Updates file's metadata
- * @param fs the file system struct
- * @param fh file handle of the file
- * @param meta new metadata. must be SPIFFS_OBJ_META_LEN bytes long.
- */
-s32_t SPIFFS_fupdate_meta(spiffs *fs, spiffs_file fh, const void *meta);
-#endif
-
-/**
- * Returns last error of last file operation.
- * @param fs the file system struct
- */
-s32_t SPIFFS_errno(spiffs *fs);
-
-/**
- * Clears last error.
- * @param fs the file system struct
- */
-void SPIFFS_clearerr(spiffs *fs);
-
-/**
- * Opens a directory stream corresponding to the given name.
- * The stream is positioned at the first entry in the directory.
- * On hydrogen builds the name argument is ignored as hydrogen builds always correspond
- * to a flat file structure - no directories.
- * @param fs the file system struct
- * @param name the name of the directory
- * @param d pointer the directory stream to be populated
- */
-spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
-
-/**
- * Closes a directory stream
- * @param d the directory stream to close
- */
-s32_t SPIFFS_closedir(spiffs_DIR *d);
-
-/**
- * Reads a directory into given spifs_dirent struct.
- * @param d pointer to the directory stream
- * @param e the dirent struct to be populated
- * @returns null if error or end of stream, else given dirent is returned
- */
-struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
-
-/**
- * Runs a consistency check on given filesystem.
- * @param fs the file system struct
- */
-s32_t SPIFFS_check(spiffs *fs);
-
-/**
- * Returns number of total bytes available and number of used bytes.
- * This is an estimation, and depends on if there a many files with little
- * data or few files with much data.
- * NB: If used number of bytes exceeds total bytes, a SPIFFS_check should
- * run. This indicates a power loss in midst of things. In worst case
- * (repeated powerlosses in mending or gc) you might have to delete some files.
- *
- * @param fs the file system struct
- * @param total total number of bytes in filesystem
- * @param used used number of bytes in filesystem
- */
-s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
-
-/**
- * Formats the entire file system. All data will be lost.
- * The filesystem must not be mounted when calling this.
- *
- * NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount
- * MUST be called prior to formatting in order to configure the filesystem.
- * If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling
- * SPIFFS_format.
- * If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
- * SPIFFS_unmount first.
- *
- * @param fs the file system struct
- */
-s32_t SPIFFS_format(spiffs *fs);
-
-/**
- * Returns nonzero if spiffs is mounted, or zero if unmounted.
- * @param fs the file system struct
- */
-u8_t SPIFFS_mounted(spiffs *fs);
-
-/**
- * Tries to find a block where most or all pages are deleted, and erase that
- * block if found. Does not care for wear levelling. Will not move pages
- * around.
- * If parameter max_free_pages are set to 0, only blocks with only deleted
- * pages will be selected.
- *
- * NB: the garbage collector is automatically called when spiffs needs free
- * pages. The reason for this function is to give possibility to do background
- * tidying when user knows the system is idle.
- *
- * Use with care.
- *
- * Setting max_free_pages to anything larger than zero will eventually wear
- * flash more as a block containing free pages can be erased.
- *
- * Will set err_no to SPIFFS_OK if a block was found and erased,
- * SPIFFS_ERR_NO_DELETED_BLOCK if no matching block was found,
- * or other error.
- *
- * @param fs the file system struct
- * @param max_free_pages maximum number allowed free pages in block
- */
-s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
-
-/**
- * Will try to make room for given amount of bytes in the filesystem by moving
- * pages and erasing blocks.
- * If it is physically impossible, err_no will be set to SPIFFS_ERR_FULL. If
- * there already is this amount (or more) of free space, SPIFFS_gc will
- * silently return. It is recommended to call SPIFFS_info before invoking
- * this method in order to determine what amount of bytes to give.
- *
- * NB: the garbage collector is automatically called when spiffs needs free
- * pages. The reason for this function is to give possibility to do background
- * tidying when user knows the system is idle.
- *
- * Use with care.
- *
- * @param fs the file system struct
- * @param size amount of bytes that should be freed
- */
-s32_t SPIFFS_gc(spiffs *fs, u32_t size);
-
-/**
- * Check if EOF reached.
- * @param fs the file system struct
- * @param fh the filehandle of the file to check
- */
-s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
-
-/**
- * Get position in file.
- * @param fs the file system struct
- * @param fh the filehandle of the file to check
- */
-s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
-
-/**
- * Registers a callback function that keeps track on operations on file
- * headers. Do note, that this callback is called from within internal spiffs
- * mechanisms. Any operations on the actual file system being callbacked from
- * in this callback will mess things up for sure - do not do this.
- * This can be used to track where files are and move around during garbage
- * collection, which in turn can be used to build location tables in ram.
- * Used in conjuction with SPIFFS_open_by_page this may improve performance
- * when opening a lot of files.
- * Must be invoked after mount.
- *
- * @param fs the file system struct
- * @param cb_func the callback on file operations
- */
-s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func);
-
-#if SPIFFS_IX_MAP
-
-/**
- * Maps the first level index lookup to a given memory map.
- * This will make reading big files faster, as the memory map will be used for
- * looking up data pages instead of searching for the indices on the physical
- * medium. When mapping, all affected indicies are found and the information is
- * copied to the array.
- * Whole file or only parts of it may be mapped. The index map will cover file
- * contents from argument offset until and including arguments (offset+len).
- * It is valid to map a longer range than the current file size. The map will
- * then be populated when the file grows.
- * On garbage collections and file data page movements, the map array will be
- * automatically updated. Do not tamper with the map array, as this contains
- * the references to the data pages. Modifying it from outside will corrupt any
- * future readings using this file descriptor.
- * The map will no longer be used when the file descriptor closed or the file
- * is unmapped.
- * This can be useful to get faster and more deterministic timing when reading
- * large files, or when seeking and reading a lot within a file.
- * @param fs the file system struct
- * @param fh the file handle of the file to map
- * @param map a spiffs_ix_map struct, describing the index map
- * @param offset absolute file offset where to start the index map
- * @param len length of the mapping in actual file bytes
- * @param map_buf the array buffer for the look up data - number of required
- * elements in the array can be derived from function
- * SPIFFS_bytes_to_ix_map_entries given the length
- */
-s32_t SPIFFS_ix_map(spiffs *fs, spiffs_file fh, spiffs_ix_map *map,
- u32_t offset, u32_t len, spiffs_page_ix *map_buf);
-
-/**
- * Unmaps the index lookup from this filehandle. All future readings will
- * proceed as normal, requiring reading of the first level indices from
- * physical media.
- * The map and map buffer given in function SPIFFS_ix_map will no longer be
- * referenced by spiffs.
- * It is not strictly necessary to unmap a file before closing it, as closing
- * a file will automatically unmap it.
- * @param fs the file system struct
- * @param fh the file handle of the file to unmap
- */
-s32_t SPIFFS_ix_unmap(spiffs *fs, spiffs_file fh);
-
-/**
- * Moves the offset for the index map given in function SPIFFS_ix_map. Parts or
- * all of the map buffer will repopulated.
- * @param fs the file system struct
- * @param fh the mapped file handle of the file to remap
- * @param offset new absolute file offset where to start the index map
- */
-s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset);
-
-/**
- * Utility function to get number of spiffs_page_ix entries a map buffer must
- * contain on order to map given amount of file data in bytes.
- * See function SPIFFS_ix_map and SPIFFS_ix_map_entries_to_bytes.
- * @param fs the file system struct
- * @param bytes number of file data bytes to map
- * @return needed number of elements in a spiffs_page_ix array needed to
- * map given amount of bytes in a file
- */
-s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes);
-
-/**
- * Utility function to amount of file data bytes that can be mapped when
- * mapping a file with buffer having given number of spiffs_page_ix entries.
- * See function SPIFFS_ix_map and SPIFFS_bytes_to_ix_map_entries.
- * @param fs the file system struct
- * @param map_page_ix_entries number of entries in a spiffs_page_ix array
- * @return amount of file data in bytes that can be mapped given a map
- * buffer having given amount of spiffs_page_ix entries
- */
-s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entries);
-
-#endif // SPIFFS_IX_MAP
-
-
-#if SPIFFS_TEST_VISUALISATION
-/**
- * Prints out a visualization of the filesystem.
- * @param fs the file system struct
- */
-s32_t SPIFFS_vis(spiffs *fs);
-#endif
-
-#if SPIFFS_BUFFER_HELP
-/**
- * Returns number of bytes needed for the filedescriptor buffer given
- * amount of file descriptors.
- */
-u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs);
-
-#if SPIFFS_CACHE
-/**
- * Returns number of bytes needed for the cache buffer given
- * amount of cache pages.
- */
-u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
-#endif
-#endif
-
-#if SPIFFS_CACHE
-#endif
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* SPIFFS_H_ */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_cache.c b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_cache.c
deleted file mode 100644
index 98acc4c2..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_cache.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * spiffs_cache.c
- *
- * Created on: Jun 23, 2013
- * Author: petera
- */
-
-#include "spiffs.h"
-#include "spiffs_nucleus.h"
-
-#if SPIFFS_CACHE
-
-// returns cached page for give page index, or null if no such cached page
-static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) {
- spiffs_cache *cache = spiffs_get_cache(fs);
- if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) return 0;
- int i;
- for (i = 0; i < cache->cpage_count; i++) {
- spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
- if ((cache->cpage_use_map & (1 << i)) &&
- (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
- cp->ucache.spix.pix == pix) {
- //SPIFFS_CACHE_DBG("CACHE_GET: have cache page "_SPIPRIi" for "_SPIPRIpg"\n", i, pix);
- cp->last_access = cache->last_access;
- return cp;
- }
- }
- //SPIFFS_CACHE_DBG("CACHE_GET: no cache for "_SPIPRIpg"\n", pix);
- return 0;
-}
-
-// frees cached page
-static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
- s32_t res = SPIFFS_OK;
- spiffs_cache *cache = spiffs_get_cache(fs);
- spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, ix);
- if (cache->cpage_use_map & (1 << ix)) {
- if (write_back &&
- (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
- (cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
- u8_t *mem = spiffs_get_cache_page(fs, cache, ix);
- SPIFFS_CACHE_DBG("CACHE_FREE: write cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->ucache.spix.pix);
- res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->ucache.spix.pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
- }
-
-#if SPIFFS_CACHE_WR
- if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) {
- SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" objid "_SPIPRIid"\n", ix, cp->ucache.swrc.obj_id);
- } else
-#endif
- {
- SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->ucache.spix.pix);
- }
- cache->cpage_use_map &= ~(1 << ix);
- cp->flags = 0;
- }
-
- return res;
-}
-
-// removes the oldest accessed cached page
-static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t flags) {
- s32_t res = SPIFFS_OK;
- spiffs_cache *cache = spiffs_get_cache(fs);
-
- if ((cache->cpage_use_map & cache->cpage_use_mask) != cache->cpage_use_mask) {
- // at least one free cpage
- return SPIFFS_OK;
- }
-
- // all busy, scan thru all to find the cpage which has oldest access
- int i;
- int cand_ix = -1;
- u32_t oldest_val = 0;
- for (i = 0; i < cache->cpage_count; i++) {
- spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
- if ((cache->last_access - cp->last_access) > oldest_val &&
- (cp->flags & flag_mask) == flags) {
- oldest_val = cache->last_access - cp->last_access;
- cand_ix = i;
- }
- }
-
- if (cand_ix >= 0) {
- res = spiffs_cache_page_free(fs, cand_ix, 1);
- }
-
- return res;
-}
-
-// allocates a new cached page and returns it, or null if all cache pages are busy
-static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
- spiffs_cache *cache = spiffs_get_cache(fs);
- if (cache->cpage_use_map == 0xffffffff) {
- // out of cache memory
- return 0;
- }
- int i;
- for (i = 0; i < cache->cpage_count; i++) {
- if ((cache->cpage_use_map & (1 << i)) == 0) {
- spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
- cache->cpage_use_map |= (1 << i);
- cp->last_access = cache->last_access;
- //SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi"\n", i);
- return cp;
- }
- }
- // out of cache entries
- return 0;
-}
-
-// drops the cache page for give page index
-void spiffs_cache_drop_page(spiffs *fs, spiffs_page_ix pix) {
- spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
- if (cp) {
- spiffs_cache_page_free(fs, cp->ix, 0);
- }
-}
-
-// ------------------------------
-
-// reads from spi flash or the cache
-s32_t spiffs_phys_rd(
- spiffs *fs,
- u8_t op,
- spiffs_file fh,
- u32_t addr,
- u32_t len,
- u8_t *dst) {
- (void)fh;
- s32_t res = SPIFFS_OK;
- spiffs_cache *cache = spiffs_get_cache(fs);
- spiffs_cache_page *cp = spiffs_cache_page_get(fs, SPIFFS_PADDR_TO_PAGE(fs, addr));
- cache->last_access++;
- if (cp) {
- // we've already got one, you see
-#if SPIFFS_CACHE_STATS
- fs->cache_hits++;
-#endif
- cp->last_access = cache->last_access;
- u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
- _SPIFFS_MEMCPY(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len);
- } else {
- if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) {
- // for second layer lookup functions, we do not cache in order to prevent shredding
- return SPIFFS_HAL_READ(fs, addr, len, dst);
- }
-#if SPIFFS_CACHE_STATS
- fs->cache_misses++;
-#endif
- // this operation will always free one cache page (unless all already free),
- // the result code stems from the write operation of the possibly freed cache page
- res = spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0);
-
- cp = spiffs_cache_page_allocate(fs);
- if (cp) {
- cp->flags = SPIFFS_CACHE_FLAG_WRTHRU;
- cp->ucache.spix.pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
- SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for pix "_SPIPRIpg "\n", cp->ix, cp->ucache.spix.pix);
-
- s32_t res2 = SPIFFS_HAL_READ(fs,
- addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),
- SPIFFS_CFG_LOG_PAGE_SZ(fs),
- spiffs_get_cache_page(fs, cache, cp->ix));
- if (res2 != SPIFFS_OK) {
- // honor read failure before possible write failure (bad idea?)
- res = res2;
- }
- u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
- _SPIFFS_MEMCPY(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len);
- } else {
- // this will never happen, last resort for sake of symmetry
- s32_t res2 = SPIFFS_HAL_READ(fs, addr, len, dst);
- if (res2 != SPIFFS_OK) {
- // honor read failure before possible write failure (bad idea?)
- res = res2;
- }
- }
- }
- return res;
-}
-
-// writes to spi flash and/or the cache
-s32_t spiffs_phys_wr(
- spiffs *fs,
- u8_t op,
- spiffs_file fh,
- u32_t addr,
- u32_t len,
- u8_t *src) {
- (void)fh;
- spiffs_page_ix pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
- spiffs_cache *cache = spiffs_get_cache(fs);
- spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
-
- if (cp && (op & SPIFFS_OP_COM_MASK) != SPIFFS_OP_C_WRTHRU) {
- // have a cache page
- // copy in data to cache page
-
- if ((op & SPIFFS_OP_COM_MASK) == SPIFFS_OP_C_DELE &&
- (op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) {
- // page is being deleted, wipe from cache - unless it is a lookup page
- spiffs_cache_page_free(fs, cp->ix, 0);
- return SPIFFS_HAL_WRITE(fs, addr, len, src);
- }
-
- u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
- _SPIFFS_MEMCPY(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len);
-
- cache->last_access++;
- cp->last_access = cache->last_access;
-
- if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
- // page is being updated, no write-cache, just pass thru
- return SPIFFS_HAL_WRITE(fs, addr, len, src);
- } else {
- return SPIFFS_OK;
- }
- } else {
- // no cache page, no write cache - just write thru
- return SPIFFS_HAL_WRITE(fs, addr, len, src);
- }
-}
-
-#if SPIFFS_CACHE_WR
-// returns the cache page that this fd refers, or null if no cache page
-spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
- spiffs_cache *cache = spiffs_get_cache(fs);
-
- if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) {
- // all cpages free, no cpage cannot be assigned to obj_id
- return 0;
- }
-
- int i;
- for (i = 0; i < cache->cpage_count; i++) {
- spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
- if ((cache->cpage_use_map & (1 << i)) &&
- (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) &&
- cp->ucache.swrc.obj_id == fd->obj_id) {
- return cp;
- }
- }
-
- return 0;
-}
-
-// allocates a new cache page and refers this to given fd - flushes an old cache
-// page if all cache is busy
-spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_fd *fd) {
- // before this function is called, it is ensured that there is no already existing
- // cache page with same object id
- spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0);
- spiffs_cache_page *cp = spiffs_cache_page_allocate(fs);
- if (cp == 0) {
- // could not get cache page
- return 0;
- }
-
- cp->flags = SPIFFS_CACHE_FLAG_TYPE_WR;
- cp->ucache.swrc.obj_id = fd->obj_id;
- fd->cache_page = cp;
- SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for fd "_SPIPRIfd ":"_SPIPRIid "\n", cp->ix, fd->file_nbr, fd->obj_id);
- return cp;
-}
-
-// unrefers all fds that this cache page refers to and releases the cache page
-void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) {
- if (cp == 0) return;
- u32_t i;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr != 0 && cur_fd->cache_page == cp) {
- cur_fd->cache_page = 0;
- }
- }
- spiffs_cache_page_free(fs, cp->ix, 0);
-
- cp->ucache.swrc.obj_id = 0;
-}
-
-#endif
-
-// initializes the cache
-void spiffs_cache_init(spiffs *fs) {
- if (fs->cache == 0) return;
- u32_t sz = fs->cache_size;
- u32_t cache_mask = 0;
- int i;
- int cache_entries =
- (sz - sizeof(spiffs_cache)) / (SPIFFS_CACHE_PAGE_SIZE(fs));
- if (cache_entries <= 0) return;
-
- for (i = 0; i < cache_entries; i++) {
- cache_mask <<= 1;
- cache_mask |= 1;
- }
-
- spiffs_cache cache;
- memset(&cache, 0, sizeof(spiffs_cache));
- cache.cpage_count = cache_entries;
- cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache));
-
- cache.cpage_use_map = 0xffffffff;
- cache.cpage_use_mask = cache_mask;
- _SPIFFS_MEMCPY(fs->cache, &cache, sizeof(spiffs_cache));
-
- spiffs_cache *c = spiffs_get_cache(fs);
-
- memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs));
-
- c->cpage_use_map &= ~(c->cpage_use_mask);
- for (i = 0; i < cache.cpage_count; i++) {
- spiffs_get_cache_page_hdr(fs, c, i)->ix = i;
- }
-}
-
-#endif // SPIFFS_CACHE
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_check.c b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_check.c
deleted file mode 100644
index 90fba8a4..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_check.c
+++ /dev/null
@@ -1,1006 +0,0 @@
-/*
- * spiffs_check.c
- *
- * Contains functionality for checking file system consistency
- * and mending problems.
- * Three levels of consistency checks are implemented:
- *
- * Look up consistency
- * Checks if indices in lookup pages are coherent with page headers
- * Object index consistency
- * Checks if there are any orphaned object indices (missing object index headers).
- * If an object index is found but not its header, the object index is deleted.
- * This is critical for the following page consistency check.
- * Page consistency
- * Checks for pages that ought to be indexed, ought not to be indexed, are multiple indexed
- *
- *
- * Created on: Jul 7, 2013
- * Author: petera
- */
-
-
-#include "spiffs.h"
-#include "spiffs_nucleus.h"
-
-#if !SPIFFS_READ_ONLY
-
-#if SPIFFS_HAL_CALLBACK_EXTRA
-#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
- do { \
- if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \
- } while (0)
-#else
-#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
- do { \
- if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \
- } while (0)
-#endif
-
-//---------------------------------------
-// Look up consistency
-
-// searches in the object indices and returns the referenced page index given
-// the object id and the data span index
-// destroys fs->lu_work
-static s32_t spiffs_object_get_data_page_index_reference(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix data_spix,
- spiffs_page_ix *pix,
- spiffs_page_ix *objix_pix) {
- s32_t res;
-
- // calculate object index span index for given data page span index
- spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
-
- // find obj index for obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, objix_pix);
- SPIFFS_CHECK_RES(res);
-
- // load obj index entry
- u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, *objix_pix);
- if (objix_spix == 0) {
- // get referenced page from object index header
- addr += sizeof(spiffs_page_object_ix_header) + data_spix * sizeof(spiffs_page_ix);
- } else {
- // get referenced page from object index
- addr += sizeof(spiffs_page_object_ix) + SPIFFS_OBJ_IX_ENTRY(fs, data_spix) * sizeof(spiffs_page_ix);
- }
-
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, 0, addr, sizeof(spiffs_page_ix), (u8_t *)pix);
-
- return res;
-}
-
-// copies page contents to a new page
-static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spiffs_page_header *p_hdr, spiffs_page_ix *new_pix) {
- s32_t res;
- res = spiffs_page_allocate_data(fs, p_hdr->obj_id, p_hdr, 0, 0, 0, 0, new_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_phys_cpy(fs, 0,
- SPIFFS_PAGE_TO_PADDR(fs, *new_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
- SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_CHECK_RES(res);
- return res;
-}
-
-// rewrites the object index for given object id and replaces the
-// data page index to a new page index
-static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_ix data_spix, spiffs_page_ix new_data_pix, spiffs_page_ix objix_pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
- spiffs_page_ix free_pix;
- obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
-
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
- free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
-
- // calculate object index span index for given data page span index
- spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- if (objix_spix == 0) {
- // calc index in index header
- entry = data_spix;
- } else {
- // calc entry in index
- entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix);
-
- }
- // load index
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
- spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work;
-
- // be ultra safe, double check header against provided data
- if (objix_p_hdr->obj_id != obj_id) {
- spiffs_page_delete(fs, free_pix);
- return SPIFFS_ERR_CHECK_OBJ_ID_MISM;
- }
- if (objix_p_hdr->span_ix != objix_spix) {
- spiffs_page_delete(fs, free_pix);
- return SPIFFS_ERR_CHECK_SPIX_MISM;
- }
- if ((objix_p_hdr->flags & (SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_INDEX |
- SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) !=
- (SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_DELET)) {
- spiffs_page_delete(fs, free_pix);
- return SPIFFS_ERR_CHECK_FLAGS_BAD;
- }
-
- // rewrite in mem
- if (objix_spix == 0) {
- ((spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix;
- } else {
- ((spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix;
- }
-
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, free_pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, free_pix) * sizeof(spiffs_page_ix),
- sizeof(spiffs_obj_id),
- (u8_t *)&obj_id);
- SPIFFS_CHECK_RES(res);
- res = spiffs_page_delete(fs, objix_pix);
-
- return res;
-}
-
-// deletes an object just by marking object index header as deleted
-static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) {
- spiffs_page_ix objix_hdr_pix;
- s32_t res;
- res = spiffs_obj_lu_find_id_and_span(fs, obj_id, 0, 0, &objix_hdr_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- return SPIFFS_OK;
- }
- SPIFFS_CHECK_RES(res);
- u8_t flags = 0xff;
-#if SPIFFS_NO_BLIND_WRITES
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags),
- sizeof(flags), &flags);
- SPIFFS_CHECK_RES(res);
-#endif
- flags &= ~SPIFFS_PH_FLAG_IXDELE;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags),
- sizeof(flags), &flags);
- return res;
-}
-
-// validates the given look up entry
-static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, spiffs_page_header *p_hdr,
- spiffs_page_ix cur_pix, spiffs_block_ix cur_block, int cur_entry, int *reload_lu) {
- (void)cur_block;
- (void)cur_entry;
- u8_t delete_page = 0;
- s32_t res = SPIFFS_OK;
- spiffs_page_ix objix_pix;
- spiffs_page_ix ref_pix;
- // check validity, take actions
- if (((lu_obj_id == SPIFFS_OBJ_ID_DELETED) && (p_hdr->flags & SPIFFS_PH_FLAG_DELET)) ||
- ((lu_obj_id == SPIFFS_OBJ_ID_FREE) && (p_hdr->flags & SPIFFS_PH_FLAG_USED) == 0)) {
- // look up entry deleted / free but used in page header
- SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" deleted/free in lu but not on page\n", cur_pix);
- *reload_lu = 1;
- delete_page = 1;
- if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) {
- // header says data page
- // data page can be removed if not referenced by some object index
- res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- // no object with this id, so remove page safely
- res = SPIFFS_OK;
- } else {
- SPIFFS_CHECK_RES(res);
- if (ref_pix == cur_pix) {
- // data page referenced by object index but deleted in lu
- // copy page to new place and re-write the object index to new place
- spiffs_page_ix new_pix;
- res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
- SPIFFS_CHECK_DBG("LU: FIXUP: data page not found elsewhere, rewriting "_SPIPRIpg" to new page "_SPIPRIpg"\n", cur_pix, new_pix);
- SPIFFS_CHECK_RES(res);
- *reload_lu = 1;
- SPIFFS_CHECK_DBG("LU: FIXUP: "_SPIPRIpg" rewritten to "_SPIPRIpg", affected objix_pix "_SPIPRIpg"\n", cur_pix, new_pix, objix_pix);
- res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
- if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
- // index bad also, cannot mend this file
- SPIFFS_CHECK_DBG("LU: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res);
- res = spiffs_page_delete(fs, new_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
- } else {
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix);
- }
- SPIFFS_CHECK_RES(res);
- }
- }
- } else {
- // header says index page
- // index page can be removed if other index with same obj_id and spanix is found
- res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, 0);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- // no such index page found, check for a data page amongst page headers
- // lu cannot be trusted
- res = spiffs_obj_lu_find_id_and_span_by_phdr(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, 0);
- if (res == SPIFFS_OK) { // ignore other errors
- // got a data page also, assume lu corruption only, rewrite to new page
- spiffs_page_ix new_pix;
- res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
- SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting "_SPIPRIpg" to new page "_SPIPRIpg"\n", cur_pix, new_pix);
- SPIFFS_CHECK_RES(res);
- *reload_lu = 1;
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
- }
- } else {
- SPIFFS_CHECK_RES(res);
- }
- }
- }
- if (lu_obj_id != SPIFFS_OBJ_ID_FREE && lu_obj_id != SPIFFS_OBJ_ID_DELETED) {
- // look up entry used
- if ((p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG) != (lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG)) {
- SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" differ in obj_id lu:"_SPIPRIid" ph:"_SPIPRIid"\n", cur_pix, lu_obj_id, p_hdr->obj_id);
- delete_page = 1;
- if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0 ||
- (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) ||
- (p_hdr->flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_IXDELE)) == 0) {
- // page deleted or not finalized, just remove it
- } else {
- if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) {
- // if data page, check for reference to this page
- res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- // no object with this id, so remove page safely
- res = SPIFFS_OK;
- } else {
- SPIFFS_CHECK_RES(res);
- // if found, rewrite page with object id, update index, and delete current
- if (ref_pix == cur_pix) {
- spiffs_page_ix new_pix;
- res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
- if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
- // index bad also, cannot mend this file
- SPIFFS_CHECK_DBG("LU: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res);
- res = spiffs_page_delete(fs, new_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
- *reload_lu = 1;
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
- }
- SPIFFS_CHECK_RES(res);
- }
- }
- } else {
- // else if index, check for other pages with both obj_id's and spanix
- spiffs_page_ix objix_pix_lu, objix_pix_ph;
- // see if other object index page exists for lookup obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_lu);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- objix_pix_lu = 0;
- }
- SPIFFS_CHECK_RES(res);
- // see if other object index exists for page header obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_ph);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- objix_pix_ph = 0;
- }
- SPIFFS_CHECK_RES(res);
- // if both obj_id's found, just delete current
- if (objix_pix_ph == 0 || objix_pix_lu == 0) {
- // otherwise try finding first corresponding data pages
- spiffs_page_ix data_pix_lu, data_pix_ph;
- // see if other data page exists for look up obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_lu);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- objix_pix_lu = 0;
- }
- SPIFFS_CHECK_RES(res);
- // see if other data page exists for page header obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_ph);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- objix_pix_ph = 0;
- }
- SPIFFS_CHECK_RES(res);
-
- spiffs_page_header new_ph;
- new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL);
- new_ph.span_ix = p_hdr->span_ix;
- spiffs_page_ix new_pix;
- if ((objix_pix_lu && data_pix_lu && data_pix_ph && objix_pix_ph == 0) ||
- (objix_pix_lu == 0 && data_pix_ph && objix_pix_ph == 0)) {
- // got a data page for page header obj id
- // rewrite as obj_id_ph
- new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
- res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
- SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page "_SPIPRIpg" as "_SPIPRIid" to pix "_SPIPRIpg"\n", cur_pix, new_ph.obj_id, new_pix);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
- SPIFFS_CHECK_RES(res);
- *reload_lu = 1;
- } else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) ||
- (objix_pix_ph == 0 && data_pix_lu && objix_pix_lu == 0)) {
- // got a data page for look up obj id
- // rewrite as obj_id_lu
- new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
- SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page "_SPIPRIpg" as "_SPIPRIid"\n", cur_pix, new_ph.obj_id);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
- res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
- SPIFFS_CHECK_RES(res);
- *reload_lu = 1;
- } else {
- // cannot safely do anything
- SPIFFS_CHECK_DBG("LU: FIXUP: nothing to do, just delete\n", NULL);
- }
- }
- }
- }
- } else if (((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX)) ||
- ((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0 && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) == 0)) {
- SPIFFS_CHECK_DBG("LU: "_SPIPRIpg" lu/page index marking differ\n", cur_pix);
- spiffs_page_ix data_pix, objix_pix_d;
- // see if other data page exists for given obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &data_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- data_pix = 0;
- }
- SPIFFS_CHECK_RES(res);
- // see if other object index exists for given obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix_d);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- objix_pix_d = 0;
- }
- SPIFFS_CHECK_RES(res);
-
- delete_page = 1;
- // if other data page exists and object index exists, just delete page
- if (data_pix && objix_pix_d) {
- SPIFFS_CHECK_DBG("LU: FIXUP: other index and data page exists, simply remove\n", NULL);
- } else
- // if only data page exists, make this page index
- if (data_pix && objix_pix_d == 0) {
- SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n", NULL);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
- spiffs_page_header new_ph;
- spiffs_page_ix new_pix;
- new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
- new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
- new_ph.span_ix = p_hdr->span_ix;
- res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
- SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header));
- SPIFFS_CHECK_RES(res);
- } else
- // if only index exists, make data page
- if (data_pix == 0 && objix_pix_d) {
- SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n", NULL);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
- spiffs_page_header new_ph;
- spiffs_page_ix new_pix;
- new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
- new_ph.obj_id = lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- new_ph.span_ix = p_hdr->span_ix;
- res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
- SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header));
- SPIFFS_CHECK_RES(res);
- } else {
- // if nothing exists, we cannot safely make a decision - delete
- }
- } else if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0) {
- SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" busy in lu but deleted on page\n", cur_pix);
- delete_page = 1;
- } else if ((p_hdr->flags & SPIFFS_PH_FLAG_FINAL)) {
- SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" busy but not final\n", cur_pix);
- // page can be removed if not referenced by object index
- *reload_lu = 1;
- res = spiffs_object_get_data_page_index_reference(fs, lu_obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- // no object with this id, so remove page safely
- res = SPIFFS_OK;
- delete_page = 1;
- } else {
- SPIFFS_CHECK_RES(res);
- if (ref_pix != cur_pix) {
- SPIFFS_CHECK_DBG("LU: FIXUP: other finalized page is referred, just delete\n", NULL);
- delete_page = 1;
- } else {
- // page referenced by object index but not final
- // just finalize
- SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n", NULL);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
- u8_t flags = 0xff;
-#if SPIFFS_NO_BLIND_WRITES
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags),
- sizeof(flags), &flags);
- SPIFFS_CHECK_RES(res);
-#endif
- flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags),
- sizeof(flags), &flags);
- }
- }
- }
- }
-
- if (delete_page) {
- SPIFFS_CHECK_DBG("LU: FIXUP: deleting page "_SPIPRIpg"\n", cur_pix);
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
- res = spiffs_page_delete(fs, cur_pix);
- SPIFFS_CHECK_RES(res);
- }
-
- return res;
-}
-
-static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry,
- const void *user_const_p, void *user_var_p) {
- (void)user_const_p;
- (void)user_var_p;
- s32_t res = SPIFFS_OK;
- spiffs_page_header p_hdr;
- spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
-
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS,
- (cur_block * 256) / fs->block_count, 0);
-
- // load header
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
-
- int reload_lu = 0;
-
- res = spiffs_lookup_check_validate(fs, obj_id, &p_hdr, cur_pix, cur_block, cur_entry, &reload_lu);
- SPIFFS_CHECK_RES(res);
-
- if (res == SPIFFS_OK) {
- return reload_lu ? SPIFFS_VIS_COUNTINUE_RELOAD : SPIFFS_VIS_COUNTINUE;
- }
- return res;
-}
-
-
-// Scans all object look up. For each entry, corresponding page header is checked for validity.
-// If an object index header page is found, this is also checked
-s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
- (void)check_all_objects;
- s32_t res = SPIFFS_OK;
-
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
-
- res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0);
-
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_OK;
- }
-
- if (res != SPIFFS_OK) {
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0);
- }
-
- CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0);
-
- return res;
-}
-
-//---------------------------------------
-// Page consistency
-
-// Scans all pages (except lu pages), reserves 4 bits in working memory for each page
-// bit 0: 0 == FREE|DELETED, 1 == USED
-// bit 1: 0 == UNREFERENCED, 1 == REFERENCED
-// bit 2: 0 == NOT_INDEX, 1 == INDEX
-// bit 3: unused
-// A consistent file system will have only pages being
-// * x000 free, unreferenced, not index
-// * x011 used, referenced only once, not index
-// * x101 used, unreferenced, index
-// The working memory might not fit all pages so several scans might be needed
-static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
- const u32_t bits = 4;
- const spiffs_page_ix pages_per_scan = SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8 / bits;
-
- s32_t res = SPIFFS_OK;
- spiffs_page_ix pix_offset = 0;
-
- // for each range of pages fitting into work memory
- while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) {
- // set this flag to abort all checks and rescan the page range
- u8_t restart = 0;
- memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
-
- spiffs_block_ix cur_block = 0;
- // build consistency bitmap for id range traversing all blocks
- while (!restart && cur_block < fs->block_count) {
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS,
- (pix_offset * 256) / (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) +
- ((((cur_block * pages_per_scan * 256) / (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count),
- 0);
- // traverse each page except for lookup pages
- spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
- while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block + 1)) {
- //if ((cur_pix & 0xff) == 0)
- // SPIFFS_CHECK_DBG("PA: processing pix "_SPIPRIpg", block "_SPIPRIbl" of pix "_SPIPRIpg", block "_SPIPRIbl"\n",
- // cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count);
-
- // read header
- spiffs_page_header p_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
-
- u8_t within_range = (cur_pix >= pix_offset && cur_pix < pix_offset + pages_per_scan);
- const u32_t pix_byte_ix = (cur_pix - pix_offset) / (8 / bits);
- const u8_t pix_bit_ix = (cur_pix & ((8 / bits) - 1)) * bits;
-
- if (within_range &&
- (p_hdr.flags & SPIFFS_PH_FLAG_DELET) && (p_hdr.flags & SPIFFS_PH_FLAG_USED) == 0) {
- // used
- fs->work[pix_byte_ix] |= (1 << (pix_bit_ix + 0));
- }
- if ((p_hdr.flags & SPIFFS_PH_FLAG_DELET) &&
- (p_hdr.flags & SPIFFS_PH_FLAG_IXDELE) &&
- (p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) == 0) {
- // found non-deleted index
- if (within_range) {
- fs->work[pix_byte_ix] |= (1 << (pix_bit_ix + 2));
- }
-
- // load non-deleted index
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
-
- // traverse index for referenced pages
- spiffs_page_ix *object_page_index;
- spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work;
-
- int entries;
- int i;
- spiffs_span_ix data_spix_offset;
- if (p_hdr.span_ix == 0) {
- // object header page index
- entries = SPIFFS_OBJ_HDR_IX_LEN(fs);
- data_spix_offset = 0;
- object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header));
- } else {
- // object page index
- entries = SPIFFS_OBJ_IX_LEN(fs);
- data_spix_offset = SPIFFS_OBJ_HDR_IX_LEN(fs) + SPIFFS_OBJ_IX_LEN(fs) * (p_hdr.span_ix - 1);
- object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix));
- }
-
- // for all entries in index
- for (i = 0; !restart && i < entries; i++) {
- spiffs_page_ix rpix = object_page_index[i];
- u8_t rpix_within_range = rpix >= pix_offset && rpix < pix_offset + pages_per_scan;
-
- if ((rpix != (spiffs_page_ix) - 1 && rpix > SPIFFS_MAX_PAGES(fs))
- || (rpix_within_range && SPIFFS_IS_LOOKUP_PAGE(fs, rpix))) {
-
- // bad reference
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg"x bad pix / LU referenced from page "_SPIPRIpg"\n",
- rpix, cur_pix);
- // check for data page elsewhere
- spiffs_page_ix data_pix;
- res = spiffs_obj_lu_find_id_and_span(fs, objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- data_spix_offset + i, 0, &data_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- data_pix = 0;
- }
- SPIFFS_CHECK_RES(res);
- if (data_pix == 0) {
- // if not, allocate free page
- spiffs_page_header new_ph;
- new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
- new_ph.obj_id = objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- new_ph.span_ix = data_spix_offset + i;
- res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &data_pix);
- SPIFFS_CHECK_RES(res);
- SPIFFS_CHECK_DBG("PA: FIXUP: found no existing data page, created new @ "_SPIPRIpg"\n", data_pix);
- }
- // remap index
- SPIFFS_CHECK_DBG("PA: FIXUP: rewriting index pix "_SPIPRIpg"\n", cur_pix);
- res = spiffs_rewrite_index(fs, objix_p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
- data_spix_offset + i, data_pix, cur_pix);
- if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
- // index bad also, cannot mend this file
- SPIFFS_CHECK_DBG("PA: FIXUP: index bad "_SPIPRIi", cannot mend - delete object\n", res);
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
- // delete file
- res = spiffs_page_delete(fs, cur_pix);
- } else {
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix);
- }
- SPIFFS_CHECK_RES(res);
- restart = 1;
-
- } else if (rpix_within_range) {
-
- // valid reference
- // read referenced page header
- spiffs_page_header rp_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t *)&rp_hdr);
- SPIFFS_CHECK_RES(res);
-
- // cross reference page header check
- if (rp_hdr.obj_id != (p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) ||
- rp_hdr.span_ix != data_spix_offset + i ||
- (rp_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) !=
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX)) {
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" has inconsistent page header ix id/span:"_SPIPRIid"/"_SPIPRIsp", ref id/span:"_SPIPRIid"/"_SPIPRIsp" flags:"_SPIPRIfl"\n",
- rpix, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, data_spix_offset + i,
- rp_hdr.obj_id, rp_hdr.span_ix, rp_hdr.flags);
- // try finding correct page
- spiffs_page_ix data_pix;
- res = spiffs_obj_lu_find_id_and_span(fs, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- data_spix_offset + i, rpix, &data_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- data_pix = 0;
- }
- SPIFFS_CHECK_RES(res);
- if (data_pix == 0) {
- // not found, this index is badly borked
- SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id "_SPIPRIid"\n", p_hdr.obj_id);
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
- res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
- SPIFFS_CHECK_RES(res);
- break;
- } else {
- // found it, so rewrite index
- SPIFFS_CHECK_DBG("PA: FIXUP: found correct data pix "_SPIPRIpg", rewrite ix pix "_SPIPRIpg" id "_SPIPRIid"\n",
- data_pix, cur_pix, p_hdr.obj_id);
- res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix);
- if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
- // index bad also, cannot mend this file
- SPIFFS_CHECK_DBG("PA: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res);
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
- res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
- } else {
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
- }
- SPIFFS_CHECK_RES(res);
- restart = 1;
- }
- } else {
- // mark rpix as referenced
- const u32_t rpix_byte_ix = (rpix - pix_offset) / (8 / bits);
- const u8_t rpix_bit_ix = (rpix & ((8 / bits) - 1)) * bits;
- if (fs->work[rpix_byte_ix] & (1 << (rpix_bit_ix + 1))) {
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" multiple referenced from page "_SPIPRIpg"\n",
- rpix, cur_pix);
- // Here, we should have fixed all broken references - getting this means there
- // must be multiple files with same object id. Only solution is to delete
- // the object which is referring to this page
- SPIFFS_CHECK_DBG("PA: FIXUP: removing object "_SPIPRIid" and page "_SPIPRIpg"\n",
- p_hdr.obj_id, cur_pix);
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
- res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
- SPIFFS_CHECK_RES(res);
- // extra precaution, delete this page also
- res = spiffs_page_delete(fs, cur_pix);
- SPIFFS_CHECK_RES(res);
- restart = 1;
- }
- fs->work[rpix_byte_ix] |= (1 << (rpix_bit_ix + 1));
- }
- }
- } // for all index entries
- } // found index
-
- // next page
- cur_pix++;
- }
- // next block
- cur_block++;
- }
- // check consistency bitmap
- if (!restart) {
- spiffs_page_ix objix_pix;
- spiffs_page_ix rpix;
-
- u32_t byte_ix;
- u8_t bit_ix;
- for (byte_ix = 0; !restart && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs); byte_ix++) {
- for (bit_ix = 0; !restart && bit_ix < 8 / bits; bit_ix ++) {
- u8_t bitmask = (fs->work[byte_ix] >> (bit_ix * bits)) & 0x7;
- spiffs_page_ix cur_pix = pix_offset + byte_ix * (8 / bits) + bit_ix;
-
- // 000 ok - free, unreferenced, not index
-
- if (bitmask == 0x1) {
-
- // 001
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" USED, UNREFERENCED, not index\n", cur_pix);
-
- u8_t rewrite_ix_to_this = 0;
- u8_t delete_page = 0;
- // check corresponding object index entry
- spiffs_page_header p_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_object_get_data_page_index_reference(fs, p_hdr.obj_id, p_hdr.span_ix,
- &rpix, &objix_pix);
- if (res == SPIFFS_OK) {
- if (((rpix == (spiffs_page_ix) - 1 || rpix > SPIFFS_MAX_PAGES(fs)) || (SPIFFS_IS_LOOKUP_PAGE(fs, rpix)))) {
- // pointing to a bad page altogether, rewrite index to this
- rewrite_ix_to_this = 1;
- SPIFFS_CHECK_DBG("PA: corresponding ref is bad: "_SPIPRIpg", rewrite to this "_SPIPRIpg"\n", rpix, cur_pix);
- } else {
- // pointing to something else, check what
- spiffs_page_header rp_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t *)&rp_hdr);
- SPIFFS_CHECK_RES(res);
- if (((p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) == rp_hdr.obj_id) &&
- ((rp_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL)) ==
- (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET))) {
- // pointing to something else valid, just delete this page then
- SPIFFS_CHECK_DBG("PA: corresponding ref is good but different: "_SPIPRIpg", delete this "_SPIPRIpg"\n", rpix, cur_pix);
- delete_page = 1;
- } else {
- // pointing to something weird, update index to point to this page instead
- if (rpix != cur_pix) {
- SPIFFS_CHECK_DBG("PA: corresponding ref is weird: "_SPIPRIpg" %s%s%s%s, rewrite this "_SPIPRIpg"\n", rpix,
- (rp_hdr.flags & SPIFFS_PH_FLAG_INDEX) ? "" : "INDEX ",
- (rp_hdr.flags & SPIFFS_PH_FLAG_DELET) ? "" : "DELETED ",
- (rp_hdr.flags & SPIFFS_PH_FLAG_USED) ? "NOTUSED " : "",
- (rp_hdr.flags & SPIFFS_PH_FLAG_FINAL) ? "NOTFINAL " : "",
- cur_pix);
- rewrite_ix_to_this = 1;
- } else {
- // should not happen, destined for fubar
- }
- }
- }
- } else if (res == SPIFFS_ERR_NOT_FOUND) {
- SPIFFS_CHECK_DBG("PA: corresponding ref not found, delete "_SPIPRIpg"\n", cur_pix);
- delete_page = 1;
- res = SPIFFS_OK;
- }
-
- if (rewrite_ix_to_this) {
- // if pointing to invalid page, redirect index to this page
- SPIFFS_CHECK_DBG("PA: FIXUP: rewrite index id "_SPIPRIid" data spix "_SPIPRIsp" to point to this pix: "_SPIPRIpg"\n",
- p_hdr.obj_id, p_hdr.span_ix, cur_pix);
- res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix);
- if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
- // index bad also, cannot mend this file
- SPIFFS_CHECK_DBG("PA: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res);
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
- res = spiffs_page_delete(fs, cur_pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
- } else {
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
- }
- SPIFFS_CHECK_RES(res);
- restart = 1;
- continue;
- } else if (delete_page) {
- SPIFFS_CHECK_DBG("PA: FIXUP: deleting page "_SPIPRIpg"\n", cur_pix);
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
- res = spiffs_page_delete(fs, cur_pix);
- }
- SPIFFS_CHECK_RES(res);
- }
- if (bitmask == 0x2) {
-
- // 010
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" FREE, REFERENCED, not index\n", cur_pix);
-
- // no op, this should be taken care of when checking valid references
- }
-
- // 011 ok - busy, referenced, not index
-
- if (bitmask == 0x4) {
-
- // 100
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" FREE, unreferenced, INDEX\n", cur_pix);
-
- // this should never happen, major fubar
- }
-
- // 101 ok - busy, unreferenced, index
-
- if (bitmask == 0x6) {
-
- // 110
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" FREE, REFERENCED, INDEX\n", cur_pix);
-
- // no op, this should be taken care of when checking valid references
- }
- if (bitmask == 0x7) {
-
- // 111
- SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" USED, REFERENCED, INDEX\n", cur_pix);
-
- // no op, this should be taken care of when checking valid references
- }
- }
- }
- }
-
- SPIFFS_CHECK_DBG("PA: processed "_SPIPRIpg", restart "_SPIPRIi"\n", pix_offset, restart);
- // next page range
- if (!restart) {
- pix_offset += pages_per_scan;
- }
- } // while page range not reached end
- return res;
-}
-
-// Checks consistency amongst all pages and fixes irregularities
-s32_t spiffs_page_consistency_check(spiffs *fs) {
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0);
- s32_t res = spiffs_page_consistency_check_i(fs);
- if (res != SPIFFS_OK) {
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0);
- }
- CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0);
- return res;
-}
-
-//---------------------------------------
-// Object index consistency
-
-// searches for given object id in temporary object id index,
-// returns the index or -1
-static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
- u32_t i;
- spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
- obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id); i++) {
- if ((obj_table[i] & ~SPIFFS_OBJ_ID_IX_FLAG) == obj_id) {
- return i;
- }
- }
- return -1;
-}
-
-static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block,
- int cur_entry, const void *user_const_p, void *user_var_p) {
- (void)user_const_p;
- s32_t res_c = SPIFFS_VIS_COUNTINUE;
- s32_t res = SPIFFS_OK;
- u32_t *log_ix = (u32_t *)user_var_p;
- spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
-
- CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS,
- (cur_block * 256) / fs->block_count, 0);
-
- if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
- spiffs_page_header p_hdr;
- spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
-
- // load header
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
-
- if (p_hdr.span_ix == 0 &&
- (p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET)) {
- SPIFFS_CHECK_DBG("IX: pix "_SPIPRIpg", obj id:"_SPIPRIid" spix:"_SPIPRIsp" header not fully deleted - deleting\n",
- cur_pix, obj_id, p_hdr.span_ix);
- CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id);
- res = spiffs_page_delete(fs, cur_pix);
- SPIFFS_CHECK_RES(res);
- return res_c;
- }
-
- if ((p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
- return res_c;
- }
-
- if (p_hdr.span_ix == 0) {
- // objix header page, register objid as reachable
- int r = spiffs_object_index_search(fs, obj_id);
- if (r == -1) {
- // not registered, do it
- obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- (*log_ix)++;
- if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) {
- *log_ix = 0;
- }
- }
- } else { // span index
- // objix page, see if header can be found
- int r = spiffs_object_index_search(fs, obj_id);
- u8_t delete = 0;
- if (r == -1) {
- // not in temporary index, try finding it
- spiffs_page_ix objix_hdr_pix;
- res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &objix_hdr_pix);
- res_c = SPIFFS_VIS_COUNTINUE_RELOAD;
- if (res == SPIFFS_OK) {
- // found, register as reachable
- obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- } else if (res == SPIFFS_ERR_NOT_FOUND) {
- // not found, register as unreachable
- delete = 1;
- obj_table[*log_ix] = obj_id | SPIFFS_OBJ_ID_IX_FLAG;
- } else {
- SPIFFS_CHECK_RES(res);
- }
- (*log_ix)++;
- if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) {
- *log_ix = 0;
- }
- } else {
- // in temporary index, check reachable flag
- if ((obj_table[r] & SPIFFS_OBJ_ID_IX_FLAG)) {
- // registered as unreachable
- delete = 1;
- }
- }
-
- if (delete) {
- SPIFFS_CHECK_DBG("IX: FIXUP: pix "_SPIPRIpg", obj id:"_SPIPRIid" spix:"_SPIPRIsp" is orphan index - deleting\n",
- cur_pix, obj_id, p_hdr.span_ix);
- CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id);
- res = spiffs_page_delete(fs, cur_pix);
- SPIFFS_CHECK_RES(res);
- }
- } // span index
- } // valid object index id
-
- return res_c;
-}
-
-// Removes orphaned and partially deleted index pages.
-// Scans for index pages. When an index page is found, corresponding index header is searched for.
-// If no such page exists, the index page cannot be reached as no index header exists and must be
-// deleted.
-s32_t spiffs_object_index_consistency_check(spiffs *fs) {
- s32_t res = SPIFFS_OK;
- // impl note:
- // fs->work is used for a temporary object index memory, listing found object ids and
- // indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit.
- // In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate
- // a reachable/unreachable object id.
- memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- u32_t obj_id_log_ix = 0;
- CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0);
- res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, 0, &obj_id_log_ix,
- 0, 0);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_OK;
- }
- if (res != SPIFFS_OK) {
- CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0);
- }
- CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0);
- return res;
-}
-
-#endif // !SPIFFS_READ_ONLY
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_config.h b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_config.h
deleted file mode 100644
index 7710a65a..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_config.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * spiffs_config.h
- *
- * Created on: Jul 3, 2013
- * Author: petera
- */
-
-#ifndef SPIFFS_CONFIG_H_
-#define SPIFFS_CONFIG_H_
-
-// ----------- 8< ------------
-// Following includes are for the linux test build of spiffs
-// These may/should/must be removed/altered/replaced in your target
-//#include
-//#include
-//
-#include "printf.h"
-#include "string.h"
-#include "flashmem.h"
-
-void Dbprintf(const char *fmt, ...);
-
-//#include
-//#include
-// ----------- >8 ------------
-
-
-typedef int s32_t;
-typedef uint32_t u32_t;
-typedef int16_t s16_t;
-typedef uint16_t u16_t;
-typedef int8_t s8_t;
-typedef uint8_t u8_t;
-
-// compile time switches
-
-// Set generic spiffs debug output call.
-#ifndef SPIFFS_DBG
-#define SPIFFS_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
-#define SPIFFS_DBGF(str) SPIFFS_DBG(str,NULL)
-#endif
-// Set spiffs debug output call for garbage collecting.
-#ifndef SPIFFS_GC_DBG
-#define SPIFFS_GC_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
-#define SPIFFS_GC_DBGF(str) SPIFFS_GC_DBG(str,NULL)
-#endif
-// Set spiffs debug output call for caching.
-#ifndef SPIFFS_CACHE_DBG
-#define SPIFFS_CACHE_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
-#define SPIFFS_CACHE_DBGF(str) SPIFFS_CACHE_DBG(str,NULL)
-#endif
-// Set spiffs debug output call for system consistency checks.
-#ifndef SPIFFS_CHECK_DBG
-#define SPIFFS_CHECK_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
-#define SPIFFS_CHECK_DBGF(str) SPIFFS_CHECK_DBG(str,NULL)
-#endif
-// Set spiffs debug output call for all api invocations.
-#ifndef SPIFFS_API_DBG
-#define SPIFFS_API_DBG(_f, ...) //Dbprintf(_f, ## __VA_ARGS__)
-#define SPIFFS_API_DBGF(str) SPIFFS_API_DBG(str,NULL)
-#endif
-
-
-
-// Defines spiffs debug print formatters
-// some general signed number
-#ifndef _SPIPRIi
-#define _SPIPRIi "%d"
-#endif
-// address
-#ifndef _SPIPRIad
-#define _SPIPRIad "%08x"
-#endif
-// block
-#ifndef _SPIPRIbl
-#define _SPIPRIbl "%04x"
-#endif
-// page
-#ifndef _SPIPRIpg
-#define _SPIPRIpg "%04x"
-#endif
-// span index
-#ifndef _SPIPRIsp
-#define _SPIPRIsp "%04x"
-#endif
-// file descriptor
-#ifndef _SPIPRIfd
-#define _SPIPRIfd "%d"
-#endif
-// file object id
-#ifndef _SPIPRIid
-#define _SPIPRIid "%04x"
-#endif
-// file flags
-#ifndef _SPIPRIfl
-#define _SPIPRIfl "%02x"
-#endif
-
-
-// Enable/disable API functions to determine exact number of bytes
-// for filedescriptor and cache buffers. Once decided for a configuration,
-// this can be disabled to reduce flash.
-#ifndef SPIFFS_BUFFER_HELP
-#define SPIFFS_BUFFER_HELP 0
-#endif
-
-// Enables/disable memory read caching of nucleus file system operations.
-// If enabled, memory area must be provided for cache in SPIFFS_mount.
-#ifndef SPIFFS_CACHE
-#define SPIFFS_CACHE 1
-#endif
-#if SPIFFS_CACHE
-// Enables memory write caching for file descriptors in hydrogen
-#ifndef SPIFFS_CACHE_WR
-#define SPIFFS_CACHE_WR 1
-#endif
-
-// Enable/disable statistics on caching. Debug/test purpose only.
-#ifndef SPIFFS_CACHE_STATS
-#define SPIFFS_CACHE_STATS 0
-#endif
-#endif
-
-// Always check header of each accessed page to ensure consistent state.
-// If enabled it will increase number of reads, will increase flash.
-#ifndef SPIFFS_PAGE_CHECK
-#define SPIFFS_PAGE_CHECK 0
-#endif
-
-// Define maximum number of gc runs to perform to reach desired free pages.
-#ifndef SPIFFS_GC_MAX_RUNS
-#define SPIFFS_GC_MAX_RUNS 5
-#endif
-
-// Enable/disable statistics on gc. Debug/test purpose only.
-#ifndef SPIFFS_GC_STATS
-#define SPIFFS_GC_STATS 0
-#endif
-
-// Garbage collecting examines all pages in a block which and sums up
-// to a block score. Deleted pages normally gives positive score and
-// used pages normally gives a negative score (as these must be moved).
-// To have a fair wear-leveling, the erase age is also included in score,
-// whose factor normally is the most positive.
-// The larger the score, the more likely it is that the block will
-// picked for garbage collection.
-
-// Garbage collecting heuristics - weight used for deleted pages.
-#ifndef SPIFFS_GC_HEUR_W_DELET
-#define SPIFFS_GC_HEUR_W_DELET (5)
-#endif
-// Garbage collecting heuristics - weight used for used pages.
-#ifndef SPIFFS_GC_HEUR_W_USED
-#define SPIFFS_GC_HEUR_W_USED (-1)
-#endif
-// Garbage collecting heuristics - weight used for time between
-// last erased and erase of this block.
-#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE
-#define SPIFFS_GC_HEUR_W_ERASE_AGE (50)
-#endif
-
-// Object name maximum length. Note that this length include the
-// zero-termination character, meaning maximum string of characters
-// can at most be SPIFFS_OBJ_NAME_LEN - 1.
-#ifndef SPIFFS_OBJ_NAME_LEN
-#define SPIFFS_OBJ_NAME_LEN (32)
-#endif
-
-// Maximum length of the metadata associated with an object.
-// Setting to non-zero value enables metadata-related API but also
-// changes the on-disk format, so the change is not backward-compatible.
-//
-// Do note: the meta length must never exceed
-// logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64)
-//
-// This is derived from following:
-// logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) +
-// spiffs_object_ix_header fields + at least some LUT entries)
-#ifndef SPIFFS_OBJ_META_LEN
-#define SPIFFS_OBJ_META_LEN (0)
-#endif
-
-// Size of buffer allocated on stack used when copying data.
-// Lower value generates more read/writes. No meaning having it bigger
-// than logical page size.
-#ifndef SPIFFS_COPY_BUFFER_STACK
-#define SPIFFS_COPY_BUFFER_STACK (256)
-#endif
-
-// Enable this to have an identifiable spiffs filesystem. This will look for
-// a magic in all sectors to determine if this is a valid spiffs system or
-// not on mount point. If not, SPIFFS_format must be called prior to mounting
-// again.
-#ifndef SPIFFS_USE_MAGIC
-#define SPIFFS_USE_MAGIC (0)
-#endif
-
-#if SPIFFS_USE_MAGIC
-// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is
-// enabled, the magic will also be dependent on the length of the filesystem.
-// For example, a filesystem configured and formatted for 4 megabytes will not
-// be accepted for mounting with a configuration defining the filesystem as 2
-// megabytes.
-#ifndef SPIFFS_USE_MAGIC_LENGTH
-#define SPIFFS_USE_MAGIC_LENGTH (0)
-#endif
-#endif
-
-// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
-// These should be defined on a multithreaded system
-
-// define this to enter a mutex if you're running on a multithreaded system
-#ifndef SPIFFS_LOCK
-#define SPIFFS_LOCK(fs)
-#endif
-// define this to exit a mutex if you're running on a multithreaded system
-#ifndef SPIFFS_UNLOCK
-#define SPIFFS_UNLOCK(fs)
-#endif
-
-// Enable if only one spiffs instance with constant configuration will exist
-// on the target. This will reduce calculations, flash and memory accesses.
-// Parts of configuration must be defined below instead of at time of mount.
-#ifndef SPIFFS_SINGLETON
-#define SPIFFS_SINGLETON (1)
-#endif
-
-#if SPIFFS_SINGLETON
-// Instead of giving parameters in config struct, singleton build must
-// give parameters in defines below.
-#ifndef SPIFFS_CFG_PHYS_SZ
-#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*128)
-#endif
-#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
-#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (4*1024)
-#endif
-#ifndef SPIFFS_CFG_PHYS_ADDR
-#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
-#endif
-#ifndef SPIFFS_CFG_LOG_PAGE_SZ
-#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256)
-#endif
-#ifndef SPIFFS_CFG_LOG_BLOCK_SZ
-#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (4*1024)
-#endif
-#endif
-
-// Enable this if your target needs aligned data for index tables
-#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
-#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1
-#endif
-
-// Enable this if you want the HAL callbacks to be called with the spiffs struct
-#ifndef SPIFFS_HAL_CALLBACK_EXTRA
-#define SPIFFS_HAL_CALLBACK_EXTRA 0
-#endif
-
-// Enable this if you want to add an integer offset to all file handles
-// (spiffs_file). This is useful if running multiple instances of spiffs on
-// same target, in order to recognise to what spiffs instance a file handle
-// belongs.
-// NB: This adds config field fh_ix_offset in the configuration struct when
-// mounting, which must be defined.
-#ifndef SPIFFS_FILEHDL_OFFSET
-#define SPIFFS_FILEHDL_OFFSET 0
-#endif
-
-// Enable this to compile a read only version of spiffs.
-// This will reduce binary size of spiffs. All code comprising modification
-// of the file system will not be compiled. Some config will be ignored.
-// HAL functions for erasing and writing to spi-flash may be null. Cache
-// can be disabled for even further binary size reduction (and ram savings).
-// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL.
-// If the file system cannot be mounted due to aborted erase operation and
-// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be
-// returned.
-// Might be useful for e.g. bootloaders and such.
-#ifndef SPIFFS_READ_ONLY
-#define SPIFFS_READ_ONLY 0
-#endif
-
-// Enable this to add a temporal file cache using the fd buffer.
-// The effects of the cache is that SPIFFS_open will find the file faster in
-// certain cases. It will make it a lot easier for spiffs to find files
-// opened frequently, reducing number of readings from the spi flash for
-// finding those files.
-// This will grow each fd by 6 bytes. If your files are opened in patterns
-// with a degree of temporal locality, the system is optimized.
-// Examples can be letting spiffs serve web content, where one file is the css.
-// The css is accessed for each html file that is opened, meaning it is
-// accessed almost every second time a file is opened. Another example could be
-// a log file that is often opened, written, and closed.
-// The size of the cache is number of given file descriptors, as it piggybacks
-// on the fd update mechanism. The cache lives in the closed file descriptors.
-// When closed, the fd know the whereabouts of the file. Instead of forgetting
-// this, the temporal cache will keep handling updates to that file even if the
-// fd is closed. If the file is opened again, the location of the file is found
-// directly. If all available descriptors become opened, all cache memory is
-// lost.
-#ifndef SPIFFS_TEMPORAL_FD_CACHE
-#define SPIFFS_TEMPORAL_FD_CACHE 1
-#endif
-
-// Temporal file cache hit score. Each time a file is opened, all cached files
-// will lose one point. If the opened file is found in cache, that entry will
-// gain SPIFFS_TEMPORAL_CACHE_HIT_SCORE points. One can experiment with this
-// value for the specific access patterns of the application. However, it must
-// be between 1 (no gain for hitting a cached entry often) and 255.
-#ifndef SPIFFS_TEMPORAL_CACHE_HIT_SCORE
-#define SPIFFS_TEMPORAL_CACHE_HIT_SCORE 4
-#endif
-
-// Enable to be able to map object indices to memory.
-// This allows for faster and more deterministic reading if cases of reading
-// large files and when changing file offset by seeking around a lot.
-// When mapping a file's index, the file system will be scanned for index pages
-// and the info will be put in memory provided by user. When reading, the
-// memory map can be looked up instead of searching for index pages on the
-// medium. This way, user can trade memory against performance.
-// Whole, parts of, or future parts not being written yet can be mapped. The
-// memory array will be owned by spiffs and updated accordingly during garbage
-// collecting or when modifying the indices. The latter is invoked by when the
-// file is modified in some way. The index buffer is tied to the file
-// descriptor.
-#ifndef SPIFFS_IX_MAP
-#define SPIFFS_IX_MAP 1
-#endif
-
-// By default SPIFFS in some cases relies on the property of NOR flash that bits
-// cannot be set from 0 to 1 by writing and that controllers will ignore such
-// bit changes. This results in fewer reads as SPIFFS can in some cases perform
-// blind writes, with all bits set to 1 and only those it needs reset set to 0.
-// Most of the chips and controllers allow this behavior, so the default is to
-// use this technique. If your controller is one of the rare ones that don't,
-// turn this option on and SPIFFS will perform a read-modify-write instead.
-#ifndef SPIFFS_NO_BLIND_WRITES
-#define SPIFFS_NO_BLIND_WRITES 0
-#endif
-
-// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
-// in the api. This function will visualize all filesystem using given printf
-// function.
-#ifndef SPIFFS_TEST_VISUALISATION
-#define SPIFFS_TEST_VISUALISATION 0
-#endif
-#if SPIFFS_TEST_VISUALISATION
-#ifndef spiffs_printf
-#define spiffs_printf(...) Dbprintf(__VA_ARGS__)
-#endif
-// spiffs_printf argument for a free page
-#ifndef SPIFFS_TEST_VIS_FREE_STR
-#define SPIFFS_TEST_VIS_FREE_STR "_"
-#endif
-// spiffs_printf argument for a deleted page
-#ifndef SPIFFS_TEST_VIS_DELE_STR
-#define SPIFFS_TEST_VIS_DELE_STR "/"
-#endif
-// spiffs_printf argument for an index page for given object id
-#ifndef SPIFFS_TEST_VIS_INDX_STR
-#define SPIFFS_TEST_VIS_INDX_STR(id) "i"
-#endif
-// spiffs_printf argument for a data page for given object id
-#ifndef SPIFFS_TEST_VIS_DATA_STR
-#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
-#endif
-#endif
-
-// Types depending on configuration such as the amount of flash bytes
-// given to spiffs file system in total (spiffs_file_system_size),
-// the logical block size (log_block_size), and the logical page size
-// (log_page_size)
-
-// Block index type. Make sure the size of this type can hold
-// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size
-typedef u16_t spiffs_block_ix;
-// Page index type. Make sure the size of this type can hold
-// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size
-typedef u16_t spiffs_page_ix;
-// Object id type - most significant bit is reserved for index flag. Make sure the
-// size of this type can hold the highest object id on a full system,
-// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2
-typedef u16_t spiffs_obj_id;
-// Object span index type. Make sure the size of this type can
-// hold the largest possible span index on the system -
-// i.e. (spiffs_file_system_size / log_page_size) - 1
-typedef u16_t spiffs_span_ix;
-
-#endif /* SPIFFS_CONFIG_H_ */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_gc.c b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_gc.c
deleted file mode 100644
index 76ff094c..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_gc.c
+++ /dev/null
@@ -1,606 +0,0 @@
-#include "spiffs.h"
-#include "spiffs_nucleus.h"
-
-#if !SPIFFS_READ_ONLY
-
-// Erases a logical block and updates the erase counter.
-// If cache is enabled, all pages that might be cached in this block
-// is dropped.
-static s32_t spiffs_gc_erase_block(
- spiffs *fs,
- spiffs_block_ix bix) {
- s32_t res;
-
- SPIFFS_GC_DBG("gc: erase block "_SPIPRIbl"\n", bix);
- res = spiffs_erase_block(fs, bix);
- SPIFFS_CHECK_RES(res);
-
-#if SPIFFS_CACHE
- {
- u32_t i;
- for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) {
- spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, bix) + i);
- }
- }
-#endif
- return res;
-}
-
-// Searches for blocks where all entries are deleted - if one is found,
-// the block is erased. Compared to the non-quick gc, the quick one ensures
-// that no updates are needed on existing objects on pages that are erased.
-s32_t spiffs_gc_quick(
- spiffs *fs, u16_t max_free_pages) {
- s32_t res = SPIFFS_OK;
- u32_t blocks = fs->block_count;
- spiffs_block_ix cur_block = 0;
- u32_t cur_block_addr = 0;
- int cur_entry = 0;
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
-
- SPIFFS_GC_DBGF("gc_quick: running\n");
-#if SPIFFS_GC_STATS
- fs->stats_gc_runs++;
-#endif
-
- int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
-
- // find fully deleted blocks
- // check each block
- while (res == SPIFFS_OK && blocks--) {
- u16_t deleted_pages_in_block = 0;
- u16_t free_pages_in_block = 0;
-
- int obj_lookup_page = 0;
- // check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each entry
- while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page &&
- cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
- spiffs_obj_id obj_id = obj_lu_buf[cur_entry - entry_offset];
- if (obj_id == SPIFFS_OBJ_ID_DELETED) {
- deleted_pages_in_block++;
- } else if (obj_id == SPIFFS_OBJ_ID_FREE) {
- // kill scan, go for next block
- free_pages_in_block++;
- if (free_pages_in_block > max_free_pages) {
- obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
- res = 1; // kill object lu loop
- break;
- }
- } else {
- // kill scan, go for next block
- obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
- res = 1; // kill object lu loop
- break;
- }
- cur_entry++;
- } // per entry
- obj_lookup_page++;
- } // per object lookup page
- if (res == 1) res = SPIFFS_OK;
-
- if (res == SPIFFS_OK &&
- deleted_pages_in_block + free_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) &&
- free_pages_in_block <= max_free_pages) {
- // found a fully deleted block
- fs->stats_p_deleted -= deleted_pages_in_block;
- res = spiffs_gc_erase_block(fs, cur_block);
- return res;
- }
-
- cur_entry = 0;
- cur_block++;
- cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- } // per block
-
- if (res == SPIFFS_OK) {
- res = SPIFFS_ERR_NO_DELETED_BLOCKS;
- }
- return res;
-}
-
-// Checks if garbage collecting is necessary. If so a candidate block is found,
-// cleansed and erased
-s32_t spiffs_gc_check(
- spiffs *fs,
- u32_t len) {
- s32_t res;
- s32_t free_pages =
- (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
- - fs->stats_p_allocated - fs->stats_p_deleted;
- int tries = 0;
-
- if (fs->free_blocks > 3 &&
- (s32_t)len < free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
- return SPIFFS_OK;
- }
-
- u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
-// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
-// SPIFFS_GC_DBG("gc: full freeblk:"_SPIPRIi" needed:"_SPIPRIi" free:"_SPIPRIi" dele:"_SPIPRIi"\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
-// return SPIFFS_ERR_FULL;
-// }
- if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
- SPIFFS_GC_DBG("gc_check: full freeblk:"_SPIPRIi" needed:"_SPIPRIi" free:"_SPIPRIi" dele:"_SPIPRIi"\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
- return SPIFFS_ERR_FULL;
- }
-
- do {
- SPIFFS_GC_DBG("\ngc_check #"_SPIPRIi": run gc free_blocks:"_SPIPRIi" pfree:"_SPIPRIi" pallo:"_SPIPRIi" pdele:"_SPIPRIi" ["_SPIPRIi"] len:"_SPIPRIi" of "_SPIPRIi"\n",
- tries,
- fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages + fs->stats_p_allocated + fs->stats_p_deleted),
- len, (u32_t)(free_pages * SPIFFS_DATA_PAGE_SIZE(fs)));
-
- spiffs_block_ix *cands;
- int count;
- spiffs_block_ix cand;
- s32_t prev_free_pages = free_pages;
- // if the fs is crammed, ignore block age when selecting candidate - kind of a bad state
- res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0);
- SPIFFS_CHECK_RES(res);
- if (count == 0) {
- SPIFFS_GC_DBGF("gc_check: no candidates, return\n");
- return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL;
- }
-#if SPIFFS_GC_STATS
- fs->stats_gc_runs++;
-#endif
- cand = cands[0];
- fs->cleaning = 1;
- //SPIFFS_GC_DBG("gcing: cleaning block "_SPIPRIi"\n", cand);
- res = spiffs_gc_clean(fs, cand);
- fs->cleaning = 0;
- if (res < 0) {
- SPIFFS_GC_DBG("gc_check: cleaning block "_SPIPRIi", result "_SPIPRIi"\n", cand, res);
- } else {
- SPIFFS_GC_DBG("gc_check: cleaning block "_SPIPRIi", result "_SPIPRIi"\n", cand, res);
- }
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_gc_erase_page_stats(fs, cand);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_gc_erase_block(fs, cand);
- SPIFFS_CHECK_RES(res);
-
- free_pages =
- (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
- - fs->stats_p_allocated - fs->stats_p_deleted;
-
- if (prev_free_pages <= 0 && prev_free_pages == free_pages) {
- // abort early to reduce wear, at least tried once
- SPIFFS_GC_DBGF("gc_check: early abort, no result on gc when fs crammed\n");
- break;
- }
-
- } while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
- (s32_t)len > free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)));
-
- free_pages =
- (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
- - fs->stats_p_allocated - fs->stats_p_deleted;
- if ((s32_t)len > free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
- res = SPIFFS_ERR_FULL;
- }
-
- SPIFFS_GC_DBG("gc_check: finished, "_SPIPRIi" dirty, blocks "_SPIPRIi" free, "_SPIPRIi" pages free, "_SPIPRIi" tries, res "_SPIPRIi"\n",
- fs->stats_p_allocated + fs->stats_p_deleted,
- fs->free_blocks, free_pages, tries, res);
-
- return res;
-}
-
-// Updates page statistics for a block that is about to be erased
-s32_t spiffs_gc_erase_page_stats(
- spiffs *fs,
- spiffs_block_ix bix) {
- s32_t res = SPIFFS_OK;
- int obj_lookup_page = 0;
- int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
- int cur_entry = 0;
- u32_t dele = 0;
- u32_t allo = 0;
-
- // check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each entry
- while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
- spiffs_obj_id obj_id = obj_lu_buf[cur_entry - entry_offset];
- if (obj_id == SPIFFS_OBJ_ID_FREE) {
- } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
- dele++;
- } else {
- allo++;
- }
- cur_entry++;
- } // per entry
- obj_lookup_page++;
- } // per object lookup page
- SPIFFS_GC_DBG("gc_check: wipe pallo:"_SPIPRIi" pdele:"_SPIPRIi"\n", allo, dele);
- fs->stats_p_allocated -= allo;
- fs->stats_p_deleted -= dele;
- return res;
-}
-
-// Finds block candidates to erase
-s32_t spiffs_gc_find_candidate(
- spiffs *fs,
- spiffs_block_ix **block_candidates,
- int *candidate_count,
- char fs_crammed) {
- s32_t res = SPIFFS_OK;
- u32_t blocks = fs->block_count;
- spiffs_block_ix cur_block = 0;
- u32_t cur_block_addr = 0;
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
- int cur_entry = 0;
-
- // using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score
- int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs) - 8) / (sizeof(spiffs_block_ix) + sizeof(s32_t)));
- *candidate_count = 0;
- memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
-
- // divide up work area into block indices and scores
- spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
- s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
-
- // align cand_scores on s32_t boundary
- cand_scores = (s32_t *)(((intptr_t)cand_scores + sizeof(intptr_t) - 1) & ~(sizeof(intptr_t) - 1));
-
- *block_candidates = cand_blocks;
-
- int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
-
- // check each block
- while (res == SPIFFS_OK && blocks--) {
- u16_t deleted_pages_in_block = 0;
- u16_t used_pages_in_block = 0;
-
- int obj_lookup_page = 0;
- // check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each entry
- while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page &&
- cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
- spiffs_obj_id obj_id = obj_lu_buf[cur_entry - entry_offset];
- if (obj_id == SPIFFS_OBJ_ID_FREE) {
- // when a free entry is encountered, scan logic ensures that all following entries are free also
- res = 1; // kill object lu loop
- break;
- } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
- deleted_pages_in_block++;
- } else {
- used_pages_in_block++;
- }
- cur_entry++;
- } // per entry
- obj_lookup_page++;
- } // per object lookup page
- if (res == 1) res = SPIFFS_OK;
-
- // calculate score and insert into candidate table
- // stoneage sort, but probably not so many blocks
- if (res == SPIFFS_OK /*&& deleted_pages_in_block > 0*/) {
- // read erase count
- spiffs_obj_id erase_count;
- res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
- SPIFFS_ERASE_COUNT_PADDR(fs, cur_block),
- sizeof(spiffs_obj_id), (u8_t *)&erase_count);
- SPIFFS_CHECK_RES(res);
-
- spiffs_obj_id erase_age;
- if (fs->max_erase_count > erase_count) {
- erase_age = fs->max_erase_count - erase_count;
- } else {
- erase_age = SPIFFS_OBJ_ID_FREE - (erase_count - fs->max_erase_count);
- }
-
- s32_t score =
- deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
- used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
- erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
- int cand_ix = 0;
- SPIFFS_GC_DBG("gc_check: bix:"_SPIPRIbl" del:"_SPIPRIi" use:"_SPIPRIi" score:"_SPIPRIi"\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
- while (cand_ix < max_candidates) {
- if (cand_blocks[cand_ix] == (spiffs_block_ix) - 1) {
- cand_blocks[cand_ix] = cur_block;
- cand_scores[cand_ix] = score;
- break;
- } else if (cand_scores[cand_ix] < score) {
- int reorder_cand_ix = max_candidates - 2;
- while (reorder_cand_ix >= cand_ix) {
- cand_blocks[reorder_cand_ix + 1] = cand_blocks[reorder_cand_ix];
- cand_scores[reorder_cand_ix + 1] = cand_scores[reorder_cand_ix];
- reorder_cand_ix--;
- }
- cand_blocks[cand_ix] = cur_block;
- cand_scores[cand_ix] = score;
- break;
- }
- cand_ix++;
- }
- (*candidate_count)++;
- }
-
- cur_entry = 0;
- cur_block++;
- cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- } // per block
-
- return res;
-}
-
-typedef enum {
- FIND_OBJ_DATA,
- MOVE_OBJ_DATA,
- MOVE_OBJ_IX,
- FINISHED
-} spiffs_gc_clean_state;
-
-typedef struct {
- spiffs_gc_clean_state state;
- spiffs_obj_id cur_obj_id;
- spiffs_span_ix cur_objix_spix;
- spiffs_page_ix cur_objix_pix;
- spiffs_page_ix cur_data_pix;
- int stored_scan_entry_index;
- u8_t obj_id_found;
-} spiffs_gc;
-
-// Empties given block by moving all data into free pages of another block
-// Strategy:
-// loop:
-// scan object lookup for object data pages
-// for first found id, check spix and load corresponding object index page to memory
-// push object scan lookup entry index
-// rescan object lookup, find data pages with same id and referenced by same object index
-// move data page, update object index in memory
-// when reached end of lookup, store updated object index
-// pop object scan lookup entry index
-// repeat loop until end of object lookup
-// scan object lookup again for remaining object index pages, move to new page in other block
-//
-s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
- s32_t res = SPIFFS_OK;
- const int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
- // this is the global localizer being pushed and popped
- int cur_entry = 0;
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
- spiffs_gc gc; // our stack frame/state
- spiffs_page_ix cur_pix = 0;
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
-
- SPIFFS_GC_DBG("gc_clean: cleaning block "_SPIPRIbl"\n", bix);
-
- memset(&gc, 0, sizeof(spiffs_gc));
- gc.state = FIND_OBJ_DATA;
-
- if (fs->free_cursor_block_ix == bix) {
- // move free cursor to next block, cannot use free pages from the block we want to clean
- fs->free_cursor_block_ix = (bix + 1) % fs->block_count;
- fs->free_cursor_obj_lu_entry = 0;
- SPIFFS_GC_DBG("gc_clean: move free cursor to block "_SPIPRIbl"\n", fs->free_cursor_block_ix);
- }
-
- while (res == SPIFFS_OK && gc.state != FINISHED) {
- SPIFFS_GC_DBG("gc_clean: state = "_SPIPRIi" entry:"_SPIPRIi"\n", gc.state, cur_entry);
- gc.obj_id_found = 0; // reset (to no found data page)
-
- // scan through lookup pages
- int obj_lookup_page = cur_entry / entries_per_page;
- u8_t scan = 1;
- // check each object lookup page
- while (scan && res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
- SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each object lookup entry
- while (scan && res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
- spiffs_obj_id obj_id = obj_lu_buf[cur_entry - entry_offset];
- cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, cur_entry);
-
- // act upon object id depending on gc state
- switch (gc.state) {
- case FIND_OBJ_DATA:
- // find a data page
- if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
- ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) {
- // found a data page, stop scanning and handle in switch case below
- SPIFFS_GC_DBG("gc_clean: FIND_DATA state:"_SPIPRIi" - found obj id "_SPIPRIid"\n", gc.state, obj_id);
- gc.obj_id_found = 1;
- gc.cur_obj_id = obj_id;
- gc.cur_data_pix = cur_pix;
- scan = 0;
- }
- break;
- case MOVE_OBJ_DATA:
- // evacuate found data pages for corresponding object index we have in memory,
- // update memory representation
- if (obj_id == gc.cur_obj_id) {
- spiffs_page_header p_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA found data page "_SPIPRIid":"_SPIPRIsp" @ "_SPIPRIpg"\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
- if (SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix) != gc.cur_objix_spix) {
- SPIFFS_GC_DBGF("gc_clean: MOVE_DATA no objix spix match, take in another run\n");
- } else {
- spiffs_page_ix new_data_pix;
- if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
- // move page
- res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_data_pix);
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA move objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg" to "_SPIPRIpg"\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix, new_data_pix);
- SPIFFS_CHECK_RES(res);
- // move wipes obj_lu, reload it
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
- SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
- } else {
- // page is deleted but not deleted in lookup, scrap it -
- // might seem unnecessary as we will erase this block, but
- // we might get aborted
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA wipe objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg"\n", obj_id, p_hdr.span_ix, cur_pix);
- res = spiffs_page_delete(fs, cur_pix);
- SPIFFS_CHECK_RES(res);
- new_data_pix = SPIFFS_OBJ_ID_FREE;
- }
- // update memory representation of object index page with new data page
- if (gc.cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[p_hdr.span_ix] = new_data_pix;
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
- } else {
- // update object index page
- ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)] = new_data_pix;
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
- }
- }
- }
- break;
- case MOVE_OBJ_IX:
- // find and evacuate object index pages
- if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
- (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
- // found an index object id
- spiffs_page_header p_hdr;
- spiffs_page_ix new_pix;
- // load header
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
- if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
- // move page
- res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_pix);
- SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX move objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg" to "_SPIPRIpg"\n", obj_id, p_hdr.span_ix, cur_pix, new_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)&p_hdr,
- SPIFFS_EV_IX_MOV, obj_id, p_hdr.span_ix, new_pix, 0);
- // move wipes obj_lu, reload it
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
- SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
- } else {
- // page is deleted but not deleted in lookup, scrap it -
- // might seem unnecessary as we will erase this block, but
- // we might get aborted
- SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX wipe objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg"\n", obj_id, p_hdr.span_ix, cur_pix);
- res = spiffs_page_delete(fs, cur_pix);
- if (res == SPIFFS_OK) {
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)0,
- SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0);
- }
- }
- SPIFFS_CHECK_RES(res);
- }
- break;
- default:
- scan = 0;
- break;
- } // switch gc state
- cur_entry++;
- } // per entry
- obj_lookup_page++; // no need to check scan variable here, obj_lookup_page is set in start of loop
- } // per object lookup page
- if (res != SPIFFS_OK) break;
-
- // state finalization and switch
- switch (gc.state) {
- case FIND_OBJ_DATA:
- if (gc.obj_id_found) {
- // handle found data page -
- // find out corresponding obj ix page and load it to memory
- spiffs_page_header p_hdr;
- spiffs_page_ix objix_pix;
- gc.stored_scan_entry_index = cur_entry; // push cursor
- cur_entry = 0; // restart scan from start
- gc.state = MOVE_OBJ_DATA;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t *)&p_hdr);
- SPIFFS_CHECK_RES(res);
- gc.cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix);
- SPIFFS_GC_DBG("gc_clean: FIND_DATA find objix span_ix:"_SPIPRIsp"\n", gc.cur_objix_spix);
- res = spiffs_obj_lu_find_id_and_span(fs, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix, 0, &objix_pix);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- // on borked systems we might get an ERR_NOT_FOUND here -
- // this is handled by simply deleting the page as it is not referenced
- // from anywhere
- SPIFFS_GC_DBG("gc_clean: FIND_OBJ_DATA objix not found! Wipe page "_SPIPRIpg"\n", gc.cur_data_pix);
- res = spiffs_page_delete(fs, gc.cur_data_pix);
- SPIFFS_CHECK_RES(res);
- // then we restore states and continue scanning for data pages
- cur_entry = gc.stored_scan_entry_index; // pop cursor
- gc.state = FIND_OBJ_DATA;
- break; // done
- }
- SPIFFS_CHECK_RES(res);
- SPIFFS_GC_DBG("gc_clean: FIND_DATA found object index at page "_SPIPRIpg"\n", objix_pix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- // cannot allow a gc if the presumed index in fact is no index, a
- // check must run or lot of data may be lost
- SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix);
- gc.cur_objix_pix = objix_pix;
- } else {
- // no more data pages found, passed thru all block, start evacuating object indices
- gc.state = MOVE_OBJ_IX;
- cur_entry = 0; // restart entry scan index
- }
- break;
- case MOVE_OBJ_DATA: {
- // store modified objix (hdr) page residing in memory now that all
- // data pages belonging to this object index and residing in the block
- // we want to evacuate
- spiffs_page_ix new_objix_pix;
- gc.state = FIND_OBJ_DATA;
- cur_entry = gc.stored_scan_entry_index; // pop cursor
- if (gc.cur_objix_spix == 0) {
- // store object index header page
- res = spiffs_object_update_index_hdr(fs, 0, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_pix, fs->work, 0, 0, 0, &new_objix_pix);
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp"\n", new_objix_pix, 0);
- SPIFFS_CHECK_RES(res);
- } else {
- // store object index page
- res = spiffs_page_move(fs, 0, fs->work, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, gc.cur_objix_pix, &new_objix_pix);
- SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, "_SPIPRIpg":"_SPIPRIsp"\n", new_objix_pix, objix->p_hdr.span_ix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work,
- SPIFFS_EV_IX_UPD, gc.cur_obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
- }
- }
- break;
- case MOVE_OBJ_IX:
- // scanned thru all block, no more object indices found - our work here is done
- gc.state = FINISHED;
- break;
- default:
- cur_entry = 0;
- break;
- } // switch gc.state
- SPIFFS_GC_DBG("gc_clean: state-> "_SPIPRIi"\n", gc.state);
- } // while state != FINISHED
-
-
- return res;
-}
-
-#endif // !SPIFFS_READ_ONLY
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_hydrogen.c b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_hydrogen.c
deleted file mode 100644
index 7290e676..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_hydrogen.c
+++ /dev/null
@@ -1,1466 +0,0 @@
-/*
- * spiffs_hydrogen.c
- *
- * Created on: Jun 16, 2013
- * Author: petera
- */
-
-#include "spiffs.h"
-#include "spiffs_nucleus.h"
-#include "printf.h"
-
-#if SPIFFS_CACHE == 1
-static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
-#endif
-
-#if SPIFFS_BUFFER_HELP
-u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
- return num_descs * sizeof(spiffs_fd);
-}
-#if SPIFFS_CACHE
-u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
- return sizeof(spiffs_cache) + num_pages * (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs));
-}
-#endif
-#endif
-
-u8_t SPIFFS_mounted(spiffs *fs) {
- return SPIFFS_CHECK_MOUNT(fs);
-}
-
-s32_t SPIFFS_format(spiffs *fs) {
-#if SPIFFS_READ_ONLY
- (void)fs;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- if (SPIFFS_CHECK_MOUNT(fs)) {
- fs->err_code = SPIFFS_ERR_MOUNTED;
- return -1;
- }
-
- s32_t res;
- SPIFFS_LOCK(fs);
-
- spiffs_block_ix bix = 0;
- while (bix < fs->block_count) {
- fs->max_erase_count = 0;
- res = spiffs_erase_block(fs, bix);
- if (res != SPIFFS_OK) {
- res = SPIFFS_ERR_ERASE_FAIL;
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- bix++;
- }
-
- SPIFFS_UNLOCK(fs);
-
- return 0;
-#endif // SPIFFS_READ_ONLY
-}
-
-#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
-
-s32_t SPIFFS_probe_fs(spiffs_config *config) {
- SPIFFS_API_DBG("%s\n", __func__);
- s32_t res = spiffs_probe(config);
- return res;
-}
-
-#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
-
-s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
- u8_t *fd_space, u32_t fd_space_size,
- void *cache, u32_t cache_size,
- spiffs_check_callback check_cb_f) {
- SPIFFS_API_DBG("%s "
- " sz:"_SPIPRIi " logpgsz:"_SPIPRIi " logblksz:"_SPIPRIi " perasz:"_SPIPRIi
- " addr:"_SPIPRIad
- " fdsz:"_SPIPRIi " cachesz:"_SPIPRIi
- "\n",
- __func__,
- SPIFFS_CFG_PHYS_SZ(fs),
- SPIFFS_CFG_LOG_PAGE_SZ(fs),
- SPIFFS_CFG_LOG_BLOCK_SZ(fs),
- SPIFFS_CFG_PHYS_ERASE_SZ(fs),
- SPIFFS_CFG_PHYS_ADDR(fs),
- fd_space_size, cache_size);
- void *user_data;
- SPIFFS_LOCK(fs);
- user_data = fs->user_data;
- memset(fs, 0, sizeof(spiffs));
- _SPIFFS_MEMCPY(&fs->cfg, config, sizeof(spiffs_config));
- fs->user_data = user_data;
- fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- fs->work = &work[0];
- fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)];
- memset(fd_space, 0, fd_space_size);
- // align fd_space pointer to pointer size byte boundary
- u8_t ptr_size = sizeof(void *);
- u8_t addr_lsb = ((u8_t)(intptr_t)fd_space) & (ptr_size - 1);
- if (addr_lsb) {
- fd_space += (ptr_size - addr_lsb);
- fd_space_size -= (ptr_size - addr_lsb);
- }
- fs->fd_space = fd_space;
- fs->fd_count = (fd_space_size / sizeof(spiffs_fd));
-
- // align cache pointer to 4 byte boundary
- addr_lsb = ((u8_t)(intptr_t)cache) & (ptr_size - 1);
- if (addr_lsb) {
- u8_t *cache_8 = (u8_t *)cache;
- cache_8 += (ptr_size - addr_lsb);
- cache = cache_8;
- cache_size -= (ptr_size - addr_lsb);
- }
- if (cache_size & (ptr_size - 1)) {
- cache_size -= (cache_size & (ptr_size - 1));
- }
-
-#if SPIFFS_CACHE
- fs->cache = cache;
- fs->cache_size = (cache_size > (SPIFFS_CFG_LOG_PAGE_SZ(fs) * 32)) ? SPIFFS_CFG_LOG_PAGE_SZ(fs) * 32 : cache_size;
- spiffs_cache_init(fs);
-#endif
-
- s32_t res;
-
-#if SPIFFS_USE_MAGIC
- res = SPIFFS_CHECK_MAGIC_POSSIBLE(fs) ? SPIFFS_OK : SPIFFS_ERR_MAGIC_NOT_POSSIBLE;
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-#endif
-
- fs->config_magic = SPIFFS_CONFIG_MAGIC;
-
- res = spiffs_obj_lu_scan(fs);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_DBG("page index byte len: "_SPIPRIi"\n", (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs));
- SPIFFS_DBG("object lookup pages: "_SPIPRIi"\n", (u32_t)SPIFFS_OBJ_LOOKUP_PAGES(fs));
- SPIFFS_DBG("page pages per block: "_SPIPRIi"\n", (u32_t)SPIFFS_PAGES_PER_BLOCK(fs));
- SPIFFS_DBG("page header length: "_SPIPRIi"\n", (u32_t)sizeof(spiffs_page_header));
- SPIFFS_DBG("object header index entries: "_SPIPRIi"\n", (u32_t)SPIFFS_OBJ_HDR_IX_LEN(fs));
- SPIFFS_DBG("object index entries: "_SPIPRIi"\n", (u32_t)SPIFFS_OBJ_IX_LEN(fs));
- SPIFFS_DBG("available file descriptors: "_SPIPRIi"\n", (u32_t)fs->fd_count);
- SPIFFS_DBG("free blocks: "_SPIPRIi"\n", (u32_t)fs->free_blocks);
-
- fs->check_cb_f = check_cb_f;
-
- fs->mounted = 1;
-
- SPIFFS_UNLOCK(fs);
-
- return 0;
-}
-
-void SPIFFS_unmount(spiffs *fs) {
- SPIFFS_API_DBG("%s\n", __func__);
- if (!SPIFFS_CHECK_CFG(fs) || !SPIFFS_CHECK_MOUNT(fs)) return;
- SPIFFS_LOCK(fs);
- u32_t i;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr != 0) {
-#if SPIFFS_CACHE
- (void)spiffs_fflush_cache(fs, cur_fd->file_nbr);
-#endif
- spiffs_fd_return(fs, cur_fd->file_nbr);
- }
- }
- fs->mounted = 0;
-
- SPIFFS_UNLOCK(fs);
-}
-
-s32_t SPIFFS_errno(spiffs *fs) {
- return fs->err_code;
-}
-
-void SPIFFS_clearerr(spiffs *fs) {
- SPIFFS_API_DBG("%s\n", __func__);
- fs->err_code = SPIFFS_OK;
-}
-
-s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
- SPIFFS_API_DBG("%s '%s'\n", __func__, path);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)path;
- (void)mode;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- (void)mode;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
- SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
- }
- SPIFFS_LOCK(fs);
- spiffs_obj_id obj_id;
- s32_t res;
-
- res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, (const u8_t *)path);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- res = spiffs_object_create(fs, obj_id, (const u8_t *)path, 0, SPIFFS_TYPE_FILE, 0);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- SPIFFS_UNLOCK(fs);
- return 0;
-#endif // SPIFFS_READ_ONLY
-}
-
-spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) {
- SPIFFS_API_DBG("%s '%s' "_SPIPRIfl "\n", __func__, path, flags);
- (void)mode;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
- SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
- }
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- spiffs_page_ix pix;
-
-#if SPIFFS_READ_ONLY
- // not valid flags in read only mode
- flags &= ~(SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_TRUNC);
-#endif // SPIFFS_READ_ONLY
-
- s32_t res = spiffs_fd_find_new(fs, &fd, path);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t *)path, &pix);
- if ((flags & SPIFFS_O_CREAT) == 0) {
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- if (res == SPIFFS_OK &&
- (flags & (SPIFFS_O_CREAT | SPIFFS_O_EXCL)) == (SPIFFS_O_CREAT | SPIFFS_O_EXCL)) {
- // creat and excl and file exists - fail
- res = SPIFFS_ERR_FILE_EXISTS;
- spiffs_fd_return(fs, fd->file_nbr);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- if ((flags & SPIFFS_O_CREAT) && res == SPIFFS_ERR_NOT_FOUND) {
-#if !SPIFFS_READ_ONLY
- spiffs_obj_id obj_id;
- // no need to enter conflicting name here, already looked for it above
- res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, 0);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- res = spiffs_object_create(fs, obj_id, (const u8_t *)path, 0, SPIFFS_TYPE_FILE, &pix);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- flags &= ~SPIFFS_O_TRUNC;
-#endif // !SPIFFS_READ_ONLY
- } else {
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
- res = spiffs_object_open_by_page(fs, pix, fd, flags, mode);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-#if !SPIFFS_READ_ONLY
- if (flags & SPIFFS_O_TRUNC) {
- res = spiffs_object_truncate(fd, 0, 0);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-#endif // !SPIFFS_READ_ONLY
-
- fd->fdoffset = 0;
-
- SPIFFS_UNLOCK(fs);
-
- return SPIFFS_FH_OFFS(fs, fd->file_nbr);
-}
-
-spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
- SPIFFS_API_DBG("%s '%s':"_SPIPRIid " "_SPIPRIfl "\n", __func__, e->name, e->obj_id, flags);
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
-
- s32_t res = spiffs_fd_find_new(fs, &fd, 0);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_open_by_page(fs, e->pix, fd, flags, mode);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-#if !SPIFFS_READ_ONLY
- if (flags & SPIFFS_O_TRUNC) {
- res = spiffs_object_truncate(fd, 0, 0);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-#endif // !SPIFFS_READ_ONLY
-
- fd->fdoffset = 0;
-
- SPIFFS_UNLOCK(fs);
-
- return SPIFFS_FH_OFFS(fs, fd->file_nbr);
-}
-
-spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode) {
- SPIFFS_API_DBG("%s "_SPIPRIpg " "_SPIPRIfl "\n", __func__, page_ix, flags);
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
-
- s32_t res = spiffs_fd_find_new(fs, &fd, 0);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if (SPIFFS_IS_LOOKUP_PAGE(fs, page_ix)) {
- res = SPIFFS_ERR_NOT_A_FILE;
- spiffs_fd_return(fs, fd->file_nbr);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- res = spiffs_object_open_by_page(fs, page_ix, fd, flags, mode);
- if (res == SPIFFS_ERR_IS_FREE ||
- res == SPIFFS_ERR_DELETED ||
- res == SPIFFS_ERR_NOT_FINALIZED ||
- res == SPIFFS_ERR_NOT_INDEX ||
- res == SPIFFS_ERR_INDEX_SPAN_MISMATCH) {
- res = SPIFFS_ERR_NOT_A_FILE;
- }
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
-#if !SPIFFS_READ_ONLY
- if (flags & SPIFFS_O_TRUNC) {
- res = spiffs_object_truncate(fd, 0, 0);
- if (res < SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-#endif // !SPIFFS_READ_ONLY
-
- fd->fdoffset = 0;
-
- SPIFFS_UNLOCK(fs);
-
- return SPIFFS_FH_OFFS(fs, fd->file_nbr);
-}
-
-static s32_t spiffs_hydro_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- s32_t res;
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if ((fd->flags & SPIFFS_O_RDONLY) == 0) {
- res = SPIFFS_ERR_NOT_READABLE;
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- if (fd->size == SPIFFS_UNDEFINED_LEN && len > 0) {
- // special case for zero sized files
- res = SPIFFS_ERR_END_OF_OBJECT;
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
-#if SPIFFS_CACHE_WR
- spiffs_fflush_cache(fs, fh);
-#endif
-
- if (fd->fdoffset + len >= fd->size) {
- // reading beyond file size
- s32_t avail = fd->size - fd->fdoffset;
- if (avail <= 0) {
- SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_END_OF_OBJECT);
- }
- res = spiffs_object_read(fd, fd->fdoffset, avail, (u8_t *)buf);
- if (res == SPIFFS_ERR_END_OF_OBJECT) {
- fd->fdoffset += avail;
- SPIFFS_UNLOCK(fs);
- return avail;
- } else {
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- len = avail;
- }
- } else {
- // reading within file size
- res = spiffs_object_read(fd, fd->fdoffset, len, (u8_t *)buf);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
- fd->fdoffset += len;
-
- SPIFFS_UNLOCK(fs);
-
- return len;
-}
-
-s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
- SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi "\n", __func__, fh, len);
- s32_t res = spiffs_hydro_read(fs, fh, buf, len);
- if (res == SPIFFS_ERR_END_OF_OBJECT) {
- res = 0;
- }
- return res;
-}
-
-
-#if !SPIFFS_READ_ONLY
-static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) {
- (void)fs;
- s32_t res = SPIFFS_OK;
- s32_t remaining = len;
- if (fd->size != SPIFFS_UNDEFINED_LEN && offset < fd->size) {
- s32_t m_len = MIN((s32_t)(fd->size - offset), len);
- res = spiffs_object_modify(fd, offset, (u8_t *)buf, m_len);
- SPIFFS_CHECK_RES(res);
- remaining -= m_len;
- u8_t *buf_8 = (u8_t *)buf;
- buf_8 += m_len;
- buf = buf_8;
- offset += m_len;
- }
- if (remaining > 0) {
- res = spiffs_object_append(fd, offset, (u8_t *)buf, remaining);
- SPIFFS_CHECK_RES(res);
- }
- return len;
-
-}
-#endif // !SPIFFS_READ_ONLY
-
-s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
- SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi "\n", __func__, fh, len);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)fh;
- (void)buf;
- (void)len;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- s32_t res;
- u32_t offset;
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if ((fd->flags & SPIFFS_O_WRONLY) == 0) {
- res = SPIFFS_ERR_NOT_WRITABLE;
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- if ((fd->flags & SPIFFS_O_APPEND)) {
- fd->fdoffset = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size;
- }
- offset = fd->fdoffset;
-
-#if SPIFFS_CACHE_WR
- if (fd->cache_page == 0) {
- // see if object id is associated with cache already
- fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
- }
-#endif
- if (fd->flags & SPIFFS_O_APPEND) {
- if (fd->size == SPIFFS_UNDEFINED_LEN) {
- offset = 0;
- } else {
- offset = fd->size;
- }
-#if SPIFFS_CACHE_WR
- if (fd->cache_page) {
- offset = MAX(offset, fd->cache_page->ucache.swrc.offset + fd->cache_page->ucache.swrc.size);
- }
-#endif
- }
-
-#if SPIFFS_CACHE_WR
- if ((fd->flags & SPIFFS_O_DIRECT) == 0) {
- if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
- // small write, try to cache it
- u8_t alloc_cpage = 1;
- if (fd->cache_page) {
- // have a cached page for this fd already, check cache page boundaries
- if (offset < fd->cache_page->ucache.swrc.offset || // writing before cache
- offset > fd->cache_page->ucache.swrc.offset + fd->cache_page->ucache.swrc.size || // writing after cache
- offset + len > fd->cache_page->ucache.swrc.offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) { // writing beyond cache page
- // boundary violation, write back cache first and allocate new
- SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", boundary viol, offs:"_SPIPRIi" size:"_SPIPRIi"\n",
- fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->ucache.swrc.offset, fd->cache_page->ucache.swrc.size);
- res = spiffs_hydro_write(fs, fd,
- spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
- fd->cache_page->ucache.swrc.offset, fd->cache_page->ucache.swrc.size);
- spiffs_cache_fd_release(fs, fd->cache_page);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- } else {
- // writing within cache
- alloc_cpage = 0;
- }
- }
-
- if (alloc_cpage) {
- fd->cache_page = spiffs_cache_page_allocate_by_fd(fs, fd);
- if (fd->cache_page) {
- fd->cache_page->ucache.swrc.offset = offset;
- fd->cache_page->ucache.swrc.size = 0;
- SPIFFS_CACHE_DBG("CACHE_WR_ALLO: allocating cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid"\n",
- fd->cache_page->ix, fd->file_nbr, fd->obj_id);
- }
- }
-
- if (fd->cache_page) {
- u32_t offset_in_cpage = offset - fd->cache_page->ucache.swrc.offset;
- SPIFFS_CACHE_DBG("CACHE_WR_WRITE: storing to cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", offs "_SPIPRIi":"_SPIPRIi" len "_SPIPRIi"\n",
- fd->cache_page->ix, fd->file_nbr, fd->obj_id,
- offset, offset_in_cpage, len);
- spiffs_cache *cache = spiffs_get_cache(fs);
- u8_t *cpage_data = spiffs_get_cache_page(fs, cache, fd->cache_page->ix);
-#ifdef _SPIFFS_TEST
- {
- intptr_t __a1 = (u8_t *)&cpage_data[offset_in_cpage] - (u8_t *)cache;
- intptr_t __a2 = (u8_t *)&cpage_data[offset_in_cpage] + len - (u8_t *)cache;
- intptr_t __b = sizeof(spiffs_cache) + cache->cpage_count * (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs));
- if (__a1 > __b || __a2 > __b) {
- printf("FATAL OOB: CACHE_WR: memcpy to cache buffer ixs:%4ld..%4ld of %4ld\n", __a1, __a2, __b);
- ERREXIT();
- }
- }
-#endif
- _SPIFFS_MEMCPY(&cpage_data[offset_in_cpage], buf, len);
- fd->cache_page->ucache.swrc.size = MAX(fd->cache_page->ucache.swrc.size, offset_in_cpage + len);
- fd->fdoffset += len;
- SPIFFS_UNLOCK(fs);
- return len;
- } else {
- res = spiffs_hydro_write(fs, fd, buf, offset, len);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- fd->fdoffset += len;
- SPIFFS_UNLOCK(fs);
- return res;
- }
- } else {
- // big write, no need to cache it - but first check if there is a cached write already
- if (fd->cache_page) {
- // write back cache first
- SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", big write, offs:"_SPIPRIi" size:"_SPIPRIi"\n",
- fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->ucache.swrc.offset, fd->cache_page->ucache.swrc.size);
- res = spiffs_hydro_write(fs, fd,
- spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
- fd->cache_page->ucache.swrc.offset, fd->cache_page->ucache.swrc.size);
- spiffs_cache_fd_release(fs, fd->cache_page);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- // data written below
- }
- }
- }
-#endif
-
- res = spiffs_hydro_write(fs, fd, buf, offset, len);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- fd->fdoffset += len;
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-#endif // SPIFFS_READ_ONLY
-}
-
-s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
- SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi " %s\n", __func__, fh, offs, (const char *[]) {"SET", "CUR", "END", "???"}[MIN(whence, 3)]);
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- s32_t res;
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
-#if SPIFFS_CACHE_WR
- spiffs_fflush_cache(fs, fh);
-#endif
-
- s32_t file_size = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size;
-
- switch (whence) {
- case SPIFFS_SEEK_CUR:
- offs = fd->fdoffset + offs;
- break;
- case SPIFFS_SEEK_END:
- offs = file_size + offs;
- break;
- }
- if (offs < 0) {
- SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_SEEK_BOUNDS);
- }
- if (offs > file_size) {
- fd->fdoffset = file_size;
- res = SPIFFS_ERR_END_OF_OBJECT;
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- spiffs_span_ix data_spix = (offs > 0 ? (offs - 1) : 0) / SPIFFS_DATA_PAGE_SIZE(fs);
- spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- if (fd->cursor_objix_spix != objix_spix) {
- spiffs_page_ix pix;
- res = spiffs_obj_lu_find_id_and_span(
- fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, &pix);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- fd->cursor_objix_spix = objix_spix;
- fd->cursor_objix_pix = pix;
- }
- fd->fdoffset = offs;
-
- SPIFFS_UNLOCK(fs);
-
- return offs;
-}
-
-s32_t SPIFFS_remove(spiffs *fs, const char *path) {
- SPIFFS_API_DBG("%s '%s'\n", __func__, path);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)path;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
- SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
- }
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- spiffs_page_ix pix;
- s32_t res;
-
- res = spiffs_fd_find_new(fs, &fd, 0);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t *)path, &pix);
- if (res != SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_open_by_page(fs, pix, fd, 0, 0);
- if (res != SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_truncate(fd, 0, 1);
- if (res != SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
- return 0;
-#endif // SPIFFS_READ_ONLY
-}
-
-s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)fh;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- s32_t res;
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if ((fd->flags & SPIFFS_O_WRONLY) == 0) {
- res = SPIFFS_ERR_NOT_WRITABLE;
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
-#if SPIFFS_CACHE_WR
- spiffs_cache_fd_release(fs, fd->cache_page);
-#endif
-
- res = spiffs_object_truncate(fd, 0, 1);
-
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
-
- return 0;
-#endif // SPIFFS_READ_ONLY
-}
-
-static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) {
- (void)fh;
- spiffs_page_object_ix_header objix_hdr;
- spiffs_obj_id obj_id;
- s32_t res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh,
- SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- SPIFFS_API_CHECK_RES(fs, res);
-
- u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, pix)) +
- SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_obj_id);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, fh,
- obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
- SPIFFS_API_CHECK_RES(fs, res);
-
- s->obj_id = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- s->type = objix_hdr.type;
- s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
- s->pix = pix;
- strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN - 1);
-#if SPIFFS_OBJ_META_LEN
- _SPIFFS_MEMCPY(s->meta, objix_hdr.meta, SPIFFS_OBJ_META_LEN);
-#endif
-
- return res;
-}
-
-s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
- SPIFFS_API_DBG("%s '%s'\n", __func__, path);
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) {
- SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
- }
- SPIFFS_LOCK(fs);
-
- s32_t res;
- spiffs_page_ix pix;
-
- res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t *)path, &pix);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_stat_pix(fs, pix, 0, s);
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-}
-
-s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_fd *fd;
- s32_t res;
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
-#if SPIFFS_CACHE_WR
- spiffs_fflush_cache(fs, fh);
-#endif
-
- res = spiffs_stat_pix(fs, fd->objix_hdr_pix, fh, s);
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-}
-
-// Checks if there are any cached writes for the object id associated with
-// given filehandle. If so, these writes are flushed.
-#if SPIFFS_CACHE == 1
-static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
- (void)fs;
- (void)fh;
- s32_t res = SPIFFS_OK;
-#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
-
- spiffs_fd *fd;
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES(fs, res);
-
- if ((fd->flags & SPIFFS_O_DIRECT) == 0) {
- if (fd->cache_page == 0) {
- // see if object id is associated with cache already
- fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
- }
- if (fd->cache_page) {
- SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", flush, offs:"_SPIPRIi" size:"_SPIPRIi"\n",
- fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->ucache.swrc.offset, fd->cache_page->ucache.swrc.size);
- res = spiffs_hydro_write(fs, fd,
- spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
- fd->cache_page->ucache.swrc.offset, fd->cache_page->ucache.swrc.size);
- if (res < SPIFFS_OK) {
- fs->err_code = res;
- }
- spiffs_cache_fd_release(fs, fd->cache_page);
- }
- }
-#endif
-
- return res;
-}
-#endif
-
-s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
- (void)fh;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- s32_t res = SPIFFS_OK;
-#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
- SPIFFS_LOCK(fs);
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fflush_cache(fs, fh);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- SPIFFS_UNLOCK(fs);
-#endif
-
- return res;
-}
-
-s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
-
- s32_t res = SPIFFS_OK;
- SPIFFS_LOCK(fs);
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
-#if SPIFFS_CACHE
- res = spiffs_fflush_cache(fs, fh);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-#endif
- res = spiffs_fd_return(fs, fh);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-}
-
-s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_path) {
- SPIFFS_API_DBG("%s %s %s\n", __func__, old_path, new_path);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)old_path;
- (void)new_path;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- if (strlen(new_path) > SPIFFS_OBJ_NAME_LEN - 1 ||
- strlen(old_path) > SPIFFS_OBJ_NAME_LEN - 1) {
- SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG);
- }
- SPIFFS_LOCK(fs);
-
- spiffs_page_ix pix_old, pix_dummy;
- spiffs_fd *fd;
-
- s32_t res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t *)old_path, &pix_old);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t *)new_path, &pix_dummy);
- if (res == SPIFFS_ERR_NOT_FOUND) {
- res = SPIFFS_OK;
- } else if (res == SPIFFS_OK) {
- res = SPIFFS_ERR_CONFLICTING_NAME;
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_fd_find_new(fs, &fd, 0);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_open_by_page(fs, pix_old, fd, 0, 0);
- if (res != SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (const u8_t *)new_path,
- 0, 0, &pix_dummy);
-#if SPIFFS_TEMPORAL_FD_CACHE
- if (res == SPIFFS_OK) {
- spiffs_fd_temporal_cache_rehash(fs, old_path, new_path);
- }
-#endif
-
- spiffs_fd_return(fs, fd->file_nbr);
-
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-#endif // SPIFFS_READ_ONLY
-}
-
-#if SPIFFS_OBJ_META_LEN
-s32_t SPIFFS_update_meta(spiffs *fs, const char *name, const void *meta) {
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)name;
- (void)meta;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- spiffs_page_ix pix, pix_dummy;
- spiffs_fd *fd;
-
- s32_t res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t *)name, &pix);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_fd_find_new(fs, &fd, 0);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_open_by_page(fs, pix, fd, 0, 0);
- if (res != SPIFFS_OK) {
- spiffs_fd_return(fs, fd->file_nbr);
- }
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, 0, meta,
- 0, &pix_dummy);
-
- spiffs_fd_return(fs, fd->file_nbr);
-
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-#endif // SPIFFS_READ_ONLY
-}
-
-s32_t SPIFFS_fupdate_meta(spiffs *fs, spiffs_file fh, const void *meta) {
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)fh;
- (void)meta;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- s32_t res;
- spiffs_fd *fd;
- spiffs_page_ix pix_dummy;
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if ((fd->flags & SPIFFS_O_WRONLY) == 0) {
- res = SPIFFS_ERR_NOT_WRITABLE;
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, 0, meta,
- 0, &pix_dummy);
-
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
-
- return res;
-#endif // SPIFFS_READ_ONLY
-}
-#endif // SPIFFS_OBJ_META_LEN
-
-spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
- SPIFFS_API_DBG("%s\n", __func__);
- (void)name;
-
- if (!SPIFFS_CHECK_CFG((fs))) {
- (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
- return 0;
- }
-
- if (!SPIFFS_CHECK_MOUNT(fs)) {
- fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
- return 0;
- }
-
- d->fs = fs;
- d->block = 0;
- d->entry = 0;
- return d;
-}
-
-static s32_t spiffs_read_dir_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- const void *user_const_p,
- void *user_var_p) {
- (void)user_const_p;
- s32_t res;
- spiffs_page_object_ix_header objix_hdr;
- if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
- (obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
- return SPIFFS_VIS_COUNTINUE;
- }
-
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- if (res != SPIFFS_OK) return res;
- if ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) &&
- objix_hdr.p_hdr.span_ix == 0 &&
- (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
- struct spiffs_dirent *e = (struct spiffs_dirent *)user_var_p;
- e->obj_id = obj_id;
- strcpy((char *)e->name, (char *)objix_hdr.name);
- e->type = objix_hdr.type;
- e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
- e->pix = pix;
-#if SPIFFS_OBJ_META_LEN
- _SPIFFS_MEMCPY(e->meta, objix_hdr.meta, SPIFFS_OBJ_META_LEN);
-#endif
- return SPIFFS_OK;
- }
- return SPIFFS_VIS_COUNTINUE;
-}
-
-struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
- SPIFFS_API_DBG("%s\n", __func__);
- if (!SPIFFS_CHECK_MOUNT(d->fs)) {
- d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
- return 0;
- }
- SPIFFS_LOCK(d->fs);
-
- spiffs_block_ix bix;
- int entry;
- s32_t res;
- struct spiffs_dirent *ret = 0;
-
- res = spiffs_obj_lu_find_entry_visitor(d->fs,
- d->block,
- d->entry,
- SPIFFS_VIS_NO_WRAP,
- 0,
- spiffs_read_dir_v,
- 0,
- e,
- &bix,
- &entry);
- if (res == SPIFFS_OK) {
- d->block = bix;
- d->entry = entry + 1;
- e->obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- ret = e;
- } else {
- d->fs->err_code = res;
- }
- SPIFFS_UNLOCK(d->fs);
- return ret;
-}
-
-s32_t SPIFFS_closedir(spiffs_DIR *d) {
- SPIFFS_API_DBG("%s\n", __func__);
- SPIFFS_API_CHECK_CFG(d->fs);
- SPIFFS_API_CHECK_MOUNT(d->fs);
- return 0;
-}
-
-s32_t SPIFFS_check(spiffs *fs) {
- SPIFFS_API_DBG("%s\n", __func__);
-#if SPIFFS_READ_ONLY
- (void)fs;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- res = spiffs_lookup_consistency_check(fs, 0);
-
- res = spiffs_object_index_consistency_check(fs);
-
- res = spiffs_page_consistency_check(fs);
-
- res = spiffs_obj_lu_scan(fs);
-
- SPIFFS_UNLOCK(fs);
- return res;
-#endif // SPIFFS_READ_ONLY
-}
-
-s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
- SPIFFS_API_DBG("%s\n", __func__);
- s32_t res = SPIFFS_OK;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- u32_t pages_per_block = SPIFFS_PAGES_PER_BLOCK(fs);
- u32_t blocks = fs->block_count;
- u32_t obj_lu_pages = SPIFFS_OBJ_LOOKUP_PAGES(fs);
- u32_t data_page_size = SPIFFS_DATA_PAGE_SIZE(fs);
- u32_t total_data_pages = (blocks - 2) * (pages_per_block - obj_lu_pages) + 1; // -2 for spare blocks, +1 for emergency page
-
- if (total) {
- *total = total_data_pages * data_page_size;
- }
-
- if (used) {
- *used = fs->stats_p_allocated * data_page_size;
- }
-
- SPIFFS_UNLOCK(fs);
- return res;
-}
-
-s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
- SPIFFS_API_DBG("%s "_SPIPRIi "\n", __func__, max_free_pages);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)max_free_pages;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- res = spiffs_gc_quick(fs, max_free_pages);
-
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- SPIFFS_UNLOCK(fs);
- return 0;
-#endif // SPIFFS_READ_ONLY
-}
-
-
-s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
- SPIFFS_API_DBG("%s "_SPIPRIi "\n", __func__, size);
-#if SPIFFS_READ_ONLY
- (void)fs;
- (void)size;
- return SPIFFS_ERR_RO_NOT_IMPL;
-#else
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- res = spiffs_gc_check(fs, size);
-
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- SPIFFS_UNLOCK(fs);
- return 0;
-#endif // SPIFFS_READ_ONLY
-}
-
-s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
-
- spiffs_fd *fd;
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
-#if SPIFFS_CACHE_WR
- res = spiffs_fflush_cache(fs, fh);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-#endif
-
- res = (fd->fdoffset >= (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size));
-
- SPIFFS_UNLOCK(fs);
- return res;
-}
-
-s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
-
- spiffs_fd *fd;
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
-#if SPIFFS_CACHE_WR
- res = spiffs_fflush_cache(fs, fh);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-#endif
-
- res = fd->fdoffset;
-
- SPIFFS_UNLOCK(fs);
- return res;
-}
-
-s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func) {
- SPIFFS_API_DBG("%s\n", __func__);
- SPIFFS_LOCK(fs);
- fs->file_cb_f = cb_func;
- SPIFFS_UNLOCK(fs);
- return 0;
-}
-
-#if SPIFFS_IX_MAP
-
-s32_t SPIFFS_ix_map(spiffs *fs, spiffs_file fh, spiffs_ix_map *map,
- u32_t offset, u32_t len, spiffs_page_ix *map_buf) {
- SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi " "_SPIPRIi "\n", __func__, fh, offset, len);
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
-
- spiffs_fd *fd;
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if (fd->ix_map) {
- SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_IX_MAP_MAPPED);
- }
-
- map->map_buf = map_buf;
- map->offset = offset;
- // nb: spix range includes last
- map->start_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- map->end_spix = (offset + len) / SPIFFS_DATA_PAGE_SIZE(fs);
- memset(map_buf, 0, sizeof(spiffs_page_ix) * (map->end_spix - map->start_spix + 1));
- fd->ix_map = map;
-
- // scan for pixes
- res = spiffs_populate_ix_map(fs, fd, 0, map->end_spix - map->start_spix + 1);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- SPIFFS_UNLOCK(fs);
- return res;
-}
-
-s32_t SPIFFS_ix_unmap(spiffs *fs, spiffs_file fh) {
- SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh);
- s32_t res;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
-
- spiffs_fd *fd;
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if (fd->ix_map == 0) {
- SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_IX_MAP_UNMAPPED);
- }
-
- fd->ix_map = 0;
-
- SPIFFS_UNLOCK(fs);
- return res;
-}
-
-s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) {
- SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi "\n", __func__, fh, offset);
- s32_t res = SPIFFS_OK;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- fh = SPIFFS_FH_UNOFFS(fs, fh);
-
- spiffs_fd *fd;
- res = spiffs_fd_get(fs, fh, &fd);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
-
- if (fd->ix_map == 0) {
- SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_IX_MAP_UNMAPPED);
- }
-
- spiffs_ix_map *map = fd->ix_map;
-
- s32_t spix_diff = offset / SPIFFS_DATA_PAGE_SIZE(fs) - map->start_spix;
- map->offset = offset;
-
- // move existing pixes if within map offs
- if (spix_diff != 0) {
- // move vector
- int i;
- const s32_t vec_len = map->end_spix - map->start_spix + 1; // spix range includes last
- map->start_spix += spix_diff;
- map->end_spix += spix_diff;
- if (spix_diff >= vec_len) {
- // moving beyond range
- memset(&map->map_buf, 0, vec_len * sizeof(spiffs_page_ix));
- // populate_ix_map is inclusive
- res = spiffs_populate_ix_map(fs, fd, 0, vec_len - 1);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- } else if (spix_diff > 0) {
- // diff positive
- for (i = 0; i < vec_len - spix_diff; i++) {
- map->map_buf[i] = map->map_buf[i + spix_diff];
- }
- // memset is non-inclusive
- memset(&map->map_buf[vec_len - spix_diff], 0, spix_diff * sizeof(spiffs_page_ix));
- // populate_ix_map is inclusive
- res = spiffs_populate_ix_map(fs, fd, vec_len - spix_diff, vec_len - 1);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- } else {
- // diff negative
- for (i = vec_len - 1; i >= -spix_diff; i--) {
- map->map_buf[i] = map->map_buf[i + spix_diff];
- }
- // memset is non-inclusive
- memset(&map->map_buf[0], 0, -spix_diff * sizeof(spiffs_page_ix));
- // populate_ix_map is inclusive
- res = spiffs_populate_ix_map(fs, fd, 0, -spix_diff - 1);
- SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- }
-
- }
-
- SPIFFS_UNLOCK(fs);
- return res;
-}
-
-s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes) {
- SPIFFS_API_CHECK_CFG(fs);
- // always add one extra page, the offset might change to the middle of a page
- return (bytes + SPIFFS_DATA_PAGE_SIZE(fs)) / SPIFFS_DATA_PAGE_SIZE(fs);
-}
-
-s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entries) {
- SPIFFS_API_CHECK_CFG(fs);
- return map_page_ix_entries * SPIFFS_DATA_PAGE_SIZE(fs);
-}
-
-#endif // SPIFFS_IX_MAP
-
-#if SPIFFS_TEST_VISUALISATION
-s32_t SPIFFS_vis(spiffs *fs) {
- s32_t res = SPIFFS_OK;
- SPIFFS_API_CHECK_CFG(fs);
- SPIFFS_API_CHECK_MOUNT(fs);
- SPIFFS_LOCK(fs);
-
- int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
- spiffs_block_ix bix = 0;
-
- while (bix < fs->block_count) {
- // check each object lookup page
- int obj_lookup_page = 0;
- int cur_entry = 0;
-
- while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each entry
- while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
- spiffs_obj_id obj_id = obj_lu_buf[cur_entry - entry_offset];
- if (cur_entry == 0) {
- spiffs_printf(_SPIPRIbl" ", bix);
- } else if ((cur_entry & 0x3f) == 0) {
- spiffs_printf(" ");
- }
- if (obj_id == SPIFFS_OBJ_ID_FREE) {
- spiffs_printf(SPIFFS_TEST_VIS_FREE_STR);
- } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
- spiffs_printf(SPIFFS_TEST_VIS_DELE_STR);
- } else if (obj_id & SPIFFS_OBJ_ID_IX_FLAG) {
- spiffs_printf(SPIFFS_TEST_VIS_INDX_STR(obj_id));
- } else {
- spiffs_printf(SPIFFS_TEST_VIS_DATA_STR(obj_id));
- }
- cur_entry++;
- if ((cur_entry & 0x3f) == 0) {
- spiffs_printf("\n");
- }
- } // per entry
- obj_lookup_page++;
- } // per object lookup page
-
- spiffs_obj_id erase_count;
- res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
- SPIFFS_ERASE_COUNT_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&erase_count);
- SPIFFS_CHECK_RES(res);
-
- if (erase_count != (spiffs_obj_id) - 1) {
- spiffs_printf("\tera_cnt: "_SPIPRIi"\n", erase_count);
- } else {
- spiffs_printf("\tera_cnt: N/A\n");
- }
-
- bix++;
- } // per block
-
- spiffs_printf("era_cnt_max: "_SPIPRIi"\n", fs->max_erase_count);
- spiffs_printf("last_errno: "_SPIPRIi"\n", fs->err_code);
- spiffs_printf("blocks: "_SPIPRIi"\n", fs->block_count);
- spiffs_printf("free_blocks: "_SPIPRIi"\n", fs->free_blocks);
- spiffs_printf("page_alloc: "_SPIPRIi"\n", fs->stats_p_allocated);
- spiffs_printf("page_delet: "_SPIPRIi"\n", fs->stats_p_deleted);
- SPIFFS_UNLOCK(fs);
- u32_t total, used;
- SPIFFS_info(fs, &total, &used);
- spiffs_printf("used: "_SPIPRIi" of "_SPIPRIi"\n", used, total);
- return res;
-}
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_nucleus.c b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_nucleus.c
deleted file mode 100644
index 74c5ade0..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_nucleus.c
+++ /dev/null
@@ -1,2365 +0,0 @@
-#include "spiffs.h"
-#include "spiffs_nucleus.h"
-#include "printf.h"
-
-static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
- s32_t res = SPIFFS_OK;
- if (pix == (spiffs_page_ix) - 1) {
- // referring to page 0xffff...., bad object index
- return SPIFFS_ERR_INDEX_REF_FREE;
- }
- if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- // referring to an object lookup page, bad object index
- return SPIFFS_ERR_INDEX_REF_LU;
- }
- if (pix > SPIFFS_MAX_PAGES(fs)) {
- // referring to a bad page
- return SPIFFS_ERR_INDEX_REF_INVALID;
- }
-#if SPIFFS_PAGE_CHECK
- spiffs_page_header ph;
- res = _spiffs_rd(
- fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, pix),
- sizeof(spiffs_page_header),
- (u8_t *)&ph);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_DATA(ph, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, spix);
-#endif
- return res;
-}
-
-#if !SPIFFS_READ_ONLY
-static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
- s32_t res = SPIFFS_OK;
- if (pix == (spiffs_page_ix) - 1) {
- // referring to page 0xffff...., bad object index
- return SPIFFS_ERR_INDEX_FREE;
- }
- if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- // referring to an object lookup page, bad object index
- return SPIFFS_ERR_INDEX_LU;
- }
- if (pix > SPIFFS_MAX_PAGES(fs)) {
- // referring to a bad page
- return SPIFFS_ERR_INDEX_INVALID;
- }
-#if SPIFFS_PAGE_CHECK
- spiffs_page_header ph;
- res = _spiffs_rd(
- fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, pix),
- sizeof(spiffs_page_header),
- (u8_t *)&ph);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(ph, fd->obj_id, spix);
-#endif
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if !SPIFFS_CACHE
-
-s32_t spiffs_phys_rd(
- spiffs *fs,
- u32_t addr,
- u32_t len,
- u8_t *dst) {
- return SPIFFS_HAL_READ(fs, addr, len, dst);
-}
-
-s32_t spiffs_phys_wr(
- spiffs *fs,
- u32_t addr,
- u32_t len,
- u8_t *src) {
- return SPIFFS_HAL_WRITE(fs, addr, len, src);
-}
-
-#endif
-
-#if !SPIFFS_READ_ONLY
-s32_t spiffs_phys_cpy(
- spiffs *fs,
- spiffs_file fh,
- u32_t dst,
- u32_t src,
- u32_t len) {
- (void)fh;
- s32_t res;
- u8_t b[SPIFFS_COPY_BUFFER_STACK];
- while (len > 0) {
- u32_t chunk_size = MIN(SPIFFS_COPY_BUFFER_STACK, len);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_MOVS, fh, src, chunk_size, b);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_MOVD, fh, dst, chunk_size, b);
- SPIFFS_CHECK_RES(res);
- len -= chunk_size;
- src += chunk_size;
- dst += chunk_size;
- }
- return SPIFFS_OK;
-}
-#endif // !SPIFFS_READ_ONLY
-
-// Find object lookup entry containing given id with visitor.
-// Iterate over object lookup pages in each block until a given object id entry is found.
-// When found, the visitor function is called with block index, entry index and user data.
-// If visitor returns SPIFFS_VIS_CONTINUE, the search goes on. Otherwise, the search will be
-// ended and visitor's return code is returned to caller.
-// If no visitor is given (0) the search returns on first entry with matching object id.
-// If no match is found in all look up, SPIFFS_VIS_END is returned.
-// @param fs the file system
-// @param starting_block the starting block to start search in
-// @param starting_lu_entry the look up index entry to start search in
-// @param flags ored combination of SPIFFS_VIS_CHECK_ID, SPIFFS_VIS_CHECK_PH,
-// SPIFFS_VIS_NO_WRAP
-// @param obj_id argument object id
-// @param v visitor callback function
-// @param user_const_p any const pointer, passed to the callback visitor function
-// @param user_var_p any pointer, passed to the callback visitor function
-// @param block_ix reported block index where match was found
-// @param lu_entry reported look up index where match was found
-s32_t spiffs_obj_lu_find_entry_visitor(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- u8_t flags,
- spiffs_obj_id obj_id,
- spiffs_visitor_f v,
- const void *user_const_p,
- void *user_var_p,
- spiffs_block_ix *block_ix,
- int *lu_entry) {
- s32_t res = SPIFFS_OK;
- s32_t entry_count = fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs);
- spiffs_block_ix cur_block = starting_block;
- u32_t cur_block_addr = starting_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
-
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
- int cur_entry = starting_lu_entry;
- int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
-
- // wrap initial
- if (cur_entry > (int)SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) - 1) {
- cur_entry = 0;
- cur_block++;
- cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- if (cur_block >= fs->block_count) {
- if (flags & SPIFFS_VIS_NO_WRAP) {
- return SPIFFS_VIS_END;
- } else {
- // block wrap
- cur_block = 0;
- cur_block_addr = 0;
- }
- }
- }
-
- // check each block
- while (res == SPIFFS_OK && entry_count > 0) {
- int obj_lookup_page = cur_entry / entries_per_page;
- // check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each entry
- while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && // for non-last obj lookup pages
- cur_entry < (int)SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) { // for last obj lookup page
- if ((flags & SPIFFS_VIS_CHECK_ID) == 0 || obj_lu_buf[cur_entry - entry_offset] == obj_id) {
- if (block_ix) *block_ix = cur_block;
- if (lu_entry) *lu_entry = cur_entry;
- if (v) {
- res = v(
- fs,
- (flags & SPIFFS_VIS_CHECK_PH) ? obj_id : obj_lu_buf[cur_entry - entry_offset],
- cur_block,
- cur_entry,
- user_const_p,
- user_var_p);
- if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) {
- if (res == SPIFFS_VIS_COUNTINUE_RELOAD) {
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
- }
- res = SPIFFS_OK;
- cur_entry++;
- entry_count--;
- continue;
- } else {
- return res;
- }
- } else {
- return SPIFFS_OK;
- }
- }
- entry_count--;
- cur_entry++;
- } // per entry
- obj_lookup_page++;
- } // per object lookup page
- cur_entry = 0;
- cur_block++;
- cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- if (cur_block >= fs->block_count) {
- if (flags & SPIFFS_VIS_NO_WRAP) {
- return SPIFFS_VIS_END;
- } else {
- // block wrap
- cur_block = 0;
- cur_block_addr = 0;
- }
- }
- } // per block
-
- SPIFFS_CHECK_RES(res);
-
- return SPIFFS_VIS_END;
-}
-
-#if !SPIFFS_READ_ONLY
-s32_t spiffs_erase_block(
- spiffs *fs,
- spiffs_block_ix bix) {
- s32_t res;
- u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
- s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
-
- // here we ignore res, just try erasing the block
- while (size > 0) {
- SPIFFS_DBG("erase "_SPIPRIad":"_SPIPRIi"\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
- SPIFFS_HAL_ERASE(fs, addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
-
- addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
- size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
- }
- fs->free_blocks++;
-
- // register erase count for this block
- res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
- SPIFFS_ERASE_COUNT_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
- SPIFFS_CHECK_RES(res);
-
-#if SPIFFS_USE_MAGIC
- // finally, write magic
- spiffs_obj_id magic = SPIFFS_MAGIC(fs, bix);
- res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
- SPIFFS_MAGIC_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&magic);
- SPIFFS_CHECK_RES(res);
-#endif
-
- fs->max_erase_count++;
- if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
- fs->max_erase_count = 0;
- }
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
-s32_t spiffs_probe(
- spiffs_config *cfg) {
- s32_t res;
- u32_t paddr;
- spiffs dummy_fs; // create a dummy fs struct just to be able to use macros
- _SPIFFS_MEMCPY(&dummy_fs.cfg, cfg, sizeof(spiffs_config));
- dummy_fs.block_count = 0;
-
- // Read three magics, as one block may be in an aborted erase state.
- // At least two of these must contain magic and be in decreasing order.
- spiffs_obj_id magic[3];
- spiffs_obj_id bix_count[3];
-
- spiffs_block_ix bix;
- for (bix = 0; bix < 3; bix++) {
- paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, bix);
-#if SPIFFS_HAL_CALLBACK_EXTRA
- // not any proper fs to report here, so callback with null
- // (cross fingers that no-one gets angry)
- res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]);
-#else
- res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]);
-#endif
- bix_count[bix] = magic[bix] ^ SPIFFS_MAGIC(&dummy_fs, 0);
- SPIFFS_CHECK_RES(res);
- }
-
- // check that we have sane number of blocks
- if (bix_count[0] < 3) return SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS;
- // check that the order is correct, take aborted erases in calculation
- // first block aborted erase
- if (magic[0] == (spiffs_obj_id)(-1) && bix_count[1] - bix_count[2] == 1) {
- return (bix_count[1] + 1) * cfg->log_block_size;
- }
- // second block aborted erase
- if (magic[1] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[2] == 2) {
- return bix_count[0] * cfg->log_block_size;
- }
- // third block aborted erase
- if (magic[2] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[1] == 1) {
- return bix_count[0] * cfg->log_block_size;
- }
- // no block has aborted erase
- if (bix_count[0] - bix_count[1] == 1 && bix_count[1] - bix_count[2] == 1) {
- return bix_count[0] * cfg->log_block_size;
- }
-
- return SPIFFS_ERR_PROBE_NOT_A_FS;
-}
-#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
-
-
-static s32_t spiffs_obj_lu_scan_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- const void *user_const_p,
- void *user_var_p) {
- (void)bix;
- (void)user_const_p;
- (void)user_var_p;
- if (obj_id == SPIFFS_OBJ_ID_FREE) {
- if (ix_entry == 0) {
- fs->free_blocks++;
- // todo optimize further, return SPIFFS_NEXT_BLOCK
- }
- } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
- fs->stats_p_deleted++;
- } else {
- fs->stats_p_allocated++;
- }
-
- return SPIFFS_VIS_COUNTINUE;
-}
-
-
-// Scans thru all obj lu and counts free, deleted and used pages
-// Find the maximum block erase count
-// Checks magic if enabled
-s32_t spiffs_obj_lu_scan(
- spiffs *fs) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
-#if SPIFFS_USE_MAGIC
- spiffs_block_ix unerased_bix = (spiffs_block_ix) - 1;
-#endif
-
- // find out erase count
- // if enabled, check magic
- bix = 0;
- spiffs_obj_id erase_count_final;
- spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
- spiffs_obj_id erase_count_max = 0;
- while (bix < fs->block_count) {
-#if SPIFFS_USE_MAGIC
- spiffs_obj_id magic;
- res = _spiffs_rd(fs,
- SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_MAGIC_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&magic);
-
- SPIFFS_CHECK_RES(res);
- if (magic != SPIFFS_MAGIC(fs, bix)) {
- if (unerased_bix == (spiffs_block_ix) - 1) {
- // allow one unerased block as it might be powered down during an erase
- unerased_bix = bix;
- } else {
- // more than one unerased block, bail out
- SPIFFS_CHECK_RES(SPIFFS_ERR_NOT_A_FS);
- }
- }
-#endif
- spiffs_obj_id erase_count;
- res = _spiffs_rd(fs,
- SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_ERASE_COUNT_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&erase_count);
- SPIFFS_CHECK_RES(res);
- if (erase_count != SPIFFS_OBJ_ID_FREE) {
- erase_count_min = MIN(erase_count_min, erase_count);
- erase_count_max = MAX(erase_count_max, erase_count);
- }
- bix++;
- }
-
- if (erase_count_min == 0 && erase_count_max == SPIFFS_OBJ_ID_FREE) {
- // clean system, set counter to zero
- erase_count_final = 0;
- } else if (erase_count_max - erase_count_min > (SPIFFS_OBJ_ID_FREE) / 2) {
- // wrap, take min
- erase_count_final = erase_count_min + 1;
- } else {
- erase_count_final = erase_count_max + 1;
- }
-
- fs->max_erase_count = erase_count_final;
-
-#if SPIFFS_USE_MAGIC
- if (unerased_bix != (spiffs_block_ix) - 1) {
- // found one unerased block, remedy
- SPIFFS_DBG("mount: erase block "_SPIPRIbl"\n", bix);
-#if SPIFFS_READ_ONLY
- res = SPIFFS_ERR_RO_ABORTED_OPERATION;
-#else
- res = spiffs_erase_block(fs, unerased_bix);
-#endif // SPIFFS_READ_ONLY
- SPIFFS_CHECK_RES(res);
- }
-#endif
-
- // count blocks
-
- fs->free_blocks = 0;
- fs->stats_p_allocated = 0;
- fs->stats_p_deleted = 0;
-
- res = spiffs_obj_lu_find_entry_visitor(fs,
- 0,
- 0,
- 0,
- 0,
- spiffs_obj_lu_scan_v,
- 0,
- 0,
- &bix,
- &entry);
-
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_OK;
- }
-
- SPIFFS_CHECK_RES(res);
-
- return res;
-}
-
-#if !SPIFFS_READ_ONLY
-// Find free object lookup entry
-// Iterate over object lookup pages in each block until a free object id entry is found
-s32_t spiffs_obj_lu_find_free(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- spiffs_block_ix *block_ix,
- int *lu_entry) {
- s32_t res;
- if (!fs->cleaning && fs->free_blocks < 2) {
- res = spiffs_gc_quick(fs, 0);
- if (res == SPIFFS_ERR_NO_DELETED_BLOCKS) {
- res = SPIFFS_OK;
- }
- SPIFFS_CHECK_RES(res);
- if (fs->free_blocks < 2) {
- return SPIFFS_ERR_FULL;
- }
- }
- res = spiffs_obj_lu_find_id(fs, starting_block, starting_lu_entry,
- SPIFFS_OBJ_ID_FREE, block_ix, lu_entry);
- if (res == SPIFFS_OK) {
- fs->free_cursor_block_ix = *block_ix;
- fs->free_cursor_obj_lu_entry = (*lu_entry) + 1;
- if (*lu_entry == 0) {
- fs->free_blocks--;
- }
- }
- if (res == SPIFFS_ERR_FULL) {
- SPIFFS_DBGF("fs full\n");
- }
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-// Find object lookup entry containing given id
-// Iterate over object lookup pages in each block until a given object id entry is found
-s32_t spiffs_obj_lu_find_id(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- spiffs_obj_id obj_id,
- spiffs_block_ix *block_ix,
- int *lu_entry) {
- s32_t res = spiffs_obj_lu_find_entry_visitor(
- fs, starting_block, starting_lu_entry, SPIFFS_VIS_CHECK_ID, obj_id, 0, 0, 0, block_ix, lu_entry);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
- return res;
-}
-
-
-static s32_t spiffs_obj_lu_find_id_and_span_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- const void *user_const_p,
- void *user_var_p) {
- s32_t res;
- spiffs_page_header ph;
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- res = _spiffs_rd(fs, 0, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph);
- SPIFFS_CHECK_RES(res);
- if (ph.obj_id == obj_id &&
- ph.span_ix == *((spiffs_span_ix *)user_var_p) &&
- (ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED)) == SPIFFS_PH_FLAG_DELET &&
- !((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (ph.flags & SPIFFS_PH_FLAG_IXDELE) == 0 && ph.span_ix == 0) &&
- (user_const_p == 0 || *((const spiffs_page_ix *)user_const_p) != pix)) {
- return SPIFFS_OK;
- } else {
- return SPIFFS_VIS_COUNTINUE;
- }
-}
-
-// Find object lookup entry containing given id and span index
-// Iterate over object lookup pages in each block until a given object id entry is found
-s32_t spiffs_obj_lu_find_id_and_span(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix exclusion_pix,
- spiffs_page_ix *pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
-
- res = spiffs_obj_lu_find_entry_visitor(fs,
- fs->cursor_block_ix,
- fs->cursor_obj_lu_entry,
- SPIFFS_VIS_CHECK_ID,
- obj_id,
- spiffs_obj_lu_find_id_and_span_v,
- exclusion_pix ? &exclusion_pix : 0,
- &spix,
- &bix,
- &entry);
-
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
-
- SPIFFS_CHECK_RES(res);
-
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
-
- fs->cursor_block_ix = bix;
- fs->cursor_obj_lu_entry = entry;
-
- return res;
-}
-
-// Find object lookup entry containing given id and span index in page headers only
-// Iterate over object lookup pages in each block until a given object id entry is found
-s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix exclusion_pix,
- spiffs_page_ix *pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
-
- res = spiffs_obj_lu_find_entry_visitor(fs,
- fs->cursor_block_ix,
- fs->cursor_obj_lu_entry,
- SPIFFS_VIS_CHECK_PH,
- obj_id,
- spiffs_obj_lu_find_id_and_span_v,
- exclusion_pix ? &exclusion_pix : 0,
- &spix,
- &bix,
- &entry);
-
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
-
- SPIFFS_CHECK_RES(res);
-
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
-
- fs->cursor_block_ix = bix;
- fs->cursor_obj_lu_entry = entry;
-
- return res;
-}
-
-#if SPIFFS_IX_MAP
-
-// update index map of given fd with given object index data
-static void spiffs_update_ix_map(spiffs *fs,
- spiffs_fd *fd, spiffs_span_ix objix_spix, spiffs_page_object_ix *objix) {
-#if SPIFFS_SINGLETON
- (void)fs;
-#endif
- spiffs_ix_map *map = fd->ix_map;
- spiffs_span_ix map_objix_start_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->start_spix);
- spiffs_span_ix map_objix_end_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->end_spix);
-
- // check if updated ix is within map range
- if (objix_spix < map_objix_start_spix || objix_spix > map_objix_end_spix) {
- return;
- }
-
- // update memory mapped page index buffer to new pages
-
- // get range of updated object index map data span indices
- spiffs_span_ix objix_data_spix_start =
- SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, objix_spix);
- spiffs_span_ix objix_data_spix_end = objix_data_spix_start +
- (objix_spix == 0 ? SPIFFS_OBJ_HDR_IX_LEN(fs) : SPIFFS_OBJ_IX_LEN(fs));
-
- // calc union of object index range and index map range array
- spiffs_span_ix map_spix = MAX(map->start_spix, objix_data_spix_start);
- spiffs_span_ix map_spix_end = MIN(map->end_spix + 1, objix_data_spix_end);
-
- while (map_spix < map_spix_end) {
- spiffs_page_ix objix_data_pix;
- if (objix_spix == 0) {
- // get data page from object index header page
- objix_data_pix = ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix_header)))[map_spix];
- } else {
- // get data page from object index page
- objix_data_pix = ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, map_spix)];
- }
-
- if (objix_data_pix == (spiffs_page_ix) - 1) {
- // reached end of object, abort
- break;
- }
-
- map->map_buf[map_spix - map->start_spix] = objix_data_pix;
- SPIFFS_DBG("map "_SPIPRIid":"_SPIPRIsp" ("_SPIPRIsp"--"_SPIPRIsp") objix.spix:"_SPIPRIsp" to pix "_SPIPRIpg"\n",
- fd->obj_id, map_spix - map->start_spix,
- map->start_spix, map->end_spix,
- objix->p_hdr.span_ix,
- objix_data_pix);
-
- map_spix++;
- }
-}
-
-typedef struct {
- spiffs_fd *fd;
- u32_t remaining_objix_pages_to_visit;
- spiffs_span_ix map_objix_start_spix;
- spiffs_span_ix map_objix_end_spix;
-} spiffs_ix_map_populate_state;
-
-static s32_t spiffs_populate_ix_map_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- const void *user_const_p,
- void *user_var_p) {
- (void)user_const_p;
- s32_t res;
- spiffs_ix_map_populate_state *state = (spiffs_ix_map_populate_state *)user_var_p;
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
-
- // load header to check it
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix), (u8_t *)objix);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix->p_hdr, obj_id, objix->p_hdr.span_ix);
-
- // check if hdr is ok, and if objix range overlap with ix map range
- if ((objix->p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE) &&
- objix->p_hdr.span_ix >= state->map_objix_start_spix &&
- objix->p_hdr.span_ix <= state->map_objix_end_spix) {
- // ok, load rest of object index
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix) + sizeof(spiffs_page_object_ix),
- SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix),
- (u8_t *)objix + sizeof(spiffs_page_object_ix));
- SPIFFS_CHECK_RES(res);
-
- spiffs_update_ix_map(fs, state->fd, objix->p_hdr.span_ix, objix);
-
- state->remaining_objix_pages_to_visit--;
- SPIFFS_DBG("map "_SPIPRIid" ("_SPIPRIsp"--"_SPIPRIsp") remaining objix pages "_SPIPRIi"\n",
- state->fd->obj_id,
- state->fd->ix_map->start_spix, state->fd->ix_map->end_spix,
- state->remaining_objix_pages_to_visit);
- }
-
- if (res == SPIFFS_OK) {
- res = state->remaining_objix_pages_to_visit ? SPIFFS_VIS_COUNTINUE : SPIFFS_VIS_END;
- }
- return res;
-}
-
-// populates index map, from vector entry start to vector entry end, inclusive
-s32_t spiffs_populate_ix_map(spiffs *fs, spiffs_fd *fd, u32_t vec_entry_start, u32_t vec_entry_end) {
- s32_t res;
- spiffs_ix_map *map = fd->ix_map;
- spiffs_ix_map_populate_state state;
- vec_entry_start = MIN((u32_t)(map->end_spix - map->start_spix), vec_entry_start);
- vec_entry_end = MAX((u32_t)(map->end_spix - map->start_spix), vec_entry_end);
- if (vec_entry_start > vec_entry_end) {
- return SPIFFS_ERR_IX_MAP_BAD_RANGE;
- }
- state.map_objix_start_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->start_spix + vec_entry_start);
- state.map_objix_end_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->start_spix + vec_entry_end);
- state.remaining_objix_pages_to_visit =
- state.map_objix_end_spix - state.map_objix_start_spix + 1;
- state.fd = fd;
-
- res = spiffs_obj_lu_find_entry_visitor(
- fs,
- SPIFFS_BLOCK_FOR_PAGE(fs, fd->objix_hdr_pix),
- SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, fd->objix_hdr_pix),
- SPIFFS_VIS_CHECK_ID,
- fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
- spiffs_populate_ix_map_v,
- 0,
- &state,
- 0,
- 0);
-
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_OK;
- }
-
- return res;
-}
-
-#endif
-
-
-#if !SPIFFS_READ_ONLY
-// Allocates a free defined page with given obj_id
-// Occupies object lookup entry and page
-// data may be NULL; where only page header is stored, len and page_offs is ignored
-s32_t spiffs_page_allocate_data(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_page_header *ph,
- u8_t *data,
- u32_t len,
- u32_t page_offs,
- u8_t finalize,
- spiffs_page_ix *pix) {
- s32_t res = SPIFFS_OK;
- spiffs_block_ix bix;
- int entry;
-
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
-
- // occupy page in object lookup
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t *)&obj_id);
- SPIFFS_CHECK_RES(res);
-
- fs->stats_p_allocated++;
-
- // write page header
- ph->flags &= ~SPIFFS_PH_FLAG_USED;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_header), (u8_t *)ph);
- SPIFFS_CHECK_RES(res);
-
- // write page data
- if (data) {
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry) + sizeof(spiffs_page_header) + page_offs, len, data);
- SPIFFS_CHECK_RES(res);
- }
-
- // finalize header if necessary
- if (finalize && (ph->flags & SPIFFS_PH_FLAG_FINAL)) {
- ph->flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&ph->flags);
- SPIFFS_CHECK_RES(res);
- }
-
- // return written page
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if !SPIFFS_READ_ONLY
-// Moves a page from src to a free page and finalizes it. Updates page index. Page data is given in param page.
-// If page data is null, provided header is used for metainfo and page data is physically copied.
-s32_t spiffs_page_move(
- spiffs *fs,
- spiffs_file fh,
- u8_t *page_data,
- spiffs_obj_id obj_id,
- spiffs_page_header *page_hdr,
- spiffs_page_ix src_pix,
- spiffs_page_ix *dst_pix) {
- s32_t res;
- u8_t was_final = 0;
- spiffs_page_header *p_hdr;
- spiffs_block_ix bix;
- int entry;
- spiffs_page_ix free_pix;
-
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
- free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
-
- if (dst_pix) *dst_pix = free_pix;
-
- p_hdr = page_data ? (spiffs_page_header *)page_data : page_hdr;
- if (page_data) {
- // got page data
- was_final = (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) == 0;
- // write unfinalized page
- p_hdr->flags |= SPIFFS_PH_FLAG_FINAL;
- p_hdr->flags &= ~SPIFFS_PH_FLAG_USED;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), page_data);
- } else {
- // copy page data
- res = spiffs_phys_cpy(fs, fh, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_PAGE_TO_PADDR(fs, src_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs));
- }
- SPIFFS_CHECK_RES(res);
-
- // mark entry in destination object lookup
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, free_pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, free_pix) * sizeof(spiffs_page_ix),
- sizeof(spiffs_obj_id),
- (u8_t *)&obj_id);
- SPIFFS_CHECK_RES(res);
-
- fs->stats_p_allocated++;
-
- if (was_final) {
- // mark finalized in destination page
- p_hdr->flags &= ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_USED);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fh,
- SPIFFS_PAGE_TO_PADDR(fs, free_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&p_hdr->flags);
- SPIFFS_CHECK_RES(res);
- }
- // mark source deleted
- res = spiffs_page_delete(fs, src_pix);
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if !SPIFFS_READ_ONLY
-// Deletes a page and removes it from object lookup.
-s32_t spiffs_page_delete(
- spiffs *fs,
- spiffs_page_ix pix) {
- s32_t res;
- // mark deleted entry in source object lookup
- spiffs_obj_id d_obj_id = SPIFFS_OBJ_ID_DELETED;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_DELE,
- 0,
- SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_page_ix),
- sizeof(spiffs_obj_id),
- (u8_t *)&d_obj_id);
- SPIFFS_CHECK_RES(res);
-
- fs->stats_p_deleted++;
- fs->stats_p_allocated--;
-
- // mark deleted in source page
- u8_t flags = 0xff;
-#if SPIFFS_NO_BLIND_WRITES
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix) + offsetof(spiffs_page_header, flags),
- sizeof(flags), &flags);
- SPIFFS_CHECK_RES(res);
-#endif
- flags &= ~(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_DELE,
- 0,
- SPIFFS_PAGE_TO_PADDR(fs, pix) + offsetof(spiffs_page_header, flags),
- sizeof(flags), &flags);
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if !SPIFFS_READ_ONLY
-// Create an object index header page with empty index and undefined length
-s32_t spiffs_object_create(
- spiffs *fs,
- spiffs_obj_id obj_id,
- const u8_t name[],
- const u8_t meta[],
- spiffs_obj_type type,
- spiffs_page_ix *objix_hdr_pix) {
- s32_t res = SPIFFS_OK;
- spiffs_block_ix bix;
- spiffs_page_object_ix_header oix_hdr;
- int entry;
-
- res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_CHECK_RES(res);
-
- obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
-
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
- SPIFFS_DBG("create: found free page @ "_SPIPRIpg" bix:"_SPIPRIbl" entry:"_SPIPRIsp"\n", (spiffs_page_ix)SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
-
- // occupy page in object lookup
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t *)&obj_id);
- SPIFFS_CHECK_RES(res);
-
- fs->stats_p_allocated++;
-
- // write empty object index page
- oix_hdr.p_hdr.obj_id = obj_id;
- oix_hdr.p_hdr.span_ix = 0;
- oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED);
- oix_hdr.type = type;
- oix_hdr.size = SPIFFS_UNDEFINED_LEN; // keep ones so we can update later without wasting this page
- strncpy((char *)oix_hdr.name, (const char *)name, SPIFFS_OBJ_NAME_LEN - 1);
-#if SPIFFS_OBJ_META_LEN
- if (meta) {
- _SPIFFS_MEMCPY(oix_hdr.meta, meta, SPIFFS_OBJ_META_LEN);
- } else {
- memset(oix_hdr.meta, 0xff, SPIFFS_OBJ_META_LEN);
- }
-#else
- (void) meta;
-#endif
-
- // update page
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_object_ix_header), (u8_t *)&oix_hdr);
-
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)&oix_hdr,
- SPIFFS_EV_IX_NEW, obj_id, 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), SPIFFS_UNDEFINED_LEN);
-
- if (objix_hdr_pix) {
- *objix_hdr_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if !SPIFFS_READ_ONLY
-// update object index header with any combination of name/size/index
-// new_objix_hdr_data may be null, if so the object index header page is loaded
-// name may be null, if so name is not changed
-// size may be null, if so size is not changed
-s32_t spiffs_object_update_index_hdr(
- spiffs *fs,
- spiffs_fd *fd,
- spiffs_obj_id obj_id,
- spiffs_page_ix objix_hdr_pix,
- u8_t *new_objix_hdr_data,
- const u8_t name[],
- const u8_t meta[],
- u32_t size,
- spiffs_page_ix *new_pix) {
- s32_t res = SPIFFS_OK;
- spiffs_page_object_ix_header *objix_hdr;
- spiffs_page_ix new_objix_hdr_pix;
-
- obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
-
- if (new_objix_hdr_data) {
- // object index header page already given to us, no need to load it
- objix_hdr = (spiffs_page_object_ix_header *)new_objix_hdr_data;
- } else {
- // read object index header page
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- }
-
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, obj_id, 0);
-
- // change name
- if (name) {
- strncpy((char *)objix_hdr->name, (const char *)name, SPIFFS_OBJ_NAME_LEN - 1);
- }
-#if SPIFFS_OBJ_META_LEN
- if (meta) {
- _SPIFFS_MEMCPY(objix_hdr->meta, meta, SPIFFS_OBJ_META_LEN);
- }
-#else
- (void) meta;
-#endif
- if (size) {
- objix_hdr->size = size;
- }
-
- // move and update page
- res = spiffs_page_move(fs, fd == 0 ? 0 : fd->file_nbr, (u8_t *)objix_hdr, obj_id, 0, objix_hdr_pix, &new_objix_hdr_pix);
-
- if (res == SPIFFS_OK) {
- if (new_pix) {
- *new_pix = new_objix_hdr_pix;
- }
- // callback on object index update
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)objix_hdr,
- new_objix_hdr_data ? SPIFFS_EV_IX_UPD : SPIFFS_EV_IX_UPD_HDR,
- obj_id, objix_hdr->p_hdr.span_ix, new_objix_hdr_pix, objix_hdr->size);
- if (fd) fd->objix_hdr_pix = new_objix_hdr_pix; // if this is not in the registered cluster
- }
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-void spiffs_cb_object_event(
- spiffs *fs,
- spiffs_page_object_ix *objix,
- int ev,
- spiffs_obj_id obj_id_raw,
- spiffs_span_ix spix,
- spiffs_page_ix new_pix,
- u32_t new_size) {
-#if SPIFFS_IX_MAP == 0
- (void)objix;
-#endif
- // update index caches in all file descriptors
- spiffs_obj_id obj_id = obj_id_raw & ~SPIFFS_OBJ_ID_IX_FLAG;
- u32_t i;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- SPIFFS_DBG(" CALLBACK %s obj_id:"_SPIPRIid" spix:"_SPIPRIsp" npix:"_SPIPRIpg" nsz:"_SPIPRIi"\n", (const char *[]) {"UPD", "NEW", "DEL", "MOV", "HUP", "???"}[MIN(ev, 5)],
- obj_id_raw, spix, new_pix, new_size);
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if ((cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue; // fd not related to updated file
-#if !SPIFFS_TEMPORAL_FD_CACHE
- if (cur_fd->file_nbr == 0) continue; // fd closed
-#endif
- if (spix == 0) { // object index header update
- if (ev != SPIFFS_EV_IX_DEL) {
-#if SPIFFS_TEMPORAL_FD_CACHE
- if (cur_fd->score == 0) continue; // never used fd
-#endif
- SPIFFS_DBG(" callback: setting fd "_SPIPRIfd":"_SPIPRIid"(fdoffs:"_SPIPRIi" offs:"_SPIPRIi") objix_hdr_pix to "_SPIPRIpg", size:"_SPIPRIi"\n",
- SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, cur_fd->fdoffset, cur_fd->offset, new_pix, new_size);
- cur_fd->objix_hdr_pix = new_pix;
- if (new_size != 0) {
- // update size and offsets for fds to this file
- cur_fd->size = new_size;
- u32_t act_new_size = new_size == SPIFFS_UNDEFINED_LEN ? 0 : new_size;
-#if SPIFFS_CACHE_WR
- if (act_new_size > 0 && cur_fd->cache_page) {
- act_new_size = MAX(act_new_size, cur_fd->cache_page->ucache.swrc.offset + cur_fd->cache_page->ucache.swrc.size);
- }
-#endif
- if (cur_fd->offset > act_new_size) {
- cur_fd->offset = act_new_size;
- }
- if (cur_fd->fdoffset > act_new_size) {
- cur_fd->fdoffset = act_new_size;
- }
-#if SPIFFS_CACHE_WR
- if (cur_fd->cache_page && cur_fd->cache_page->ucache.swrc.offset > act_new_size + 1) {
- SPIFFS_CACHE_DBG("CACHE_DROP: file trunced, dropping cache page "_SPIPRIi", no writeback\n", cur_fd->cache_page->ix);
- spiffs_cache_fd_release(fs, cur_fd->cache_page);
- }
-#endif
- }
- } else {
- // removing file
-#if SPIFFS_CACHE_WR
- if (cur_fd->file_nbr && cur_fd->cache_page) {
- SPIFFS_CACHE_DBG("CACHE_DROP: file deleted, dropping cache page "_SPIPRIi", no writeback\n", cur_fd->cache_page->ix);
- spiffs_cache_fd_release(fs, cur_fd->cache_page);
- }
-#endif
- SPIFFS_DBG(" callback: release fd "_SPIPRIfd":"_SPIPRIid" span:"_SPIPRIsp" objix_pix to "_SPIPRIpg"\n", SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, spix, new_pix);
- cur_fd->file_nbr = 0;
- cur_fd->obj_id = SPIFFS_OBJ_ID_DELETED;
- }
- } // object index header update
- if (cur_fd->cursor_objix_spix == spix) {
- if (ev != SPIFFS_EV_IX_DEL) {
- SPIFFS_DBG(" callback: setting fd "_SPIPRIfd":"_SPIPRIid" span:"_SPIPRIsp" objix_pix to "_SPIPRIpg"\n", SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, spix, new_pix);
- cur_fd->cursor_objix_pix = new_pix;
- } else {
- cur_fd->cursor_objix_pix = 0;
- }
- }
- } // fd update loop
-
-#if SPIFFS_IX_MAP
-
- // update index maps
- if (ev == SPIFFS_EV_IX_UPD || ev == SPIFFS_EV_IX_NEW) {
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- // check fd opened, having ix map, match obj id
- if (cur_fd->file_nbr == 0 ||
- cur_fd->ix_map == 0 ||
- (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue;
- SPIFFS_DBG(" callback: map ix update fd "_SPIPRIfd":"_SPIPRIid" span:"_SPIPRIsp"\n", SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, spix);
- spiffs_update_ix_map(fs, cur_fd, spix, objix);
- }
- }
-
-#endif
-
- // callback to user if object index header
- if (fs->file_cb_f && spix == 0 && (obj_id_raw & SPIFFS_OBJ_ID_IX_FLAG)) {
- spiffs_fileop_type op;
- if (ev == SPIFFS_EV_IX_NEW) {
- op = SPIFFS_CB_CREATED;
- } else if (ev == SPIFFS_EV_IX_UPD ||
- ev == SPIFFS_EV_IX_MOV ||
- ev == SPIFFS_EV_IX_UPD_HDR) {
- op = SPIFFS_CB_UPDATED;
- } else if (ev == SPIFFS_EV_IX_DEL) {
- op = SPIFFS_CB_DELETED;
- } else {
- SPIFFS_DBG(" callback: WARNING unknown callback event "_SPIPRIi"\n", ev);
- return; // bail out
- }
- fs->file_cb_f(fs, op, obj_id, new_pix);
- }
-}
-
-// Open object by id
-s32_t spiffs_object_open_by_id(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_fd *fd,
- spiffs_flags flags,
- spiffs_mode mode) {
- s32_t res = SPIFFS_OK;
- spiffs_page_ix pix;
-
- res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_object_open_by_page(fs, pix, fd, flags, mode);
-
- return res;
-}
-
-// Open object by page index
-s32_t spiffs_object_open_by_page(
- spiffs *fs,
- spiffs_page_ix pix,
- spiffs_fd *fd,
- spiffs_flags flags,
- spiffs_mode mode) {
- (void)mode;
- s32_t res = SPIFFS_OK;
- spiffs_page_object_ix_header oix_hdr;
- spiffs_obj_id obj_id;
-
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&oix_hdr);
- SPIFFS_CHECK_RES(res);
-
- spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(fs, pix);
- int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix);
-
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t *)&obj_id);
-
- fd->fs = fs;
- fd->objix_hdr_pix = pix;
- fd->size = oix_hdr.size;
- fd->offset = 0;
- fd->cursor_objix_pix = pix;
- fd->cursor_objix_spix = 0;
- fd->obj_id = obj_id;
- fd->flags = flags;
-
- SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0);
-
- SPIFFS_DBG("open: fd "_SPIPRIfd" is obj id "_SPIPRIid"\n", SPIFFS_FH_OFFS(fs, fd->file_nbr), fd->obj_id);
-
- return res;
-}
-
-#if !SPIFFS_READ_ONLY
-// Append to object
-// keep current object index (header) page in fs->work buffer
-s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
- spiffs *fs = fd->fs;
- s32_t res = SPIFFS_OK;
- u32_t written = 0;
-
- SPIFFS_DBG("append: "_SPIPRIi" bytes @ offs "_SPIPRIi" of size "_SPIPRIi"\n", len, offset, fd->size);
-
- if (offset > fd->size) {
- SPIFFS_DBGF("append: offset reversed to size\n");
- offset = fd->size;
- }
-
- res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta
- if (res != SPIFFS_OK) {
- SPIFFS_DBG("append: gc check fail "_SPIPRIi"\n", res);
- }
- SPIFFS_CHECK_RES(res);
-
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- spiffs_page_header p_hdr;
-
- spiffs_span_ix cur_objix_spix = 0;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix) - 1;
- spiffs_page_ix cur_objix_pix = fd->objix_hdr_pix;
- spiffs_page_ix new_objix_hdr_page;
-
- spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- spiffs_page_ix data_page;
- u32_t page_offs = offset % SPIFFS_DATA_PAGE_SIZE(fs);
-
- // write all data
- while (res == SPIFFS_OK && written < len) {
- // calculate object index page span index
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
-
- // handle storing and loading of object indices
- if (cur_objix_spix != prev_objix_spix) {
- // new object index page
- // within this clause we return directly if something fails, object index mess-up
- if (written > 0) {
- // store previous object index page, unless first pass
- SPIFFS_DBG("append: "_SPIPRIid" store objix "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id,
- cur_objix_pix, prev_objix_spix, written);
- if (prev_objix_spix == 0) {
- // this is an update to object index header page
- objix_hdr->size = offset + written;
- if (offset == 0) {
- // was an empty object, update same page (size was 0xffffffff)
- res = spiffs_page_index_check(fs, fd, cur_objix_pix, 0);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- } else {
- // was a nonempty object, update to new page
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, 0, offset + written, &new_objix_hdr_page);
- SPIFFS_CHECK_RES(res);
- SPIFFS_DBG("append: "_SPIPRIid" store new objix_hdr, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id,
- new_objix_hdr_page, 0, written);
- }
- } else {
- // this is an update to an object index page
- res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
- SPIFFS_CHECK_RES(res);
-
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work,
- SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
- // update length in object index header page
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, 0, offset + written, &new_objix_hdr_page);
- SPIFFS_CHECK_RES(res);
- SPIFFS_DBG("append: "_SPIPRIid" store new size I "_SPIPRIi" in objix_hdr, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id,
- offset + written, new_objix_hdr_page, 0, written);
- }
- fd->size = offset + written;
- fd->offset = offset + written;
- }
-
- // create or load new object index page
- if (cur_objix_spix == 0) {
- // load object index header page, must always exist
- SPIFFS_DBG("append: "_SPIPRIid" load objixhdr page "_SPIPRIpg":"_SPIPRIsp"\n", fd->obj_id, cur_objix_pix, cur_objix_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- } else {
- spiffs_span_ix len_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, (fd->size - 1) / SPIFFS_DATA_PAGE_SIZE(fs));
- // on subsequent passes, create a new object index page
- if (written > 0 || cur_objix_spix > len_objix_spix) {
- p_hdr.obj_id = fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = cur_objix_spix;
- p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
- res = spiffs_page_allocate_data(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, 0, 0, 0, 1, &cur_objix_pix);
- SPIFFS_CHECK_RES(res);
- // quick "load" of new object index page
- memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- _SPIFFS_MEMCPY(fs->work, &p_hdr, sizeof(spiffs_page_header));
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work,
- SPIFFS_EV_IX_NEW, fd->obj_id, cur_objix_spix, cur_objix_pix, 0);
- SPIFFS_DBG("append: "_SPIPRIid" create objix page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id
- , cur_objix_pix, cur_objix_spix, written);
- } else {
- // on first pass, we load existing object index page
- spiffs_page_ix pix;
- SPIFFS_DBG("append: "_SPIPRIid" find objix span_ix:"_SPIPRIsp"\n", fd->obj_id, cur_objix_spix);
- if (fd->cursor_objix_spix == cur_objix_spix) {
- pix = fd->cursor_objix_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
- SPIFFS_CHECK_RES(res);
- }
- SPIFFS_DBG("append: "_SPIPRIid" found object index at page "_SPIPRIpg" [fd size "_SPIPRIi"]\n", fd->obj_id, pix, fd->size);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- cur_objix_pix = pix;
- }
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = offset + written;
- fd->size = offset + written;
- }
- prev_objix_spix = cur_objix_spix;
- }
-
- // write data
- u32_t to_write = MIN(len - written, SPIFFS_DATA_PAGE_SIZE(fs) - page_offs);
- if (page_offs == 0) {
- // at beginning of a page, allocate and write a new page of data
- p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = data_spix;
- p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, &data[written], to_write, page_offs, 1, &data_page);
- SPIFFS_DBG("append: "_SPIPRIid" store new data page, "_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\n", fd->obj_id,
- data_page, data_spix, page_offs, to_write, written);
- } else {
- // append to existing page, fill out free data in existing page
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- data_page = ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- } else {
- // get data page from object index page
- data_page = ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- }
-
- res = spiffs_page_data_check(fs, fd, data_page, data_spix);
- SPIFFS_CHECK_RES(res);
-
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, data_page) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
- SPIFFS_DBG("append: "_SPIPRIid" store to existing data page, "_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\n", fd->obj_id
- , data_page, data_spix, page_offs, to_write, written);
- }
-
- if (res != SPIFFS_OK) break;
-
- // update memory representation of object index page with new data page
- if (cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_page;
- SPIFFS_DBG("append: "_SPIPRIid" wrote page "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" in mem\n", fd->obj_id
- , data_page, data_spix);
- objix_hdr->size = offset + written;
- } else {
- // update object index page
- ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = data_page;
- SPIFFS_DBG("append: "_SPIPRIid" wrote page "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", fd->obj_id
- , data_page, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- }
-
- // update internals
- page_offs = 0;
- data_spix++;
- written += to_write;
- } // while all data
-
- fd->size = offset + written;
- fd->offset = offset + written;
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
-
- // finalize updated object indices
- s32_t res2 = SPIFFS_OK;
- if (cur_objix_spix != 0) {
- // wrote beyond object index header page
- // write last modified object index page, unless object header index page
- SPIFFS_DBG("append: "_SPIPRIid" store objix page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id,
- cur_objix_pix, cur_objix_spix, written);
-
- res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res2);
-
- res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res2);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work,
- SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
-
- // update size in object header index page
- res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, 0, offset + written, &new_objix_hdr_page);
- SPIFFS_DBG("append: "_SPIPRIid" store new size II "_SPIPRIi" in objix_hdr, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi", res "_SPIPRIi"\n", fd->obj_id
- , offset + written, new_objix_hdr_page, 0, written, res2);
- SPIFFS_CHECK_RES(res2);
- } else {
- // wrote within object index header page
- if (offset == 0) {
- // wrote to empty object - simply update size and write whole page
- objix_hdr->size = offset + written;
- SPIFFS_DBG("append: "_SPIPRIid" store fresh objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id
- , cur_objix_pix, cur_objix_spix, written);
-
- res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res2);
-
- res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res2);
- // callback on object index update
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work,
- SPIFFS_EV_IX_UPD_HDR, fd->obj_id, objix_hdr->p_hdr.span_ix, cur_objix_pix, objix_hdr->size);
- } else {
- // modifying object index header page, update size and make new copy
- res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, 0, offset + written, &new_objix_hdr_page);
- SPIFFS_DBG("append: "_SPIPRIid" store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id
- , new_objix_hdr_page, 0, written);
- SPIFFS_CHECK_RES(res2);
- }
- }
-
- return res;
-} // spiffs_object_append
-#endif // !SPIFFS_READ_ONLY
-
-#if !SPIFFS_READ_ONLY
-// Modify object
-// keep current object index (header) page in fs->work buffer
-s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
- spiffs *fs = fd->fs;
- s32_t res = SPIFFS_OK;
- u32_t written = 0;
-
- res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_CHECK_RES(res);
-
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- spiffs_page_header p_hdr;
-
- spiffs_span_ix cur_objix_spix = 0;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix) - 1;
- spiffs_page_ix cur_objix_pix = fd->objix_hdr_pix;
- spiffs_page_ix new_objix_hdr_pix;
-
- spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- spiffs_page_ix data_pix;
- u32_t page_offs = offset % SPIFFS_DATA_PAGE_SIZE(fs);
-
-
- // write all data
- while (res == SPIFFS_OK && written < len) {
- // calculate object index page span index
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
-
- // handle storing and loading of object indices
- if (cur_objix_spix != prev_objix_spix) {
- // new object index page
- // within this clause we return directly if something fails, object index mess-up
- if (written > 0) {
- // store previous object index (header) page, unless first pass
- if (prev_objix_spix == 0) {
- // store previous object index header page
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, 0, 0, &new_objix_hdr_pix);
- SPIFFS_DBG("modify: store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", new_objix_hdr_pix, 0, written);
- SPIFFS_CHECK_RES(res);
- } else {
- // store new version of previous object index page
- spiffs_page_ix new_objix_pix;
-
- res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_page_move(fs, fd->file_nbr, (u8_t *)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
- SPIFFS_DBG("modify: store previous modified objix page, "_SPIPRIid":"_SPIPRIsp", written "_SPIPRIi"\n", new_objix_pix, objix->p_hdr.span_ix, written);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)objix,
- SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
- }
- }
-
- // load next object index page
- if (cur_objix_spix == 0) {
- // load object index header page, must exist
- SPIFFS_DBG("modify: load objixhdr page "_SPIPRIpg":"_SPIPRIsp"\n", cur_objix_pix, cur_objix_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- } else {
- // load existing object index page on first pass
- spiffs_page_ix pix;
- SPIFFS_DBG("modify: find objix span_ix:"_SPIPRIsp"\n", cur_objix_spix);
- if (fd->cursor_objix_spix == cur_objix_spix) {
- pix = fd->cursor_objix_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
- SPIFFS_CHECK_RES(res);
- }
- SPIFFS_DBG("modify: found object index at page "_SPIPRIpg"\n", pix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- cur_objix_pix = pix;
- }
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = offset + written;
- prev_objix_spix = cur_objix_spix;
- }
-
- // write partial data
- u32_t to_write = MIN(len - written, SPIFFS_DATA_PAGE_SIZE(fs) - page_offs);
- spiffs_page_ix orig_data_pix;
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- orig_data_pix = ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- } else {
- // get data page from object index page
- orig_data_pix = ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- }
-
- p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = data_spix;
- p_hdr.flags = 0xff;
- if (page_offs == 0 && to_write == SPIFFS_DATA_PAGE_SIZE(fs)) {
- // a full page, allocate and write a new page of data
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
- SPIFFS_DBG("modify: store new data page, "_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\n", data_pix, data_spix, page_offs, to_write, written);
- if (res != SPIFFS_OK) break;
- } else {
- // write to existing page, allocate new and copy unmodified data
-
- res = spiffs_page_data_check(fs, fd, orig_data_pix, data_spix);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, 0, 0, 0, 0, &data_pix);
- if (res != SPIFFS_OK) break;
-
- // copy unmodified data
- if (page_offs > 0) {
- // before modification
- res = spiffs_phys_cpy(fs, fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, orig_data_pix) + sizeof(spiffs_page_header),
- page_offs);
- if (res != SPIFFS_OK) break;
- }
- if (page_offs + to_write < SPIFFS_DATA_PAGE_SIZE(fs)) {
- // after modification
- res = spiffs_phys_cpy(fs, fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + page_offs + to_write,
- SPIFFS_PAGE_TO_PADDR(fs, orig_data_pix) + sizeof(spiffs_page_header) + page_offs + to_write,
- SPIFFS_DATA_PAGE_SIZE(fs) - (page_offs + to_write));
- if (res != SPIFFS_OK) break;
- }
-
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
- if (res != SPIFFS_OK) break;
- p_hdr.flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&p_hdr.flags);
- if (res != SPIFFS_OK) break;
-
- SPIFFS_DBG("modify: store to existing data page, src:"_SPIPRIpg", dst:"_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\n", orig_data_pix, data_pix, data_spix, page_offs, to_write, written);
- }
-
- // delete original data page
- res = spiffs_page_delete(fs, orig_data_pix);
- if (res != SPIFFS_OK) break;
- // update memory representation of object index page with new data page
- if (cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_pix;
- SPIFFS_DBG("modify: wrote page "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" in mem\n", data_pix, data_spix);
- } else {
- // update object index page
- ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = data_pix;
- SPIFFS_DBG("modify: wrote page "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- }
-
- // update internals
- page_offs = 0;
- data_spix++;
- written += to_write;
- } // while all data
-
- fd->offset = offset + written;
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
-
- // finalize updated object indices
- s32_t res2 = SPIFFS_OK;
- if (cur_objix_spix != 0) {
- // wrote beyond object index header page
- // write last modified object index page
- // move and update page
- spiffs_page_ix new_objix_pix;
-
- res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res2);
-
- res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t *)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
- SPIFFS_DBG("modify: store modified objix page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", new_objix_pix, cur_objix_spix, written);
- fd->cursor_objix_pix = new_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- SPIFFS_CHECK_RES(res2);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)objix,
- SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
-
- } else {
- // wrote within object index header page
- res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, 0, 0, &new_objix_hdr_pix);
- SPIFFS_DBG("modify: store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", new_objix_hdr_pix, 0, written);
- SPIFFS_CHECK_RES(res2);
- }
-
- return res;
-} // spiffs_object_modify
-#endif // !SPIFFS_READ_ONLY
-
-static s32_t spiffs_object_find_object_index_header_by_name_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- const void *user_const_p,
- void *user_var_p) {
- (void)user_var_p;
- s32_t res;
- spiffs_page_object_ix_header objix_hdr;
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
- (obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
- return SPIFFS_VIS_COUNTINUE;
- }
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- SPIFFS_CHECK_RES(res);
- if (objix_hdr.p_hdr.span_ix == 0 &&
- (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
- if (strcmp((const char *)user_const_p, (char *)objix_hdr.name) == 0) {
- return SPIFFS_OK;
- }
- }
-
- return SPIFFS_VIS_COUNTINUE;
-}
-
-// Finds object index header page by name
-s32_t spiffs_object_find_object_index_header_by_name(
- spiffs *fs,
- const u8_t name[SPIFFS_OBJ_NAME_LEN],
- spiffs_page_ix *pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
-
- res = spiffs_obj_lu_find_entry_visitor(fs,
- fs->cursor_block_ix,
- fs->cursor_obj_lu_entry,
- 0,
- 0,
- spiffs_object_find_object_index_header_by_name_v,
- name,
- 0,
- &bix,
- &entry);
-
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
- SPIFFS_CHECK_RES(res);
-
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
-
- fs->cursor_block_ix = bix;
- fs->cursor_obj_lu_entry = entry;
-
- return res;
-}
-
-#if !SPIFFS_READ_ONLY
-// Truncates object to new size. If new size is null, object may be removed totally
-s32_t spiffs_object_truncate(
- spiffs_fd *fd,
- u32_t new_size,
- u8_t remove_full) {
- s32_t res = SPIFFS_OK;
- spiffs *fs = fd->fs;
-
- if ((fd->size == SPIFFS_UNDEFINED_LEN || fd->size == 0) && !remove_full) {
- // no op
- return res;
- }
-
- // need 2 pages if not removing: object index page + possibly chopped data page
- if (remove_full == 0) {
- res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs) * 2);
- SPIFFS_CHECK_RES(res);
- }
-
- spiffs_page_ix objix_pix = fd->objix_hdr_pix;
- spiffs_span_ix data_spix = (fd->size > 0 ? fd->size - 1 : 0) / SPIFFS_DATA_PAGE_SIZE(fs);
- u32_t cur_size = fd->size == (u32_t)SPIFFS_UNDEFINED_LEN ? 0 : fd->size ;
- spiffs_span_ix cur_objix_spix = 0;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix) - 1;
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- spiffs_page_ix data_pix;
- spiffs_page_ix new_objix_hdr_pix;
-
- // before truncating, check if object is to be fully removed and mark this
- if (remove_full && new_size == 0) {
- u8_t flags = ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, fd->objix_hdr_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&flags);
- SPIFFS_CHECK_RES(res);
- }
-
- // delete from end of object until desired len is reached
- while (cur_size > new_size) {
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
-
- // put object index for current data span index in work buffer
- if (prev_objix_spix != cur_objix_spix) {
- if (prev_objix_spix != (spiffs_span_ix) - 1) {
- // remove previous object index page
- SPIFFS_DBG("truncate: delete objix page "_SPIPRIpg":"_SPIPRIsp"\n", objix_pix, prev_objix_spix);
-
- res = spiffs_page_index_check(fs, fd, objix_pix, prev_objix_spix);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_page_delete(fs, objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)0,
- SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0);
- if (prev_objix_spix > 0) {
- // Update object index header page, unless we totally want to remove the file.
- // If fully removing, we're not keeping consistency as good as when storing the header between chunks,
- // would we be aborted. But when removing full files, a crammed system may otherwise
- // report ERR_FULL a la windows. We cannot have that.
- // Hence, take the risk - if aborted, a file check would free the lost pages and mend things
- // as the file is marked as fully deleted in the beginning.
- if (remove_full == 0) {
- SPIFFS_DBG("truncate: update objix hdr page "_SPIPRIpg":"_SPIPRIsp" to size "_SPIPRIi"\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, 0, cur_size, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- fd->size = cur_size;
- }
- }
- // load current object index (header) page
- if (cur_objix_spix == 0) {
- objix_pix = fd->objix_hdr_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
- SPIFFS_CHECK_RES(res);
- }
-
- SPIFFS_DBG("truncate: load objix page "_SPIPRIpg":"_SPIPRIsp" for data spix:"_SPIPRIsp"\n", objix_pix, cur_objix_spix, data_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- fd->cursor_objix_pix = objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = cur_size;
-
- prev_objix_spix = cur_objix_spix;
- }
-
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- data_pix = ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = SPIFFS_OBJ_ID_FREE;
- } else {
- // get data page from object index page
- data_pix = ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = SPIFFS_OBJ_ID_FREE;
- }
-
- SPIFFS_DBG("truncate: got data pix "_SPIPRIpg"\n", data_pix);
-
- if (new_size == 0 || remove_full || cur_size - new_size >= SPIFFS_DATA_PAGE_SIZE(fs)) {
- // delete full data page
- res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
- if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) {
- SPIFFS_DBG("truncate: err validating data pix "_SPIPRIi"\n", res);
- break;
- }
-
- if (res == SPIFFS_OK) {
- res = spiffs_page_delete(fs, data_pix);
- if (res != SPIFFS_OK) {
- SPIFFS_DBG("truncate: err deleting data pix "_SPIPRIi"\n", res);
- break;
- }
- } else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) {
- res = SPIFFS_OK;
- }
-
- // update current size
- if (cur_size % SPIFFS_DATA_PAGE_SIZE(fs) == 0) {
- cur_size -= SPIFFS_DATA_PAGE_SIZE(fs);
- } else {
- cur_size -= cur_size % SPIFFS_DATA_PAGE_SIZE(fs);
- }
- fd->size = cur_size;
- fd->offset = cur_size;
- SPIFFS_DBG("truncate: delete data page "_SPIPRIpg" for data spix:"_SPIPRIsp", cur_size:"_SPIPRIi"\n", data_pix, data_spix, cur_size);
- } else {
- // delete last page, partially
- spiffs_page_header p_hdr;
- spiffs_page_ix new_data_pix;
- u32_t bytes_to_remove = SPIFFS_DATA_PAGE_SIZE(fs) - (new_size % SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_DBG("truncate: delete "_SPIPRIi" bytes from data page "_SPIPRIpg" for data spix:"_SPIPRIsp", cur_size:"_SPIPRIi"\n", bytes_to_remove, data_pix, data_spix, cur_size);
-
- res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
- if (res != SPIFFS_OK) break;
-
- p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = data_spix;
- p_hdr.flags = 0xff;
- // allocate new page and copy unmodified data
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, 0, 0, 0, 0, &new_data_pix);
- if (res != SPIFFS_OK) break;
- res = spiffs_phys_cpy(fs, 0,
- SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header),
- SPIFFS_DATA_PAGE_SIZE(fs) - bytes_to_remove);
- if (res != SPIFFS_OK) break;
- // delete original data page
- res = spiffs_page_delete(fs, data_pix);
- if (res != SPIFFS_OK) break;
- p_hdr.flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&p_hdr.flags);
- if (res != SPIFFS_OK) break;
-
- // update memory representation of object index page with new data page
- if (cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix;
- SPIFFS_DBG("truncate: wrote page "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- } else {
- // update object index page
- ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix;
- SPIFFS_DBG("truncate: wrote page "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- }
- cur_size = new_size;
- fd->size = new_size;
- fd->offset = cur_size;
- break;
- }
- data_spix--;
- } // while all data
-
- // update object indices
- if (cur_objix_spix == 0) {
- // update object index header page
- if (cur_size == 0) {
- if (remove_full) {
- // remove object altogether
- SPIFFS_DBG("truncate: remove object index header page "_SPIPRIpg"\n", objix_pix);
-
- res = spiffs_page_index_check(fs, fd, objix_pix, 0);
- SPIFFS_CHECK_RES(res);
-
- res = spiffs_page_delete(fs, objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)0,
- SPIFFS_EV_IX_DEL, fd->obj_id, 0, objix_pix, 0);
- } else {
- // make uninitialized object
- SPIFFS_DBG("truncate: reset objix_hdr page "_SPIPRIpg"\n", objix_pix);
- memset(fs->work + sizeof(spiffs_page_object_ix_header), 0xff,
- SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header));
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- objix_pix, fs->work, 0, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- } else {
- // update object index header page
- SPIFFS_DBGF("truncate: update object index header page with indices and size\n");
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- objix_pix, fs->work, 0, 0, cur_size, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- } else {
- // update both current object index page and object index header page
- spiffs_page_ix new_objix_pix;
-
- res = spiffs_page_index_check(fs, fd, objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res);
-
- // move and update object index page
- res = spiffs_page_move(fs, fd->file_nbr, (u8_t *)objix_hdr, fd->obj_id, 0, objix_pix, &new_objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, (spiffs_page_object_ix *)objix_hdr,
- SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
- SPIFFS_DBG("truncate: store modified objix page, "_SPIPRIpg":"_SPIPRIsp"\n", new_objix_pix, cur_objix_spix);
- fd->cursor_objix_pix = new_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = cur_size;
- // update object index header page with new size
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, 0, cur_size, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- fd->size = cur_size;
-
- return res;
-} // spiffs_object_truncate
-#endif // !SPIFFS_READ_ONLY
-
-s32_t spiffs_object_read(
- spiffs_fd *fd,
- u32_t offset,
- u32_t len,
- u8_t *dst) {
- s32_t res = SPIFFS_OK;
- spiffs *fs = fd->fs;
- spiffs_page_ix objix_pix;
- spiffs_page_ix data_pix;
- spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- u32_t cur_offset = offset;
- spiffs_span_ix cur_objix_spix;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix) - 1;
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
-
- while (cur_offset < offset + len) {
-#if SPIFFS_IX_MAP
- // check if we have a memory, index map and if so, if we're within index map's range
- // and if so, if the entry is populated
- if (fd->ix_map && data_spix >= fd->ix_map->start_spix && data_spix <= fd->ix_map->end_spix
- && fd->ix_map->map_buf[data_spix - fd->ix_map->start_spix]) {
- data_pix = fd->ix_map->map_buf[data_spix - fd->ix_map->start_spix];
- } else {
-#endif
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- if (prev_objix_spix != cur_objix_spix) {
- // load current object index (header) page
- if (cur_objix_spix == 0) {
- objix_pix = fd->objix_hdr_pix;
- } else {
- SPIFFS_DBG("read: find objix "_SPIPRIid":"_SPIPRIsp"\n", fd->obj_id, cur_objix_spix);
- if (fd->cursor_objix_spix == cur_objix_spix) {
- objix_pix = fd->cursor_objix_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
- SPIFFS_CHECK_RES(res);
- }
- }
- SPIFFS_DBG("read: load objix page "_SPIPRIpg":"_SPIPRIsp" for data spix:"_SPIPRIsp"\n", objix_pix, cur_objix_spix, data_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix->p_hdr, fd->obj_id, cur_objix_spix);
-
- fd->offset = cur_offset;
- fd->cursor_objix_pix = objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
-
- prev_objix_spix = cur_objix_spix;
- }
-
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- data_pix = ((spiffs_page_ix *)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- } else {
- // get data page from object index page
- data_pix = ((spiffs_page_ix *)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- }
-#if SPIFFS_IX_MAP
- }
-#endif
- // all remaining data
- u32_t len_to_read = offset + len - cur_offset;
- // remaining data in page
- len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
- // remaining data in file
- len_to_read = MIN(len_to_read, fd->size - cur_offset);
- SPIFFS_DBG("read: offset:"_SPIPRIi" rd:"_SPIPRIi" data spix:"_SPIPRIsp" is data_pix:"_SPIPRIpg" addr:"_SPIPRIad"\n", cur_offset, len_to_read, data_spix, data_pix,
- (u32_t)(SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs))));
- if (len_to_read == 0) {
- res = SPIFFS_ERR_END_OF_OBJECT;
- break;
- }
- res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_rd(
- fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)),
- len_to_read,
- dst);
- SPIFFS_CHECK_RES(res);
- dst += len_to_read;
- cur_offset += len_to_read;
- fd->offset = cur_offset;
- data_spix++;
- }
-
- return res;
-}
-
-#if !SPIFFS_READ_ONLY
-typedef struct {
- spiffs_obj_id min_obj_id;
- spiffs_obj_id max_obj_id;
- u32_t compaction;
- const u8_t *conflicting_name;
-} spiffs_free_obj_id_state;
-
-static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
- const void *user_const_p, void *user_var_p) {
- if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) {
- spiffs_obj_id min_obj_id = *((spiffs_obj_id *)user_var_p);
- const u8_t *conflicting_name = (const u8_t *)user_const_p;
-
- // if conflicting name parameter is given, also check if this name is found in object index hdrs
- if (conflicting_name && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- int res;
- spiffs_page_object_ix_header objix_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- SPIFFS_CHECK_RES(res);
- if (objix_hdr.p_hdr.span_ix == 0 &&
- (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
- if (strcmp((const char *)user_const_p, (char *)objix_hdr.name) == 0) {
- return SPIFFS_ERR_CONFLICTING_NAME;
- }
- }
- }
-
- id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- u32_t bit_ix = (id - min_obj_id) & 7;
- int byte_ix = (id - min_obj_id) >> 3;
- if (byte_ix >= 0 && (u32_t)byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
- fs->work[byte_ix] |= (1 << bit_ix);
- }
- }
- return SPIFFS_VIS_COUNTINUE;
-}
-
-static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
- const void *user_const_p, void *user_var_p) {
- (void)user_var_p;
- if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
- s32_t res;
- const spiffs_free_obj_id_state *state = (const spiffs_free_obj_id_state *)user_const_p;
- spiffs_page_object_ix_header objix_hdr;
-
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, ix_entry), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- if (res == SPIFFS_OK && objix_hdr.p_hdr.span_ix == 0 &&
- ((objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) ==
- (SPIFFS_PH_FLAG_DELET))) {
- // ok object look up entry
- if (state->conflicting_name && strcmp((const char *)state->conflicting_name, (char *)objix_hdr.name) == 0) {
- return SPIFFS_ERR_CONFLICTING_NAME;
- }
-
- id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- if (id >= state->min_obj_id && id <= state->max_obj_id) {
- u8_t *map = (u8_t *)fs->work;
- int ix = (id - state->min_obj_id) / state->compaction;
- //SPIFFS_DBG("free_obj_id: add ix "_SPIPRIi" for id "_SPIPRIid" min"_SPIPRIid" max"_SPIPRIid" comp:"_SPIPRIi"\n", ix, id, state->min_obj_id, state->max_obj_id, state->compaction);
- map[ix]++;
- }
- }
- }
- return SPIFFS_VIS_COUNTINUE;
-}
-
-// Scans thru all object lookup for object index header pages. If total possible number of
-// object ids cannot fit into a work buffer, these are grouped. When a group containing free
-// object ids is found, the object lu is again scanned for object ids within group and bitmasked.
-// Finally, the bitmask is searched for a free id
-s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, const u8_t *conflicting_name) {
- s32_t res = SPIFFS_OK;
- u32_t max_objects = (fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) / 2;
- spiffs_free_obj_id_state state;
- spiffs_obj_id free_obj_id = SPIFFS_OBJ_ID_FREE;
- state.min_obj_id = 1;
- state.max_obj_id = max_objects + 1;
- if (state.max_obj_id & SPIFFS_OBJ_ID_IX_FLAG) {
- state.max_obj_id = ((spiffs_obj_id) - 1) & ~SPIFFS_OBJ_ID_IX_FLAG;
- }
- state.compaction = 0;
- state.conflicting_name = conflicting_name;
- while (res == SPIFFS_OK && free_obj_id == SPIFFS_OBJ_ID_FREE) {
- if (state.max_obj_id - state.min_obj_id <= (spiffs_obj_id)SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8) {
- // possible to represent in bitmap
- u32_t i, j;
- SPIFFS_DBG("free_obj_id: BITM min:"_SPIPRIid" max:"_SPIPRIid"\n", state.min_obj_id, state.max_obj_id);
-
- memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v,
- conflicting_name, &state.min_obj_id, 0, 0);
- if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
- SPIFFS_CHECK_RES(res);
- // traverse bitmask until found free obj_id
- for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs); i++) {
- u8_t mask = fs->work[i];
- if (mask == 0xff) {
- continue;
- }
- for (j = 0; j < 8; j++) {
- if ((mask & (1 << j)) == 0) {
- *obj_id = (i << 3) + j + state.min_obj_id;
- return SPIFFS_OK;
- }
- }
- }
- return SPIFFS_ERR_FULL;
- } else {
- // not possible to represent all ids in range in a bitmap, compact and count
- if (state.compaction != 0) {
- // select element in compacted table, decrease range and recompact
- u32_t i, min_i = 0;
- u8_t *map = (u8_t *)fs->work;
- u8_t min_count = 0xff;
-
- for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t); i++) {
- if (map[i] < min_count) {
- min_count = map[i];
- min_i = i;
- if (min_count == 0) {
- break;
- }
- }
- }
-
- if (min_count == state.compaction) {
- // there are no free objids!
- SPIFFS_DBGF("free_obj_id: compacted table is full\n");
- return SPIFFS_ERR_FULL;
- }
-
- SPIFFS_DBG("free_obj_id: COMP select index:"_SPIPRIi" min_count:"_SPIPRIi" min:"_SPIPRIid" max:"_SPIPRIid" compact:"_SPIPRIi"\n", min_i, min_count, state.min_obj_id, state.max_obj_id, state.compaction);
-
- if (min_count == 0) {
- // no id in this range, skip compacting and use directly
- *obj_id = min_i * state.compaction + state.min_obj_id;
- return SPIFFS_OK;
- } else {
- SPIFFS_DBG("free_obj_id: COMP SEL chunk:"_SPIPRIi" min:"_SPIPRIid" -> "_SPIPRIid"\n", state.compaction, state.min_obj_id, state.min_obj_id + min_i * state.compaction);
- state.min_obj_id += min_i * state.compaction;
- state.max_obj_id = state.min_obj_id + state.compaction;
- // decrease compaction
- }
- if ((state.max_obj_id - state.min_obj_id <= (spiffs_obj_id)SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8)) {
- // no need for compacting, use bitmap
- continue;
- }
- }
- // in a work memory of log_page_size bytes, we may fit in log_page_size ids
- // todo what if compaction is > 255 - then we cannot fit it in a byte
- state.compaction = (state.max_obj_id - state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t)));
- SPIFFS_DBG("free_obj_id: COMP min:"_SPIPRIid" max:"_SPIPRIid" compact:"_SPIPRIi"\n", state.min_obj_id, state.max_obj_id, state.compaction);
-
- memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, &state, 0, 0, 0);
- if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
- SPIFFS_CHECK_RES(res);
- state.conflicting_name = 0; // searched for conflicting name once, no need to do it again
- }
- }
-
- return res;
-}
-#endif // !SPIFFS_READ_ONLY
-
-#if SPIFFS_TEMPORAL_FD_CACHE
-// djb2 hash
-static u32_t spiffs_hash(spiffs *fs, const u8_t *name) {
- (void)fs;
- u32_t hash = 5381;
- u8_t c;
- int i = 0;
- while ((c = name[i++]) && i < SPIFFS_OBJ_NAME_LEN) {
- hash = (hash * 33) ^ c;
- }
- return hash;
-}
-#endif
-
-s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd, const char *name) {
-#if SPIFFS_TEMPORAL_FD_CACHE
- u32_t i;
- u16_t min_score = 0xffff;
- u32_t cand_ix = (u32_t) - 1;
- u32_t name_hash = name ? spiffs_hash(fs, (const u8_t *)name) : 0;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
-
- if (name) {
- // first, decrease score of all closed descriptors
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr == 0) {
- if (cur_fd->score > 1) { // score == 0 indicates never used fd
- cur_fd->score--;
- }
- }
- }
- }
-
- // find the free fd with least score or name match
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr == 0) {
- if (name && cur_fd->name_hash == name_hash) {
- cand_ix = i;
- break;
- }
- if (cur_fd->score < min_score) {
- min_score = cur_fd->score;
- cand_ix = i;
- }
- }
- }
-
- if (cand_ix != (u32_t) - 1) {
- spiffs_fd *cur_fd = &fds[cand_ix];
- if (name) {
- if (cur_fd->name_hash == name_hash && cur_fd->score > 0) {
- // opened an fd with same name hash, assume same file
- // set search point to saved obj index page and hope we have a correct match directly
- // when start searching - if not, we will just keep searching until it is found
- fs->cursor_block_ix = SPIFFS_BLOCK_FOR_PAGE(fs, cur_fd->objix_hdr_pix);
- fs->cursor_obj_lu_entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, cur_fd->objix_hdr_pix);
- // update score
- if (cur_fd->score < 0xffff - SPIFFS_TEMPORAL_CACHE_HIT_SCORE) {
- cur_fd->score += SPIFFS_TEMPORAL_CACHE_HIT_SCORE;
- } else {
- cur_fd->score = 0xffff;
- }
- } else {
- // no hash hit, restore this fd to initial state
- cur_fd->score = SPIFFS_TEMPORAL_CACHE_HIT_SCORE;
- cur_fd->name_hash = name_hash;
- }
- }
- cur_fd->file_nbr = cand_ix + 1;
- *fd = cur_fd;
- return SPIFFS_OK;
- } else {
- return SPIFFS_ERR_OUT_OF_FILE_DESCS;
- }
-#else
- (void)name;
- u32_t i;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr == 0) {
- cur_fd->file_nbr = i + 1;
- *fd = cur_fd;
- return SPIFFS_OK;
- }
- }
- return SPIFFS_ERR_OUT_OF_FILE_DESCS;
-#endif
-}
-
-s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
- if (f <= 0 || f > (s16_t)fs->fd_count) {
- return SPIFFS_ERR_BAD_DESCRIPTOR;
- }
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- spiffs_fd *fd = &fds[f - 1];
- if (fd->file_nbr == 0) {
- return SPIFFS_ERR_FILE_CLOSED;
- }
- fd->file_nbr = 0;
-#if SPIFFS_IX_MAP
- fd->ix_map = 0;
-#endif
- return SPIFFS_OK;
-}
-
-s32_t spiffs_fd_get(spiffs *fs, spiffs_file f, spiffs_fd **fd) {
- if (f <= 0 || f > (s16_t)fs->fd_count) {
- return SPIFFS_ERR_BAD_DESCRIPTOR;
- }
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- *fd = &fds[f - 1];
- if ((*fd)->file_nbr == 0) {
- return SPIFFS_ERR_FILE_CLOSED;
- }
- return SPIFFS_OK;
-}
-
-#if SPIFFS_TEMPORAL_FD_CACHE
-void spiffs_fd_temporal_cache_rehash(
- spiffs *fs,
- const char *old_path,
- const char *new_path) {
- u32_t i;
- u32_t old_hash = spiffs_hash(fs, (const u8_t *)old_path);
- u32_t new_hash = spiffs_hash(fs, (const u8_t *)new_path);
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->score > 0 && cur_fd->name_hash == old_hash) {
- cur_fd->name_hash = new_hash;
- }
- }
-}
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_nucleus.h b/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_nucleus.h
deleted file mode 100644
index 7fbf98ac..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/spiffs_nucleus.h
+++ /dev/null
@@ -1,848 +0,0 @@
-/*
- * spiffs_nucleus.h
- *
- * Created on: Jun 15, 2013
- * Author: petera
- */
-
-/* SPIFFS layout
- *
- * spiffs is designed for following spi flash characteristics:
- * - only big areas of data (blocks) can be erased
- * - erasing resets all bits in a block to ones
- * - writing pulls ones to zeroes
- * - zeroes cannot be pulled to ones, without erase
- * - wear leveling
- *
- * spiffs is also meant to be run on embedded, memory constraint devices.
- *
- * Entire area is divided in blocks. Entire area is also divided in pages.
- * Each block contains same number of pages. A page cannot be erased, but a
- * block can be erased.
- *
- * Entire area must be block_size * x
- * page_size must be block_size / (2^y) where y > 2
- *
- * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
- *
- * BLOCK 0 PAGE 0 object lookup 1
- * PAGE 1 object lookup 2
- * ...
- * PAGE n-1 object lookup n
- * PAGE n object data 1
- * PAGE n+1 object data 2
- * ...
- * PAGE n+m-1 object data m
- *
- * BLOCK 1 PAGE n+m object lookup 1
- * PAGE n+m+1 object lookup 2
- * ...
- * PAGE 2n+m-1 object lookup n
- * PAGE 2n+m object data 1
- * PAGE 2n+m object data 2
- * ...
- * PAGE 2n+2m-1 object data m
- * ...
- *
- * n is number of object lookup pages, which is number of pages needed to index all pages
- * in a block by object id
- * : block_size / page_size * sizeof(obj_id) / page_size
- * m is number data pages, which is number of pages in block minus number of lookup pages
- * : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
- * thus, n+m is total number of pages in a block
- * : block_size / page_size
- *
- * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
- *
- * Object lookup pages contain object id entries. Each entry represent the corresponding
- * data page.
- * Assuming a 16 bit object id, an object id being 0xffff represents a free page.
- * An object id being 0x0000 represents a deleted page.
- *
- * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
- * page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
- * page 2 : data : data for object id 0008
- * page 3 : data : data for object id 0001
- * page 4 : data : data for object id 0aaa
- * ...
- *
- *
- * Object data pages can be either object index pages or object content.
- * All object data pages contains a data page header, containing object id and span index.
- * The span index denotes the object page ordering amongst data pages with same object id.
- * This applies to both object index pages (when index spans more than one page of entries),
- * and object data pages.
- * An object index page contains page entries pointing to object content page. The entry index
- * in a object index page correlates to the span index in the actual object data page.
- * The first object index page (span index 0) is called object index header page, and also
- * contains object flags (directory/file), size, object name etc.
- *
- * ex:
- * BLOCK 1
- * PAGE 256: objectl lookup page 1
- * [*123] [ 123] [ 123] [ 123]
- * [ 123] [*123] [ 123] [ 123]
- * [free] [free] [free] [free] ...
- * PAGE 257: objectl lookup page 2
- * [free] [free] [free] [free] ...
- * PAGE 258: object index page (header)
- * obj.id:0123 span.ix:0000 flags:INDEX
- * size:1600 name:ex.txt type:file
- * [259] [260] [261] [262]
- * PAGE 259: object data page
- * obj.id:0123 span.ix:0000 flags:DATA
- * PAGE 260: object data page
- * obj.id:0123 span.ix:0001 flags:DATA
- * PAGE 261: object data page
- * obj.id:0123 span.ix:0002 flags:DATA
- * PAGE 262: object data page
- * obj.id:0123 span.ix:0003 flags:DATA
- * PAGE 263: object index page
- * obj.id:0123 span.ix:0001 flags:INDEX
- * [264] [265] [fre] [fre]
- * [fre] [fre] [fre] [fre]
- * PAGE 264: object data page
- * obj.id:0123 span.ix:0004 flags:DATA
- * PAGE 265: object data page
- * obj.id:0123 span.ix:0005 flags:DATA
- *
- */
-#ifndef SPIFFS_NUCLEUS_H_
-#define SPIFFS_NUCLEUS_H_
-
-#include "common.h"
-
-#include "string.h"
-#include "spiffs.h"
-
-#define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
-#define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
-#define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
-#define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
-#define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
-
-// visitor result, continue searching
-#define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
-// visitor result, continue searching after reloading lu buffer
-#define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
-// visitor result, stop searching
-#define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
-
-// updating an object index contents
-#define SPIFFS_EV_IX_UPD (0)
-// creating a new object index
-#define SPIFFS_EV_IX_NEW (1)
-// deleting an object index
-#define SPIFFS_EV_IX_DEL (2)
-// moving an object index without updating contents
-#define SPIFFS_EV_IX_MOV (3)
-// updating an object index header data only, not the table itself
-#define SPIFFS_EV_IX_UPD_HDR (4)
-
-#define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
-
-#define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
-
-#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
-#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
-
-
-
-#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
-/* For GCC, clang and TI compilers */
-#define SPIFFS_PACKED __attribute__((packed))
-#elif defined(__ICCARM__) || defined(__CC_ARM)
-/* For IAR ARM and Keil MDK-ARM compilers */
-#define SPIFFS_PACKED
-
-#else
-/* Unknown compiler */
-#define SPIFFS_PACKED
-#endif
-
-
-
-#if SPIFFS_USE_MAGIC
-#if !SPIFFS_USE_MAGIC_LENGTH
-#define SPIFFS_MAGIC(fs, bix) \
- ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
-#else // SPIFFS_USE_MAGIC_LENGTH
-#define SPIFFS_MAGIC(fs, bix) \
- ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
-#endif // SPIFFS_USE_MAGIC_LENGTH
-#endif // SPIFFS_USE_MAGIC
-
-#define SPIFFS_CONFIG_MAGIC (0x20090315)
-
-#if SPIFFS_SINGLETON == 0
-#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
- ((fs)->cfg.log_page_size)
-#define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
- ((fs)->cfg.log_block_size)
-#define SPIFFS_CFG_PHYS_SZ(fs) \
- ((fs)->cfg.phys_size)
-#define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
- ((fs)->cfg.phys_erase_block)
-#define SPIFFS_CFG_PHYS_ADDR(fs) \
- ((fs)->cfg.phys_addr)
-#endif
-
-// total number of pages
-#define SPIFFS_MAX_PAGES(fs) \
- ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
-// total number of pages per block, including object lookup pages
-#define SPIFFS_PAGES_PER_BLOCK(fs) \
- ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
-// number of object lookup pages per block
-#define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
- (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
-// checks if page index belongs to object lookup
-#define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
- (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
-// number of object lookup entries in all object lookup pages
-#define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
- (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
-// converts a block to physical address
-#define SPIFFS_BLOCK_TO_PADDR(fs, block) \
- ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
-// converts a object lookup entry to page index
-#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
- ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
-// converts a object lookup entry to physical address of corresponding page
-#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
- (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
-// converts a page to physical address
-#define SPIFFS_PAGE_TO_PADDR(fs, page) \
- ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
-// converts a physical address to page
-#define SPIFFS_PADDR_TO_PAGE(fs, addr) \
- ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
-// gives index in page for a physical address
-#define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
- ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
-// returns containing block for given page
-#define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
- ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
-// returns starting page for block
-#define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
- ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
-// converts page to entry in object lookup page
-#define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
- ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
-// returns data size in a data page
-#define SPIFFS_DATA_PAGE_SIZE(fs) \
- ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
-// returns physical address for block's erase count,
-// always in the physical last entry of the last object lookup page
-#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
- ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
-// returns physical address for block's magic,
-// always in the physical second last entry of the last object lookup page
-#define SPIFFS_MAGIC_PADDR(fs, bix) \
- ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
-// checks if there is any room for magic in the object luts
-#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
- ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
- <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
-
-// define helpers object
-
-// entries in an object header page index
-#define SPIFFS_OBJ_HDR_IX_LEN(fs) \
- ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
-// entries in an object page index
-#define SPIFFS_OBJ_IX_LEN(fs) \
- ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
-// object index entry for given data span index
-#define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
- ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
-// object index span index number for given data span index or entry
-#define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
- ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
-// get data span index for object index span index
-#define SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, spix) \
- ( (spix) == 0 ? 0 : (SPIFFS_OBJ_HDR_IX_LEN(fs) + (((spix)-1) * SPIFFS_OBJ_IX_LEN(fs))) )
-
-#if SPIFFS_FILEHDL_OFFSET
-#define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
-#define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
-#else
-#define SPIFFS_FH_OFFS(fs, fh) (fh)
-#define SPIFFS_FH_UNOFFS(fs, fh) (fh)
-#endif
-
-
-#define SPIFFS_OP_T_OBJ_LU (0<<0)
-#define SPIFFS_OP_T_OBJ_LU2 (1<<0)
-#define SPIFFS_OP_T_OBJ_IX (2<<0)
-#define SPIFFS_OP_T_OBJ_DA (3<<0)
-#define SPIFFS_OP_C_DELE (0<<2)
-#define SPIFFS_OP_C_UPDT (1<<2)
-#define SPIFFS_OP_C_MOVS (2<<2)
-#define SPIFFS_OP_C_MOVD (3<<2)
-#define SPIFFS_OP_C_FLSH (4<<2)
-#define SPIFFS_OP_C_READ (5<<2)
-#define SPIFFS_OP_C_WRTHRU (6<<2)
-
-#define SPIFFS_OP_TYPE_MASK (3<<0)
-#define SPIFFS_OP_COM_MASK (7<<2)
-
-
-// if 0, this page is written to, else clean
-#define SPIFFS_PH_FLAG_USED (1<<0)
-// if 0, writing is finalized, else under modification
-#define SPIFFS_PH_FLAG_FINAL (1<<1)
-// if 0, this is an index page, else a data page
-#define SPIFFS_PH_FLAG_INDEX (1<<2)
-// if 0, page is deleted, else valid
-#define SPIFFS_PH_FLAG_DELET (1<<7)
-// if 0, this index header is being deleted
-#define SPIFFS_PH_FLAG_IXDELE (1<<6)
-
-
-#define SPIFFS_CHECK_MOUNT(fs) \
- ((fs)->mounted != 0)
-
-#define SPIFFS_CHECK_CFG(fs) \
- ((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
-
-#define SPIFFS_CHECK_RES(res) \
- do { \
- if ((res) < SPIFFS_OK) return (res); \
- } while (0);
-
-#define SPIFFS_API_CHECK_MOUNT(fs) \
- if (!SPIFFS_CHECK_MOUNT((fs))) { \
- (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
- return SPIFFS_ERR_NOT_MOUNTED; \
- }
-
-#define SPIFFS_API_CHECK_CFG(fs) \
- if (!SPIFFS_CHECK_CFG((fs))) { \
- (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
- return SPIFFS_ERR_NOT_CONFIGURED; \
- }
-
-#define SPIFFS_API_CHECK_RES(fs, res) \
- if ((res) < SPIFFS_OK) { \
- (fs)->err_code = (res); \
- return (res); \
- }
-
-#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
- if ((res) < SPIFFS_OK) { \
- (fs)->err_code = (res); \
- SPIFFS_UNLOCK(fs); \
- return (res); \
- }
-
-#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
- if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
- if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
- if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
- if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
- if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
- if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
-//if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
-
-#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
- if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
- if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
- if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
- if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
- if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
- if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
-
-
-// check id, only visit matching objec ids
-#define SPIFFS_VIS_CHECK_ID (1<<0)
-// report argument object id to visitor - else object lookup id is reported
-#define SPIFFS_VIS_CHECK_PH (1<<1)
-// stop searching at end of all look up pages
-#define SPIFFS_VIS_NO_WRAP (1<<2)
-
-#if SPIFFS_HAL_CALLBACK_EXTRA
-
-#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
- (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
-#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
- (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
-#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
- (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
-
-#else // SPIFFS_HAL_CALLBACK_EXTRA
-
-#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
- (_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
-#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
- (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
-#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
- (_fs)->cfg.hal_erase_f((_paddr), (_len))
-
-#endif // SPIFFS_HAL_CALLBACK_EXTRA
-
-#if SPIFFS_CACHE
-
-#define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
-#define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
-#define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
-#define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
-#define SPIFFS_CACHE_FLAG_DATA (1<<4)
-#define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
-
-#define SPIFFS_CACHE_PAGE_SIZE(fs) \
- (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
-
-#define spiffs_get_cache(fs) \
- ((spiffs_cache *)((fs)->cache))
-
-#define spiffs_get_cache_page_hdr(fs, c, ix) \
- ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
-
-#define spiffs_get_cache_page(fs, c, ix) \
- ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
-
-// cache page struct
-typedef struct {
- // cache flags
- u8_t flags;
- // cache page index
- u8_t ix;
- // last access of this cache page
- u32_t last_access;
- union {
- // type read cache
- struct spix {
- // read cache page index
- spiffs_page_ix pix;
- } spix;
-#if SPIFFS_CACHE_WR
- // type write cache
- struct swrc {
- // write cache
- spiffs_obj_id obj_id;
- // offset in cache page
- u32_t offset;
- // size of cache page
- u16_t size;
- } swrc;
-#endif
- } ucache;
-} spiffs_cache_page;
-
-// cache struct
-typedef struct {
- u8_t cpage_count;
- u32_t last_access;
- u32_t cpage_use_map;
- u32_t cpage_use_mask;
- u8_t *cpages;
-} spiffs_cache;
-
-#endif
-
-
-// spiffs nucleus file descriptor
-typedef struct {
- // the filesystem of this descriptor
- spiffs *fs;
- // number of file descriptor - if 0, the file descriptor is closed
- spiffs_file file_nbr;
- // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
- spiffs_obj_id obj_id;
- // size of the file
- u32_t size;
- // cached object index header page index
- spiffs_page_ix objix_hdr_pix;
- // cached offset object index page index
- spiffs_page_ix cursor_objix_pix;
- // cached offset object index span index
- spiffs_span_ix cursor_objix_spix;
- // current absolute offset
- u32_t offset;
- // current file descriptor offset (cached)
- u32_t fdoffset;
- // fd flags
- spiffs_flags flags;
-#if SPIFFS_CACHE_WR
- spiffs_cache_page *cache_page;
-#endif
-#if SPIFFS_TEMPORAL_FD_CACHE
- // djb2 hash of filename
- u32_t name_hash;
- // hit score (score == 0 indicates never used fd)
- u16_t score;
-#endif
-#if SPIFFS_IX_MAP
- // spiffs index map, if 0 it means unmapped
- spiffs_ix_map *ix_map;
-#endif
-} spiffs_fd;
-
-
-// object structs
-
-// page header, part of each page except object lookup pages
-// NB: this is always aligned when the data page is an object index,
-// as in this case struct spiffs_page_object_ix is used
-typedef struct SPIFFS_PACKED {
- // object id
- spiffs_obj_id obj_id;
- // object span index
- spiffs_span_ix span_ix;
- // flags
- u8_t flags;
-} spiffs_page_header;
-
-// object index header page header
-typedef struct SPIFFS_PACKED
-#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
-__attribute((aligned(sizeof(spiffs_page_ix))))
-#endif
-{
- // common page header
- spiffs_page_header p_hdr;
- // alignment
- u8_t _align[4 - ((sizeof(spiffs_page_header) & 3) == 0 ? 4 : (sizeof(spiffs_page_header) & 3))];
- // size of object
- u32_t size;
- // type of object
- spiffs_obj_type type;
- // name of object
- u8_t name[SPIFFS_OBJ_NAME_LEN];
-#if SPIFFS_OBJ_META_LEN
- // metadata. not interpreted by SPIFFS in any way.
- u8_t meta[SPIFFS_OBJ_META_LEN];
-#endif
-}
-spiffs_page_object_ix_header;
-
-// object index page header
-typedef struct SPIFFS_PACKED {
- spiffs_page_header p_hdr;
- u8_t _align[4 - ((sizeof(spiffs_page_header) & 3) == 0 ? 4 : (sizeof(spiffs_page_header) & 3))];
-} spiffs_page_object_ix;
-
-// callback func for object lookup visitor
-typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
- const void *user_const_p, void *user_var_p);
-
-
-#if SPIFFS_CACHE
-#define _spiffs_rd(fs, op, fh, addr, len, dst) \
- spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
-#define _spiffs_wr(fs, op, fh, addr, len, src) \
- spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
-#else
-#define _spiffs_rd(fs, op, fh, addr, len, dst) \
- spiffs_phys_rd((fs), (addr), (len), (dst))
-#define _spiffs_wr(fs, op, fh, addr, len, src) \
- spiffs_phys_wr((fs), (addr), (len), (src))
-#endif
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-// ---------------
-
-s32_t spiffs_phys_rd(
- spiffs *fs,
-#if SPIFFS_CACHE
- u8_t op,
- spiffs_file fh,
-#endif
- u32_t addr,
- u32_t len,
- u8_t *dst);
-
-s32_t spiffs_phys_wr(
- spiffs *fs,
-#if SPIFFS_CACHE
- u8_t op,
- spiffs_file fh,
-#endif
- u32_t addr,
- u32_t len,
- u8_t *src);
-
-s32_t spiffs_phys_cpy(
- spiffs *fs,
- spiffs_file fh,
- u32_t dst,
- u32_t src,
- u32_t len);
-
-s32_t spiffs_phys_count_free_blocks(
- spiffs *fs);
-
-s32_t spiffs_obj_lu_find_entry_visitor(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- u8_t flags,
- spiffs_obj_id obj_id,
- spiffs_visitor_f v,
- const void *user_const_p,
- void *user_var_p,
- spiffs_block_ix *block_ix,
- int *lu_entry);
-
-s32_t spiffs_erase_block(
- spiffs *fs,
- spiffs_block_ix bix);
-
-#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
-s32_t spiffs_probe(
- spiffs_config *cfg);
-#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
-
-// ---------------
-
-s32_t spiffs_obj_lu_scan(
- spiffs *fs);
-
-s32_t spiffs_obj_lu_find_free_obj_id(
- spiffs *fs,
- spiffs_obj_id *obj_id,
- const u8_t *conflicting_name);
-
-s32_t spiffs_obj_lu_find_free(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- spiffs_block_ix *block_ix,
- int *lu_entry);
-
-s32_t spiffs_obj_lu_find_id(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- spiffs_obj_id obj_id,
- spiffs_block_ix *block_ix,
- int *lu_entry);
-
-s32_t spiffs_obj_lu_find_id_and_span(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix exclusion_pix,
- spiffs_page_ix *pix);
-
-s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix exclusion_pix,
- spiffs_page_ix *pix);
-
-// ---------------
-
-s32_t spiffs_page_allocate_data(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_page_header *ph,
- u8_t *data,
- u32_t len,
- u32_t page_offs,
- u8_t finalize,
- spiffs_page_ix *pix);
-
-s32_t spiffs_page_move(
- spiffs *fs,
- spiffs_file fh,
- u8_t *page_data,
- spiffs_obj_id obj_id,
- spiffs_page_header *page_hdr,
- spiffs_page_ix src_pix,
- spiffs_page_ix *dst_pix);
-
-s32_t spiffs_page_delete(
- spiffs *fs,
- spiffs_page_ix pix);
-
-// ---------------
-
-s32_t spiffs_object_create(
- spiffs *fs,
- spiffs_obj_id obj_id,
- const u8_t name[],
- const u8_t meta[],
- spiffs_obj_type type,
- spiffs_page_ix *objix_hdr_pix);
-
-s32_t spiffs_object_update_index_hdr(
- spiffs *fs,
- spiffs_fd *fd,
- spiffs_obj_id obj_id,
- spiffs_page_ix objix_hdr_pix,
- u8_t *new_objix_hdr_data,
- const u8_t name[],
- const u8_t meta[],
- u32_t size,
- spiffs_page_ix *new_pix);
-
-#if SPIFFS_IX_MAP
-
-s32_t spiffs_populate_ix_map(
- spiffs *fs,
- spiffs_fd *fd,
- u32_t vec_entry_start,
- u32_t vec_entry_end);
-
-#endif
-
-void spiffs_cb_object_event(
- spiffs *fs,
- spiffs_page_object_ix *objix,
- int ev,
- spiffs_obj_id obj_id_raw,
- spiffs_span_ix spix,
- spiffs_page_ix new_pix,
- u32_t new_size);
-
-s32_t spiffs_object_open_by_id(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_fd *fd,
- spiffs_flags flags,
- spiffs_mode mode);
-
-s32_t spiffs_object_open_by_page(
- spiffs *fs,
- spiffs_page_ix pix,
- spiffs_fd *fd,
- spiffs_flags flags,
- spiffs_mode mode);
-
-s32_t spiffs_object_append(
- spiffs_fd *fd,
- u32_t offset,
- u8_t *data,
- u32_t len);
-
-s32_t spiffs_object_modify(
- spiffs_fd *fd,
- u32_t offset,
- u8_t *data,
- u32_t len);
-
-s32_t spiffs_object_read(
- spiffs_fd *fd,
- u32_t offset,
- u32_t len,
- u8_t *dst);
-
-s32_t spiffs_object_truncate(
- spiffs_fd *fd,
- u32_t new_size,
- u8_t remove_full);
-
-s32_t spiffs_object_find_object_index_header_by_name(
- spiffs *fs,
- const u8_t name[SPIFFS_OBJ_NAME_LEN],
- spiffs_page_ix *pix);
-
-// ---------------
-
-s32_t spiffs_gc_check(
- spiffs *fs,
- u32_t len);
-
-s32_t spiffs_gc_erase_page_stats(
- spiffs *fs,
- spiffs_block_ix bix);
-
-s32_t spiffs_gc_find_candidate(
- spiffs *fs,
- spiffs_block_ix **block_candidates,
- int *candidate_count,
- char fs_crammed);
-
-s32_t spiffs_gc_clean(
- spiffs *fs,
- spiffs_block_ix bix);
-
-s32_t spiffs_gc_quick(
- spiffs *fs, u16_t max_free_pages);
-
-// ---------------
-
-s32_t spiffs_fd_find_new(
- spiffs *fs,
- spiffs_fd **fd,
- const char *name);
-
-s32_t spiffs_fd_return(
- spiffs *fs,
- spiffs_file f);
-
-s32_t spiffs_fd_get(
- spiffs *fs,
- spiffs_file f,
- spiffs_fd **fd);
-
-#if SPIFFS_TEMPORAL_FD_CACHE
-void spiffs_fd_temporal_cache_rehash(
- spiffs *fs,
- const char *old_path,
- const char *new_path);
-#endif
-
-#if SPIFFS_CACHE
-void spiffs_cache_init(
- spiffs *fs);
-
-void spiffs_cache_drop_page(
- spiffs *fs,
- spiffs_page_ix pix);
-
-#if SPIFFS_CACHE_WR
-spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
- spiffs *fs,
- spiffs_fd *fd);
-
-void spiffs_cache_fd_release(
- spiffs *fs,
- spiffs_cache_page *cp);
-
-spiffs_cache_page *spiffs_cache_page_get_by_fd(
- spiffs *fs,
- spiffs_fd *fd);
-#endif
-#endif
-
-s32_t spiffs_lookup_consistency_check(
- spiffs *fs,
- u8_t check_all_objects);
-
-s32_t spiffs_page_consistency_check(
- spiffs *fs);
-
-s32_t spiffs_object_index_consistency_check(
- spiffs *fs);
-
-// memcpy macro,
-// checked in test builds, otherwise plain memcpy (unless already defined)
-#ifdef _SPIFFS_TEST
-#define _SPIFFS_MEMCPY(__d, __s, __l) do { \
- intptr_t __a1 = (intptr_t)((u8_t*)(__s)); \
- intptr_t __a2 = (intptr_t)((u8_t*)(__s)+(__l)); \
- intptr_t __b1 = (intptr_t)((u8_t*)(__d)); \
- intptr_t __b2 = (intptr_t)((u8_t*)(__d)+(__l)); \
- if (__a1 <= __b2 && __b1 <= __a2) { \
- printf("FATAL OVERLAP: memcpy from %lx..%lx to %lx..%lx\n", __a1, __a2, __b1, __b2); \
- ERREXIT(); \
- } \
- memcpy((__d),(__s),(__l)); \
-} while (0)
-#else
-#ifndef _SPIFFS_MEMCPY
-#define _SPIFFS_MEMCPY(__d, __s, __l) do{memcpy((__d),(__s),(__l));}while(0)
-#endif
-#endif //_SPIFFS_TEST
-
-#endif /* SPIFFS_NUCLEUS_H_ */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/start.c b/pm3rdv4rrg/src/main/cpp/armsrc/start.c
deleted file mode 100644
index 3e6f3470..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/start.c
+++ /dev/null
@@ -1,82 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Mar 2006
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Just vector to AppMain(). This is in its own file so that I can place it
-// with the linker script.
-//-----------------------------------------------------------------------------
-
-#ifndef __START_H
-#define __START_H
-
-#include "proxmark3_arm.h"
-#include "appmain.h"
-#include "zlib.h"
-#include "BigBuf.h"
-
-static uint8_t *next_free_memory;
-extern struct common_area common_area;
-extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__;
-
-static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) {
- uint8_t *allocated_memory;
-
- allocated_memory = next_free_memory;
- next_free_memory += items * size;
- return allocated_memory;
-}
-
-static void inflate_free(voidpf opaque, voidpf address) {
- // nothing to do
-}
-
-static void uncompress_data_section(void) {
- z_stream data_section;
-
- next_free_memory = BigBuf_get_addr();
-
- // initialize zstream structure
- data_section.next_in = (uint8_t *) &__data_src_start__;
- data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter.
- data_section.next_out = (uint8_t *) &__data_start__;
- data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct.
- data_section.zalloc = &inflate_malloc;
- data_section.zfree = &inflate_free;
- data_section.opaque = NULL;
-
- // initialize zlib for inflate
- int res = inflateInit2(&data_section, 15);
- if (res < 0)
- return;
-
- // uncompress data segment to RAM
- inflate(&data_section, Z_FINISH);
-
- // save the size of the compressed data section
- common_area.arg1 = data_section.total_in;
-}
-
-void __attribute__((section(".startos"))) Vector(void) {
- /* Stack should have been set up by the bootloader */
- // char *src;
- char *dst, *end;
-
- uncompress_data_section();
-
- /* Set up (that is: clear) BSS. */
- dst = &__bss_start__;
- end = &__bss_end__;
- while (dst < end) *dst++ = 0;
-
- // Set up data segment: Copy from flash to ram
- // src = &__data_src_start__;
- // dst = &__data_start__;
- // end = &__data_end__;
- // while(dst < end) *dst++ = *src++;
-
- AppMain();
-}
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/string.c b/pm3rdv4rrg/src/main/cpp/armsrc/string.c
deleted file mode 100644
index 8dbe2680..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/string.c
+++ /dev/null
@@ -1,334 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Sept 2005
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Common string.h functions
-//-----------------------------------------------------------------------------
-#include "string.h"
-
-void *memcpy(void *dest, const void *src, int len) {
- uint8_t *d = dest;
- const uint8_t *s = src;
- while ((len--) > 0) {
- *d = *s;
- d++;
- s++;
- }
- return dest;
-}
-
-void *memset(void *dest, int c, int len) {
- uint8_t *d = dest;
- while ((len--) > 0) {
- *d = c;
- d++;
- }
- return dest;
-}
-
-int memcmp(const void *av, const void *bv, int len) {
- const uint8_t *a = av;
- const uint8_t *b = bv;
-
- while ((len--) > 0) {
- if (*a != *b) {
- return *a - *b;
- }
- a++;
- b++;
- }
- return 0;
-}
-
-void memxor(uint8_t *dest, uint8_t *src, size_t len) {
- for (; len > 0; len--, dest++, src++)
- *dest ^= *src;
-}
-
-int strlen(const char *str) {
- const char *p;
- for (p = str; *p != '\0'; ++p) {};
- return p - str;
-}
-
-char *strncat(char *dest, const char *src, unsigned int n) {
- unsigned int dest_len = strlen(dest);
- unsigned int i;
-
- for (i = 0 ; i < n && src[i] != '\0' ; i++)
- dest[dest_len + i] = src[i];
- dest[dest_len + i] = '\0';
-
- return dest;
-}
-
-char *strcat(char *dest, const char *src) {
- unsigned int dest_len = strlen(dest);
- unsigned int i;
-
- for (i = 0 ; src[i] != '\0' ; i++)
- dest[dest_len + i] = src[i];
- dest[dest_len + i] = '\0';
-
- return dest;
-}
-////////////////////////////////////////// code to do 'itoa'
-
-/* reverse: reverse string s in place */
-void strreverse(char s[]) {
- int j = strlen(s) - 1;
-
- for (int i = 0; i < j; i++, j--) {
- int c = s[i];
- s[i] = s[j];
- s[j] = c;
- }
-}
-
-/* itoa: convert n to characters in s */
-void itoa(int n, char s[]) {
- int i, sign;
-
- if ((sign = n) < 0) /* record sign */
- n = -n; /* make n positive */
- i = 0;
- do { /* generate digits in reverse order */
- s[i++] = n % 10 + '0'; /* get next digit */
- } while ((n /= 10) > 0); /* delete it */
- if (sign < 0)
- s[i++] = '-';
- s[i] = '\0';
- strreverse(s);
-}
-
-//////////////////////////////////////// END 'itoa' CODE
-
-
-
-char *strcpy(char *dst, const char *src) {
- char *save = dst;
-
- for (; (*dst = *src) != '\0'; ++src, ++dst);
- return save;
-}
-
-char *strncpy(char *dst, const char *src, size_t n) {
- if (n != 0) {
- char *d = dst;
- const char *s = src;
-
- do {
- if ((*d++ = *s++) == 0) {
- /* NUL pad the remaining n-1 bytes */
- while (--n) {
- *d++ = 0;
- }
- break;
- }
- } while (--n);
- }
- return dst;
-}
-
-int strcmp(const char *s1, const char *s2) {
- while (*s1 == *s2++) {
- if (*s1++ == 0) {
- return (0);
- }
- }
- return (*(unsigned char *) s1 - * (unsigned char *) --s2);
-}
-
-char *__strtok_r(char *, const char *, char **);
-
-char *__strtok_r(char *s, const char *delim, char **last) {
- char *spanp, *tok;
- int c, sc;
-
- if (s == NULL && (s = *last) == NULL)
- return (NULL);
-
- /*
- * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
- */
-cont:
- c = *s++;
- for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
- if (c == sc)
- goto cont;
- }
-
- if (c == 0) {
- /* no non-delimiter characters */
- *last = NULL;
- return (NULL);
- }
- tok = s - 1;
-
- /*
- * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
- * Note that delim must have one NUL; we stop if we see that, too.
- */
- for (;;) {
- c = *s++;
- spanp = (char *)delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = '\0';
- *last = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
-}
-
-char *strtok(char *s, const char *delim) {
- static char *last;
-
- return (__strtok_r(s, delim, &last));
-}
-
-
-char *strchr(const char *s, int c) {
- while (*s != (char)c)
- if (!*s++)
- return 0;
- return (char *)s;
-}
-
-size_t strspn(const char *s1, const char *s2) {
- size_t ret = 0;
- while (*s1 && strchr(s2, *s1++))
- ret++;
- return ret;
-}
-
-char *strrchr(const char *s, int c) {
- const char *ret = 0;
- do {
- if (*s == (char)c)
- ret = s;
- } while (*s++);
- return (char *)ret;
-}
-
-size_t strcspn(const char *s1, const char *s2) {
- size_t ret = 0;
- while (*s1)
- if (strchr(s2, *s1))
- return ret;
- else
- s1++, ret++;
- return ret;
-}
-
-char *strpbrk(const char *s1, const char *s2) {
- while (*s1)
- if (strchr(s2, *s1++))
- return (char *)--s1;
- return 0;
-}
-
-int strncmp(const char *s1, const char *s2, size_t n) {
- while (n--)
- if (*s1++ != *s2++)
- return *(unsigned char *)(s1 - 1) - *(unsigned char *)(s2 - 1);
- return 0;
-}
-
-
-
-
-#define isspace(a) __extension__ ({ unsigned char bb__isspace = (a) - 9; bb__isspace == (' ' - 9) || bb__isspace <= (13 - 9); })
-
-unsigned long strtoul(const char *p, char **out_p, int base) {
- unsigned long v = 0;
-
- while (isspace(*p))
- p++;
- if (((base == 16) || (base == 0)) &&
- ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X')))) {
- p += 2;
- base = 16;
- }
- if (base == 0) {
- if (*p == '0')
- base = 8;
- else
- base = 10;
- }
- while (1) {
- char c = *p;
- if ((c >= '0') && (c <= '9') && (c - '0' < base))
- v = (v * base) + (c - '0');
- else if ((c >= 'a') && (c <= 'z') && (c - 'a' + 10 < base))
- v = (v * base) + (c - 'a' + 10);
- else if ((c >= 'A') && (c <= 'Z') && (c - 'A' + 10 < base))
- v = (v * base) + (c - 'A' + 10);
- else
- break;
- p++;
- }
-
- if (out_p) *out_p = (char *)p;
- return v;
-}
-
-long strtol(const char *p, char **out_p, int base) {
- long v = 0;
- int is_neg = 0;
-
- while (isspace(*p))
- p++;
- if (*p == '-')
- is_neg = 1, p++;
- else if (*p == '+')
- is_neg = 0;
- if (((base == 16) || (base == 0)) &&
- ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X')))) {
- p += 2;
- base = 16;
- }
- if (base == 0) {
- if (*p == '0')
- base = 8;
- else
- base = 10;
- }
- while (1) {
- char c = *p;
- if ((c >= '0') && (c <= '9') && (c - '0' < base))
- v = (v * base) + (c - '0');
- else if ((c >= 'a') && (c <= 'z') && (c - 'a' + 10 < base))
- v = (v * base) + (c - 'a' + 10);
- else if ((c >= 'A') && (c <= 'Z') && (c - 'A' + 10 < base))
- v = (v * base) + (c - 'A' + 10);
- else
- break;
- p++;
- }
- if (is_neg)
- v = -v;
- if (out_p) *out_p = (char *)p;
- return v;
-}
-
-char c_tolower(int c) {
- // (int)a = 97, (int)A = 65
- // (a)97 - (A)65 = 32
- // therefore 32 + 65 = a
- return c > 64 && c < 91 ? c + 32 : c;
-}
-
-char c_isprint(unsigned char c) {
- if (c >= 0x20 && c <= 0x7e)
- return 1;
- return 0;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/string.h b/pm3rdv4rrg/src/main/cpp/armsrc/string.h
deleted file mode 100644
index 0ebb4ab5..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/string.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Copyright (C) 2010 Hector Martin "marcan"
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Common string.h functions
-//-----------------------------------------------------------------------------
-
-#ifndef __STRING_H
-#define __STRING_H
-
-#include "common.h"
-
-int strlen(const char *str);
-void *memcpy(void *dest, const void *src, int len);
-void *memset(void *dest, int c, int len);
-int memcmp(const void *av, const void *bv, int len);
-void memxor(uint8_t *dest, uint8_t *src, size_t len);
-char *strncat(char *dest, const char *src, unsigned int n);
-char *strcat(char *dest, const char *src);
-void strreverse(char s[]);
-void itoa(int n, char s[]);
-char *strcpy(char *dst, const char *src);
-char *strncpy(char *dst, const char *src, size_t n);
-int strcmp(const char *s1, const char *s2);
-char *strtok(char *s, const char *delim);
-char *strchr(const char *s, int c);
-size_t strspn(const char *s1, const char *s2);
-char *strrchr(const char *s, int c);
-size_t strcspn(const char *s1, const char *s2);
-char *strpbrk(const char *s1, const char *s2);
-int strncmp(const char *s1, const char *s2, size_t n);
-char c_tolower(int c);
-char c_isprint(unsigned char c);
-
-#endif /* __STRING_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/thinfilm.c b/pm3rdv4rrg/src/main/cpp/armsrc/thinfilm.c
deleted file mode 100644
index d9659f6d..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/thinfilm.c
+++ /dev/null
@@ -1,162 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2019 iceman
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support a mangeled ISO 14443 type A for Thinfilm tags by Kovio
-//-----------------------------------------------------------------------------
-
-#include "thinfilm.h"
-
-#include "proxmark3_arm.h"
-#include "cmd.h"
-#include "appmain.h"
-#include "BigBuf.h"
-#include "iso14443a.h"
-#include "fpgaloader.h"
-#include "ticks.h"
-#include "dbprint.h"
-#include "util.h"
-
-/**
- * ref
- * https://www.thinfilmnfc.com/wp-content/uploads/2017/09/Thinfilm-Kovio-NFC-Barcode-Protocol-Tag-Functional-Specification-v3.4-2017-05-26.pdf
- * https://developer.android.com/reference/android/nfc/tech/NfcBarcode
- *
- */
-
-void ReadThinFilm(void) {
-
- clear_trace();
-
- set_tracing(true);
-
- iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-
- uint8_t len = 0;
- uint8_t buf[36] = {0x00};
-
- // power on and listen for answer.
- bool status = GetIso14443aAnswerFromTag_Thinfilm(buf, &len);
- reply_ng(CMD_HF_THINFILM_READ, status ? PM3_SUCCESS : PM3_ENODATA, buf, len);
-
- hf_field_off();
- set_tracing(false);
-}
-
-#define SEC_D 0xf0
-#define SEC_E 0x0f
-#define SEC_F 0x00
-uint16_t FpgaSendQueueDelay;
-
-uint16_t ReadReaderField(void) {
- uint16_t hf_av = AvgAdc(ADC_CHAN_HF);
- if (((MAX_ADC_HF_VOLTAGE * hf_av) >> 10) > MAX_ADC_HF_VOLTAGE - 300)
- hf_av = AvgAdc(ADC_CHAN_HF_RDV40);
- return hf_av;
-}
-
-static void CodeThinfilmAsTag(const uint8_t *cmd, uint16_t len) {
- ToSendReset();
- for (uint16_t i = 0; i < len; i++) {
- uint8_t b = cmd[i];
- for (uint8_t j = 0; j < 8; j++) {
- ToSend[++ToSendMax] = (b & 0x80) ? SEC_D : SEC_E;
- b <<= 1;
- }
- }
- ToSendMax++;
-}
-
-int EmSendCmdThinfilmRaw(uint8_t *resp, uint16_t respLen) {
- volatile uint8_t b;
- uint16_t i = 0;
- uint32_t ThisTransferTime;
- // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
- for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
- while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
- if (AT91C_BASE_SSC->SSC_RHR) break;
- }
- while ((ThisTransferTime = GetCountSspClk()) & 0x00000007);
-
-
- // Clear TXRDY:
- AT91C_BASE_SSC->SSC_THR = SEC_F;
-
- // write cycle
- for (; i < respLen;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = resp[i++];
- FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- }
-
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
- (void)b;
- }
- if (BUTTON_PRESS()) break;
- }
-
- // Ensure that the FPGA Delay Queue is empty
- uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
- for (i = 0; i <= fpga_queued_bits / 8 + 1;) {
- if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = SEC_F;
- FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- i++;
- }
- }
-
- return 0;
-}
-
-void SimulateThinFilm(uint8_t *data, size_t len) {
- Dbprintf("Simulate %i-bit Thinfilm tag", len * 8);
- Dbhexdump(len, data, true);
- int16_t status = PM3_SUCCESS;
- CodeThinfilmAsTag(data, len);
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- // Set up the synchronous serial port
- FpgaSetupSsc();
- // connect Demodulated Signal to ADC:
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
- SpinDelay(100);
- uint16_t hf_baseline = ReadReaderField();
-
- // Start the timer
- StartCountSspClk();
-
- bool reader_detected = false;
- LED_A_ON();
- for (;;) {
- WDT_HIT();
- if (BUTTON_PRESS() || data_available()) {
- status = PM3_EOPABORTED;
- break;
- }
- uint16_t hf_av = ReadReaderField();
- if (hf_av < hf_baseline)
- hf_baseline = hf_av;
- if (hf_av > hf_baseline + 10) {
- EmSendCmdThinfilmRaw(ToSend, ToSendMax);
- if (!reader_detected) {
- LED_B_ON();
- //Dbprintf("Reader detected, start beaming data");
- reader_detected = true;
- }
- } else {
- if (reader_detected) {
- LED_B_OFF();
- //Dbprintf("Reader gone, stop beaming data");
- reader_detected = false;
- }
- }
- }
- LED_A_OFF();
- reply_ng(CMD_HF_THINFILM_SIMULATE, status, NULL, 0);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/thinfilm.h b/pm3rdv4rrg/src/main/cpp/armsrc/thinfilm.h
deleted file mode 100644
index af156448..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/thinfilm.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//-----------------------------------------------------------------------------
-// Iceman - August 2019
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support a mangeled ISO 14443 type A for Thinfilm tags by Kovio
-//-----------------------------------------------------------------------------
-
-#ifndef __THINFILM_H
-#define __THINFILM_H
-
-#include "common.h"
-
-void ReadThinFilm(void);
-void SimulateThinFilm(uint8_t *data, size_t len);
-
-#endif /* __ISO14443A_H */
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/ticks.c b/pm3rdv4rrg/src/main/cpp/armsrc/ticks.c
deleted file mode 100644
index 0ce55e41..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/ticks.c
+++ /dev/null
@@ -1,264 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Sept 2005
-// Iceman, Sept 2016
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Timers, Clocks functions used in LF or Legic where you would need detailed time.
-//-----------------------------------------------------------------------------
-#include "ticks.h"
-
-#include "proxmark3_arm.h"
-#include "dbprint.h"
-
-// timer counts in 21.3us increments (1024/48MHz), rounding applies
-// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
-void SpinDelayUs(int us) {
- int ticks = ((MCK / 1000000) * us + 512) >> 10;
-
- // Borrow a PWM unit for my real-time clock
- AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
-
- // 48 MHz / 1024 gives 46.875 kHz
- AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register
- AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
- AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register
-
- uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-
- for (;;) {
- uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
- if (now == (uint16_t)(start + ticks))
- return;
-
- WDT_HIT();
- }
-}
-
-// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
-void SpinDelay(int ms) {
- if (ms > 1390) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, SpinDelay called with %i > 1390"), ms);
- ms = 1390;
- }
- // convert to us and call microsecond delay function
- SpinDelayUs(ms * 1000);
-}
-// -------------------------------------------------------------------------
-// timer lib
-// -------------------------------------------------------------------------
-// test procedure:
-//
-// ti = GetTickCount();
-// SpinDelay(1000);
-// ti = GetTickCount() - ti;
-// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount());
-void StartTickCount(void) {
- // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz.
- // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register.
- while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
- uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
- // set RealTimeCounter divider to count at 1kHz, should be 32 if RC is exactly at 32kHz:
- AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((((MAINCK / 1000 * 16) + (mainf / 2)) / mainf) & AT91C_RTTC_RTPRES);
- // note: worst case precision is approx 2.5%
-}
-
-/*
-* Get the current count.
-*/
-uint32_t RAMFUNC GetTickCount(void) {
- return AT91C_BASE_RTTC->RTTC_RTVR;
-}
-
-uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks) {
- uint32_t stop_ticks = AT91C_BASE_RTTC->RTTC_RTVR;
- if (stop_ticks >= start_ticks)
- return stop_ticks - start_ticks;
- return (UINT32_MAX - start_ticks) + stop_ticks;
-}
-
-// -------------------------------------------------------------------------
-// microseconds timer
-// -------------------------------------------------------------------------
-void StartCountUS(void) {
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
- AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
-
- // fast clock
- // tick=1.5mks
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
- AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
- AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
- AT91C_BASE_TC0->TC_RA = 1;
- AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
-
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
-
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TCB->TCB_BCR = 1;
-
- while (AT91C_BASE_TC1->TC_CV > 0);
-}
-
-uint32_t RAMFUNC GetCountUS(void) {
- //return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
- // By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
- return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
-}
-
-// -------------------------------------------------------------------------
-// Timer for iso14443 commands. Uses ssp_clk from FPGA
-// -------------------------------------------------------------------------
-void StartCountSspClk(void) {
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers
- AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1
- | AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none
- | AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0
-
- // configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs:
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // disable TC1
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz
- | AT91C_TC_CPCSTOP // Stop clock on RC compare
- | AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event
- | AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
- | AT91C_TC_ENETRG // Enable external trigger event
- | AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare
- | AT91C_TC_WAVE // Waveform Mode
- | AT91C_TC_AEEVT_SET // Set TIOA1 on external event
- | AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare
- AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04
-
- // use TC0 to count TIOA1 pulses
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1
- | AT91C_TC_WAVE // Waveform Mode
- | AT91C_TC_WAVESEL_UP // just count
- | AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare
- | AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare
- AT91C_BASE_TC0->TC_RA = 1; // RA Compare value = 1; pulse width to TC2
- AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow
-
- // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk)
- AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2
- AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0
- | AT91C_TC_WAVE // Waveform Mode
- | AT91C_TC_WAVESEL_UP; // just count
-
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1
- AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC2
-
- // synchronize the counter with the ssp_frame signal.
- // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present
- while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame)
- while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low
- while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high
-
- // note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame
- // it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge
- AT91C_BASE_TCB->TCB_BCR = 1; // assert Sync (set all timers to 0 on next active clock edge)
- // at the next (3rd) ssp_clk rising edge, TC1 will be reset (and not generate a clock signal to TC0)
- // at the next (4th) ssp_clk rising edge, TC0 (the low word of our counter) will be reset. From now on,
- // whenever the last three bits of our counter go 0, we can be sure to be in the middle of a frame transfer.
- // (just started with the transfer of the 4th Bit).
-
- // The high word of the counter (TC2) will not reset until the low word (TC0) overflows.
- // Therefore need to wait quite some time before we can use the counter.
- while (AT91C_BASE_TC2->TC_CV > 0);
-}
-void ResetSspClk(void) {
- //enable clock of timer and software trigger
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- while (AT91C_BASE_TC2->TC_CV > 0);
-}
-uint32_t RAMFUNC GetCountSspClk(void) {
- uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV;
- if ((tmp_count & 0x0000ffff) == 0) //small chance that we may have missed an increment in TC2
- return (AT91C_BASE_TC2->TC_CV << 16);
- return tmp_count;
-}
-
-uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start) {
- uint32_t stop = GetCountSspClk();
- if (stop >= start)
- return stop - start;
- return (UINT32_MAX - start) + stop;
-}
-
-// -------------------------------------------------------------------------
-// Timer for bitbanging, or LF stuff when you need a very precis timer
-// 1us = 1.5ticks
-// -------------------------------------------------------------------------
-void StartTicks(void) {
- // initialization of the timer
- AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
- AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
-
- // disable TC0 and TC1 for re-configuration
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-
- // first configure TC1 (higher, 0xFFFF0000) 16 bit counter
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0
-
- // second configure TC0 (lower, 0x0000FFFF) 16 bit counter
- AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
- AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO |
- AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit)
- AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit)
- AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit)
- AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero
- AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer
-
- // synchronized startup procedure
- while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
- while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared)
-
- // return to zero
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
- while (AT91C_BASE_TC0->TC_CV > 0);
-}
-
-uint32_t GetTicks(void) {
- uint32_t hi, lo;
-
- do {
- hi = AT91C_BASE_TC1->TC_CV;
- lo = AT91C_BASE_TC0->TC_CV;
- } while (hi != AT91C_BASE_TC1->TC_CV);
-
- return (hi << 16) | lo;
-}
-
-// Wait - Spindelay in ticks.
-// if called with a high number, this will trigger the WDT...
-void WaitTicks(uint32_t ticks) {
- if (ticks == 0) return;
- ticks += GetTicks();
- while (GetTicks() < ticks);
-}
-
-// Wait / Spindelay in us (microseconds)
-// 1us = 1.5ticks.
-void WaitUS(uint32_t us) {
- WaitTicks((us & 0x3FFFFFFF) * 3 / 2);
-}
-void WaitMS(uint32_t ms) {
- WaitTicks((ms & 0x1FFFFF) * 1500);
-}
-
-// stop clock
-void StopTicks(void) {
- AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/ticks.h b/pm3rdv4rrg/src/main/cpp/armsrc/ticks.h
deleted file mode 100644
index b39ec52b..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/ticks.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-// Iceman, Sept 2016
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Timers, Clocks functions used in LF or Legic where you would need detailed time.
-//-----------------------------------------------------------------------------
-
-#ifndef __TICKS_H
-#define __TICKS_H
-
-#include "common.h"
-
-#ifndef GET_TICKS
-#define GET_TICKS GetTicks()
-#endif
-
-void SpinDelay(int ms);
-void SpinDelayUs(int us);
-
-void StartTickCount(void);
-uint32_t RAMFUNC GetTickCount(void);
-uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks);
-
-void StartCountUS(void);
-uint32_t RAMFUNC GetCountUS(void);
-void ResetUSClock(void);
-void SpinDelayCountUs(uint32_t us);
-
-void StartCountSspClk();
-void ResetSspClk(void);
-uint32_t RAMFUNC GetCountSspClk();
-uint32_t RAMFUNC GetCountSspClkDelta();
-
-void StartTicks(void);
-uint32_t GetTicks(void);
-void WaitTicks(uint32_t ticks);
-void WaitUS(uint32_t us);
-void WaitMS(uint32_t ms);
-
-void StopTicks(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/usart.c b/pm3rdv4rrg/src/main/cpp/armsrc/usart.c
deleted file mode 100644
index 85325de5..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/usart.c
+++ /dev/null
@@ -1,263 +0,0 @@
-//-----------------------------------------------------------------------------
-// Iceman, July 2018
-// edits by - Anticat, August 2018
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// The main USART code, for serial communications over FPC connector
-//-----------------------------------------------------------------------------
-#include "usart.h"
-#include "proxmark3_arm.h"
-
-volatile AT91PS_USART pUS1 = AT91C_BASE_US1;
-volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
-volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1;
-
-uint32_t usart_baudrate = 0;
-uint8_t usart_parity = 0;
-/*
-void usart_close(void) {
- // Reset the USART mode
- pUS1->US_MR = 0;
-
- // Reset the baud rate divisor register
- pUS1->US_BRGR = 0;
-
- // Reset the Timeguard Register
- pUS1->US_TTGR = 0;
-
- // Disable all interrupts
- pUS1->US_IDR = 0xFFFFFFFF;
-
- // Abort the Peripheral Data Transfers
- pUS1->US_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
-
- // Disable receiver and transmitter and stop any activity immediately
- pUS1->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS | AT91C_US_RSTTX | AT91C_US_RSTRX;
-}
-*/
-
-static uint8_t us_inbuf1[USART_BUFFLEN];
-static uint8_t us_inbuf2[USART_BUFFLEN];
-uint8_t *usart_cur_inbuf = NULL;
-uint16_t usart_cur_inbuf_off = 0;
-static uint8_t us_rxfifo[USART_FIFOLEN];
-static size_t us_rxfifo_low = 0;
-static size_t us_rxfifo_high = 0;
-
-
-static void usart_fill_rxfifo(void) {
- uint16_t rxfifo_free ;
- if (pUS1->US_RNCR == 0) { // One buffer got filled, backup buffer being used
- if (us_rxfifo_low > us_rxfifo_high)
- rxfifo_free = us_rxfifo_low - us_rxfifo_high;
- else
- rxfifo_free = sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low;
- uint16_t available = USART_BUFFLEN - usart_cur_inbuf_off;
- if (available <= rxfifo_free) {
- for (uint16_t i = 0; i < available; i++) {
- us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
- if (us_rxfifo_high == sizeof(us_rxfifo))
- us_rxfifo_high = 0;
- }
- // Give next buffer
- pUS1->US_RNPR = (uint32_t)usart_cur_inbuf;
- pUS1->US_RNCR = USART_BUFFLEN;
- // Swap current buff
- if (usart_cur_inbuf == us_inbuf1)
- usart_cur_inbuf = us_inbuf2;
- else
- usart_cur_inbuf = us_inbuf1;
- usart_cur_inbuf_off = 0;
- } else {
- // Take only what we have room for
- available = rxfifo_free;
- for (uint16_t i = 0; i < available; i++) {
- us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
- if (us_rxfifo_high == sizeof(us_rxfifo))
- us_rxfifo_high = 0;
- }
- usart_cur_inbuf_off += available;
- return;
- }
- }
- if (pUS1->US_RCR < USART_BUFFLEN - usart_cur_inbuf_off) { // Current buffer partially filled
- if (us_rxfifo_low > us_rxfifo_high)
- rxfifo_free = us_rxfifo_low - us_rxfifo_high;
- else
- rxfifo_free = sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low;
- uint16_t available = USART_BUFFLEN - pUS1->US_RCR - usart_cur_inbuf_off;
- if (available > rxfifo_free)
- available = rxfifo_free;
- for (uint16_t i = 0; i < available; i++) {
- us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
- if (us_rxfifo_high == sizeof(us_rxfifo))
- us_rxfifo_high = 0;
- }
- usart_cur_inbuf_off += available;
- }
-}
-
-uint16_t usart_rxdata_available(void) {
- usart_fill_rxfifo();
- if (us_rxfifo_low <= us_rxfifo_high)
- return us_rxfifo_high - us_rxfifo_low;
- else
- return sizeof(us_rxfifo) - us_rxfifo_low + us_rxfifo_high;
-}
-
-uint32_t usart_read_ng(uint8_t *data, size_t len) {
- if (len == 0) return 0;
- uint32_t nbBytesRcv = 0;
- uint32_t try = 0;
-// uint32_t highest_observed_try = 0;
- // Empirical max try observed: 3000000 / USART_BAUD_RATE
- // Let's take 10x
-
- uint32_t tryconstant = 0;
-#ifdef USART_SLOW_LINK
- // Experienced up to 13200 tries on BT link even at 460800
- tryconstant = 50000;
-#endif
-
- uint32_t maxtry = 10 * (3000000 / USART_BAUD_RATE) + tryconstant;
-
- while (len) {
- uint32_t available = usart_rxdata_available();
-
- uint32_t packetSize = MIN(available, len);
- if (available > 0) {
-// Dbprintf_usb("Dbg USART ask %d bytes, available %d bytes, packetsize %d bytes", len, available, packetSize);
-// highest_observed_try = MAX(highest_observed_try, try);
- try = 0;
- }
- len -= packetSize;
- while (packetSize--) {
- data[nbBytesRcv++] = us_rxfifo[us_rxfifo_low++];
- if (us_rxfifo_low == sizeof(us_rxfifo))
- us_rxfifo_low = 0;
- }
- if (try++ == maxtry) {
-// Dbprintf_usb("Dbg USART TIMEOUT");
- break;
- }
- }
-// highest_observed_try = MAX(highest_observed_try, try);
-// Dbprintf_usb("Dbg USART max observed try %i", highest_observed_try);
- return nbBytesRcv;
-}
-
-// transfer from devices to client
-inline int usart_writebuffer_sync(uint8_t *data, size_t len) {
-
- // Wait for current PDC bank to be free
- // (and check next bank too, in case there will be a usart_writebuffer_async)
- while (pUS1->US_TNCR || pUS1->US_TCR) {};
- pUS1->US_TPR = (uint32_t)data;
- pUS1->US_TCR = len;
- // Wait until finishing all transfers to make sure "data" buffer can be discarded
- // (if we don't wait here, bulk write as e.g. "hw status" will fail)
- while (pUS1->US_TNCR || pUS1->US_TCR) {};
- return PM3_SUCCESS;
-}
-
-void usart_init(uint32_t baudrate, uint8_t parity) {
-
- if (baudrate != 0)
- usart_baudrate = baudrate;
- if ((parity == 'N') || (parity == 'O') || (parity == 'E'))
- usart_parity = parity;
-
- // For a nice detailed sample, interrupt driven but still relevant.
- // See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf
-
- // disable & reset receiver / transmitter for configuration
- pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS);
-
- //enable the USART1 Peripheral clock
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
-
- // disable PIO control of read / transmit pins
- pPIO->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
-
- // enable peripheral mode A on read / transmit pins
- pPIO->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
- pPIO->PIO_BSR = 0;
-
- // enable pull-up on read / transmit pins (see 31.5.1 I/O Lines)
- pPIO->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
-
- // set mode
- uint32_t mode = AT91C_US_USMODE_NORMAL | // normal mode
- AT91C_US_CLKS_CLOCK | // MCK (48MHz)
- AT91C_US_OVER | // oversampling
- AT91C_US_CHRL_8_BITS | // 8 bits
- AT91C_US_NBSTOP_1_BIT | // 1 stop bit
- AT91C_US_CHMODE_NORMAL; // channel mode: normal
-
- switch (usart_parity) {
- case 'N':
- mode |= AT91C_US_PAR_NONE; // parity: none
- break;
- case 'O':
- mode |= AT91C_US_PAR_ODD; // parity: odd
- break;
- case 'E':
- mode |= AT91C_US_PAR_EVEN; // parity: even
- break;
- }
- pUS1->US_MR = mode;
-
- // all interrupts disabled
- pUS1->US_IDR = 0xFFFF;
-
- // http://ww1.microchip.com/downloads/en/DeviceDoc/doc6175.pdf
- // note that for very large baudrates, error is not neglectible:
- // b921600 => 8.6%
- // b1382400 => 8.6%
- // FP, Fractional Part (Datasheet p402, Supported in AT91SAM512 / 256) (31.6.1.3)
- // FP = 0 disabled;
- // FP = 1-7 Baudrate resolution,
- // CD, Clock divider,
- // sync == 0 , (async?)
- // OVER = 0, -no
- // baudrate == selected clock/16/CD
- // OVER = 1, -yes we are oversampling
- // baudrate == selected clock/8/CD --> this is ours
- //
- uint32_t brgr = MCK / (usart_baudrate << 3);
- // doing fp = round((mck / (usart_baudrate << 3) - brgr) * 8) with integers:
- uint32_t fp = ((16 * MCK / (usart_baudrate << 3) - 16 * brgr) + 1) / 2;
-
- pUS1->US_BRGR = (fp << 16) | brgr;
-
- // Write the Timeguard Register
- pUS1->US_TTGR = 0;
- pUS1->US_RTOR = 0;
- pUS1->US_FIDI = 0;
- pUS1->US_IF = 0;
-
- // Initialize DMA buffers
- pUS1->US_TPR = (uint32_t)0;
- pUS1->US_TCR = 0;
- pUS1->US_TNPR = (uint32_t)0;
- pUS1->US_TNCR = 0;
- pUS1->US_RPR = (uint32_t)us_inbuf1;
- pUS1->US_RCR = USART_BUFFLEN;
- usart_cur_inbuf = us_inbuf1;
- usart_cur_inbuf_off = 0;
- pUS1->US_RNPR = (uint32_t)us_inbuf2;
- pUS1->US_RNCR = USART_BUFFLEN;
-
- // Initialize our fifo
- us_rxfifo_low = 0;
- us_rxfifo_high = 0;
-
- // re-enable receiver / transmitter
- pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN);
-
- // ready to read and transmit
- pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/usart.h b/pm3rdv4rrg/src/main/cpp/armsrc/usart.h
deleted file mode 100644
index 01ca0d80..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/usart.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __USART_H
-#define __USART_H
-
-#include "common.h"
-#include "usart_defs.h"
-
-#define USART_BUFFLEN 512
-#define USART_FIFOLEN (2*USART_BUFFLEN)
-
-// Higher baudrates are pointless, only increasing overflow risk
-
-extern uint32_t usart_baudrate;
-extern uint8_t usart_parity;
-
-void usart_init(uint32_t baudrate, uint8_t parity);
-int usart_writebuffer_sync(uint8_t *data, size_t len);
-uint32_t usart_read_ng(uint8_t *data, size_t len);
-uint16_t usart_rxdata_available(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/util.c b/pm3rdv4rrg/src/main/cpp/armsrc/util.c
deleted file mode 100644
index d1a4fb93..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/util.c
+++ /dev/null
@@ -1,332 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Sept 2005
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Utility functions used in many places, not specific to any piece of code.
-//-----------------------------------------------------------------------------
-#include "util.h"
-
-#include "proxmark3_arm.h"
-#include "ticks.h"
-#include "commonutil.h"
-#include "dbprint.h"
-#include "string.h"
-#include "usb_cdc.h"
-#include "usart.h"
-
-size_t nbytes(size_t nbits) {
- return (nbits >> 3) + ((nbits % 8) > 0);
-}
-
-//convert hex digit to integer
-uint8_t hex2int(char hexchar) {
- switch (hexchar) {
- case '0':
- return 0;
- break;
- case '1':
- return 1;
- break;
- case '2':
- return 2;
- break;
- case '3':
- return 3;
- break;
- case '4':
- return 4;
- break;
- case '5':
- return 5;
- break;
- case '6':
- return 6;
- break;
- case '7':
- return 7;
- break;
- case '8':
- return 8;
- break;
- case '9':
- return 9;
- break;
- case 'a':
- case 'A':
- return 10;
- break;
- case 'b':
- case 'B':
- return 11;
- break;
- case 'c':
- case 'C':
- return 12;
- break;
- case 'd':
- case 'D':
- return 13;
- break;
- case 'e':
- case 'E':
- return 14;
- break;
- case 'f':
- case 'F':
- return 15;
- break;
- default:
- return 0;
- }
-}
-
-void LEDsoff() {
- LED_A_OFF();
- LED_B_OFF();
- LED_C_OFF();
- LED_D_OFF();
-}
-
-//ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8
-void LED(int led, int ms) {
- if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
- LED_A_ON();
- if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
- LED_B_ON();
- if (led & LED_C) // Proxmark3 historical mapping: LED_RED
- LED_C_ON();
- if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
- LED_D_ON();
-
- if (!ms)
- return;
-
- SpinDelay(ms);
-
- if (led & LED_A)
- LED_A_OFF();
- if (led & LED_B)
- LED_B_OFF();
- if (led & LED_C)
- LED_C_OFF();
- if (led & LED_D)
- LED_D_OFF();
-}
-
-void SpinOff(uint32_t pause) {
- LED_A_OFF();
- LED_B_OFF();
- LED_C_OFF();
- LED_D_OFF();
- SpinDelay(pause);
-}
-
-// Blinks..
-// A = 1, B = 2, C = 4, D = 8
-void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
- SpinOff(speed);
- NTIME(times) {
-
- if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
- LED_A_INV();
- if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
- LED_B_INV();
- if (led & LED_C) // Proxmark3 historical mapping: LED_RED
- LED_C_INV();
- if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
- LED_D_INV();
-
- SpinDelay(speed);
- }
- LED_A_OFF();
- LED_B_OFF();
- LED_C_OFF();
- LED_D_OFF();
-}
-
-void SpinDown(uint32_t speed) {
- SpinOff(speed);
- LED_D_ON();
- SpinDelay(speed);
- LED_D_OFF();
- LED_C_ON();
- SpinDelay(speed);
- LED_C_OFF();
- LED_B_ON();
- SpinDelay(speed);
- LED_B_OFF();
- LED_A_ON();
- SpinDelay(speed);
- LED_A_OFF();
-}
-
-void SpinUp(uint32_t speed) {
- SpinOff(speed);
- LED_A_ON();
- SpinDelay(speed);
- LED_A_OFF();
- LED_B_ON();
- SpinDelay(speed);
- LED_B_OFF();
- LED_C_ON();
- SpinDelay(speed);
- LED_C_OFF();
- LED_D_ON();
- SpinDelay(speed);
- LED_D_OFF();
-}
-
-
-// Determine if a button is double clicked, single clicked,
-// not clicked, or held down (for ms || 1sec)
-// In general, don't use this function unless you expect a
-// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
-int BUTTON_CLICKED(int ms) {
- // Up to 500ms in between clicks to mean a double click
- // timer counts in 21.3us increments (1024/48MHz)
- // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
- if (ms > 1390) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_CLICKED called with %i > 1390"), ms);
- ms = 1390;
- }
- int ticks = ((MCK / 1000) * (ms ? ms : 1000)) >> 10;
-
- // If we're not even pressed, forget about it!
- if (!BUTTON_PRESS())
- return BUTTON_NO_CLICK;
-
- // Borrow a PWM unit for my real-time clock
- AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
- // 48 MHz / 1024 gives 46.875 kHz
- AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
- AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
- AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
-
- uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-
- int letoff = 0;
- for (;;) {
- uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-
- // We haven't let off the button yet
- if (!letoff) {
- // We just let it off!
- if (!BUTTON_PRESS()) {
- letoff = 1;
-
- // reset our timer for 500ms
- start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
- ticks = ((MCK / 1000) * (500)) >> 10;
- }
-
- // Still haven't let it off
- else
- // Have we held down a full second?
- if (now == (uint16_t)(start + ticks))
- return BUTTON_HOLD;
- }
-
- // We already let off, did we click again?
- else
- // Sweet, double click!
- if (BUTTON_PRESS())
- return BUTTON_DOUBLE_CLICK;
-
- // Have we ran out of time to double click?
- else if (now == (uint16_t)(start + ticks))
- // At least we did a single click
- return BUTTON_SINGLE_CLICK;
-
- WDT_HIT();
- }
-
- // We should never get here
- return BUTTON_ERROR;
-}
-
-// Determine if a button is held down
-int BUTTON_HELD(int ms) {
- // timer counts in 21.3us increments (1024/48MHz)
- // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
- if (ms > 1390) {
- if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_HELD called with %i > 1390"), ms);
- ms = 1390;
- }
- // If button is held for one second
- int ticks = (48000 * (ms ? ms : 1000)) >> 10;
-
- // If we're not even pressed, forget about it!
- if (!BUTTON_PRESS())
- return BUTTON_NO_CLICK;
-
- // Borrow a PWM unit for my real-time clock
- AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
- // 48 MHz / 1024 gives 46.875 kHz
- AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
- AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
- AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
-
- uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-
- for (;;) {
- uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-
- // As soon as our button let go, we didn't hold long enough
- if (!BUTTON_PRESS())
- return BUTTON_SINGLE_CLICK;
-
- // Have we waited the full second?
- else if (now == (uint16_t)(start + ticks))
- return BUTTON_HOLD;
-
- WDT_HIT();
- }
-
- // We should never get here
- return BUTTON_ERROR;
-}
-
-/* Similar to FpgaGatherVersion this formats stored version information
- * into a string representation. It takes a pointer to the struct version_information,
- * verifies the magic properties, then stores a formatted string, prefixed by
- * prefix in dst.
- */
-void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) {
- struct version_information *v = (struct version_information *)version_information;
- dst[0] = 0;
- strncat(dst, prefix, len - 1);
- if (v->magic != VERSION_INFORMATION_MAGIC) {
- strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1);
- return;
- }
- if (v->versionversion != 1) {
- strncat(dst, "Version information not understood\n", len - strlen(dst) - 1);
- return;
- }
- if (!v->present) {
- strncat(dst, "Version information not available\n", len - strlen(dst) - 1);
- return;
- }
-
- strncat(dst, v->gitversion, len - strlen(dst) - 1);
- if (v->clean == 0) {
- strncat(dst, "-unclean", len - strlen(dst) - 1);
- } else if (v->clean == 2) {
- strncat(dst, "-suspect", len - strlen(dst) - 1);
- }
-
- strncat(dst, " ", len - strlen(dst) - 1);
- strncat(dst, v->buildtime, len - strlen(dst) - 1);
- strncat(dst, "\n", len - strlen(dst) - 1);
-}
-
-bool data_available(void) {
-#ifdef WITH_FPC_USART_HOST
- return usb_poll_validate_length() || (usart_rxdata_available() > 0);
-#else
- return usb_poll_validate_length();
-#endif
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/util.h b/pm3rdv4rrg/src/main/cpp/armsrc/util.h
deleted file mode 100644
index 9748152e..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/util.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, Aug 2005
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Utility functions used in many places, not specific to any piece of code.
-//-----------------------------------------------------------------------------
-
-#ifndef __UTIL_H
-#define __UTIL_H
-
-#include "common.h"
-
-// Basic macros
-
-#ifndef SHORT_COIL
-#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
-#endif
-
-#ifndef OPEN_COIL
-#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
-#endif
-
-#ifndef BYTEx
-#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
-#endif
-
-// Proxmark3 RDV4.0 LEDs
-#define LED_A 1
-#define LED_B 2
-#define LED_C 4
-#define LED_D 8
-
-// Proxmark3 historical LEDs
-#define LED_ORANGE LED_A
-#define LED_GREEN LED_B
-#define LED_RED LED_C
-#define LED_RED2 LED_D
-
-#define BUTTON_HOLD 1
-#define BUTTON_NO_CLICK 0
-#define BUTTON_SINGLE_CLICK -1
-#define BUTTON_DOUBLE_CLICK -2
-#define BUTTON_ERROR -99
-
-#ifndef REV8
-#define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
-#endif
-
-#ifndef REV16
-#define REV16(x) (REV8(x) + (REV8 (x >> 8) << 8))
-#endif
-
-#ifndef REV32
-#define REV32(x) (REV16(x) + (REV16(x >> 16) << 16))
-#endif
-
-#ifndef REV64
-#define REV64(x) (REV32(x) + (REV32(x >> 32) << 32))
-#endif
-
-#ifndef BIT32
-#define BIT32(x,n) ((((x)[(n)>>5])>>((n)))&1)
-#endif
-
-#ifndef INV32
-#define INV32(x,i,n) ((x)[(i)>>5]^=((uint32_t)(n))<<((i)&31))
-#endif
-
-#ifndef ROTL64
-#define ROTL64(x, n) ((((uint64_t)(x))<<((n)&63))+(((uint64_t)(x))>>((0-(n))&63)))
-#endif
-
-size_t nbytes(size_t nbits);
-
-uint8_t hex2int(char hexchar);
-
-void LED(int led, int ms);
-void LEDsoff(void);
-void SpinOff(uint32_t pause);
-void SpinErr(uint8_t led, uint32_t speed, uint8_t times);
-void SpinDown(uint32_t speed);
-void SpinUp(uint32_t speed);
-
-int BUTTON_CLICKED(int ms);
-int BUTTON_HELD(int ms);
-void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
-bool data_available(void);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/vtsend.c b/pm3rdv4rrg/src/main/cpp/armsrc/vtsend.c
deleted file mode 100644
index f07793cc..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/vtsend.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/**
- * @file vtsend.c
- * @author CuBeatSystems
- * @author Shinichiro Nakamura
- * @copyright
- * ===============================================================
- * Natural Tiny Shell (NT-Shell) Version 0.3.1
- * ===============================================================
- * Copyright (c) 2010-2016 Shinichiro Nakamura
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "vtsend.h"
-#include "pm3_cmd.h"
-#include "dbprint.h"
-
-#define ESC (0x1B)
-//#define UART_WRITE(P, BUF, SIZ) (P)->uart_write(BUF, SIZ, (P)->extobj)
-#define UART_WRITE(BUF) DbprintfEx(FLAG_RAWPRINT, "%s", BUF)
-
-int vtsend_init(vtsend_t *p, VTSEND_SERIAL_WRITE uart_write, void *extobj) {
- p->uart_write = uart_write;
- p->extobj = extobj;
- return 0;
-}
-
-int vtsend_cursor_position(vtsend_t *p, const int column, const int line) {
- char buf[1 + 8];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + (line / 10);
- buf[3] = '0' + (line % 10);
- buf[4] = ';';
- buf[5] = '0' + (column / 10);
- buf[6] = '0' + (column % 10);
- buf[7] = 'H';
- buf[8] = '\0';
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_cursor_up(vtsend_t *p, const int n) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + (n / 10);
- buf[3] = '0' + (n % 10);
- buf[4] = 'A';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_cursor_down(vtsend_t *p, const int n) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + (n / 10);
- buf[3] = '0' + (n % 10);
- buf[4] = 'B';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_cursor_forward(vtsend_t *p, const int n) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + (n / 10);
- buf[3] = '0' + (n % 10);
- buf[4] = 'C';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_cursor_backward(vtsend_t *p, const int n) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + (n / 10);
- buf[3] = '0' + (n % 10);
- buf[4] = 'D';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_cursor_position_save(vtsend_t *p) {
- char buf[1 + 3];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = 's';
- buf[3] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_cursor_position_restore(vtsend_t *p) {
- char buf[1 + 3];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = 'u';
- buf[3] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_erase_display(vtsend_t *p) {
- char buf[1 + 4];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '2';
- buf[3] = 'J';
- buf[4] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_erase_line(vtsend_t *p) {
- char buf[1 + 4];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '2';
- buf[3] = 'K';
- buf[4] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_set_color_foreground(vtsend_t *p, const int color) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + ((30 + color) / 10);
- buf[3] = '0' + ((30 + color) % 10);
- buf[4] = 'm';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_set_color_background(vtsend_t *p, const int color) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + ((40 + color) / 10);
- buf[3] = '0' + ((40 + color) % 10);
- buf[4] = 'm';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_set_attribute(vtsend_t *p, const int attr) {
- char buf[1 + 5];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + ((attr) / 10);
- buf[3] = '0' + ((attr) % 10);
- buf[4] = 'm';
- buf[5] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_set_scroll_region(vtsend_t *p, const int top, const int bottom) {
- char buf[1 + 8];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '0' + (top / 10);
- buf[3] = '0' + (top % 10);
- buf[4] = ';';
- buf[5] = '0' + (bottom / 10);
- buf[6] = '0' + (bottom % 10);
- buf[7] = 'r';
- buf[8] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_set_cursor(vtsend_t *p, const int visible) {
- if (visible) {
- char buf[1 + 6];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '?';
- buf[3] = '2';
- buf[4] = '5';
- buf[5] = 'h';
- buf[6] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- } else {
- char buf[1 + 6];
- buf[0] = ESC;
- buf[1] = '[';
- buf[2] = '?';
- buf[3] = '2';
- buf[4] = '5';
- buf[5] = 'l';
- buf[6] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- }
- return 0;
-}
-
-int vtsend_reset(vtsend_t *p) {
- char buf[1 + 2];
- buf[0] = ESC;
- buf[1] = 'c';
- buf[2] = '\0';
-
- UART_WRITE(buf); // UART_WRITE(p, buf, sizeof(buf));
- return 0;
-}
-
-int vtsend_draw_box(vtsend_t *p, const int x1, const int y1, const int x2, const int y2) {
- int i;
-
- vtsend_cursor_position(p, x1, y1);
- for (i = x1; i <= x2; i++) {
- UART_WRITE("-");
- }
- vtsend_cursor_position(p, x1, y2);
- for (i = x1; i <= x2; i++) {
- UART_WRITE("-");
- }
- for (i = y1; i <= y2; i++) {
- vtsend_cursor_position(p, x1, i);
- UART_WRITE("|");
- vtsend_cursor_position(p, x2, i);
- UART_WRITE("|");
- }
- return 0;
-}
-
-int vtsend_fill_box(vtsend_t *p, const int x1, const int y1, const int x2, const int y2) {
- int i, j;
- for (i = y1; i <= y2; i++) {
- vtsend_cursor_position(p, x1, i);
- for (j = x1; j <= x2; j++) {
- UART_WRITE(" ");
- }
- }
- return 0;
-}
-
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/vtsend.h b/pm3rdv4rrg/src/main/cpp/armsrc/vtsend.h
deleted file mode 100644
index 63d3d246..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/vtsend.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * @file vtsend.h
- * @author CuBeatSystems
- * @author Shinichiro Nakamura
- * @copyright
- * ===============================================================
- * Natural Tiny Shell (NT-Shell) Version 0.3.1
- * ===============================================================
- * Copyright (c) 2010-2016 Shinichiro Nakamura
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef VTSEND_H
-#define VTSEND_H
-
-#include "common.h"
-
-#define VTSEND_COLOR_BLACK (0)
-#define VTSEND_COLOR_RED (1)
-#define VTSEND_COLOR_GREEN (2)
-#define VTSEND_COLOR_YELLOW (3)
-#define VTSEND_COLOR_BLUE (4)
-#define VTSEND_COLOR_MAGENTA (5)
-#define VTSEND_COLOR_CYAN (6)
-#define VTSEND_COLOR_WHITE (7)
-
-#define VTSEND_ATTR_OFF (0)
-#define VTSEND_ATTR_BOLD_ON (1)
-#define VTSEND_ATTR_UNDERSCORE (4)
-#define VTSEND_ATTR_BLINK_ON (5)
-#define VTSEND_ATTR_REVERSE (7)
-#define VTSEND_ATTR_CONCEALED_ON (8)
-
-typedef int (*VTSEND_SERIAL_WRITE)(const char *buf, const int siz, void *extobj);
-
-typedef struct {
- VTSEND_SERIAL_WRITE uart_write;
- void *extobj;
-} vtsend_t;
-
-int vtsend_init(vtsend_t *p, VTSEND_SERIAL_WRITE uart_write, void *extobj);
-int vtsend_cursor_position(vtsend_t *p, const int column, const int line);
-int vtsend_cursor_up(vtsend_t *p, const int n);
-int vtsend_cursor_down(vtsend_t *p, const int n);
-int vtsend_cursor_forward(vtsend_t *p, const int n);
-int vtsend_cursor_backward(vtsend_t *p, const int n);
-int vtsend_cursor_position_save(vtsend_t *p);
-int vtsend_cursor_position_restore(vtsend_t *p);
-int vtsend_erase_display(vtsend_t *p);
-int vtsend_erase_line(vtsend_t *p);
-int vtsend_set_color_foreground(vtsend_t *p, const int color);
-int vtsend_set_color_background(vtsend_t *p, const int color);
-int vtsend_set_attribute(vtsend_t *p, const int attr);
-int vtsend_set_scroll_region(vtsend_t *p, const int top, const int bottom);
-int vtsend_set_cursor(vtsend_t *p, const int visible);
-int vtsend_reset(vtsend_t *p);
-
-int vtsend_draw_box(
- vtsend_t *p,
- const int x1, const int y1, const int x2, const int y2);
-int vtsend_fill_box(
- vtsend_t *p,
- const int x1, const int y1, const int x2, const int y2);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/wiegand.c b/pm3rdv4rrg/src/main/cpp/armsrc/wiegand.c
deleted file mode 100644
index cd4fb3eb..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/wiegand.c
+++ /dev/null
@@ -1,239 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Wiegand functions
-//-----------------------------------------------------------------------------
-
-#include "wiegand.h"
-
-/*
-* @brief getParity
-* @param bits pointer to the source bitstream of binary values 0|1
-* @param len how long shall parity be calculated
-* @param type use the defined values EVEN|ODD
-* @return parity bit required to match type
-*/
-uint8_t getParity(uint8_t *bits, uint8_t len, uint8_t type) {
- uint8_t x = 0;
- for (; len > 0; --len)
- x += bits[len - 1];
-
- return (x & 1) ^ type;
-}
-
-// by marshmellow
-/* pass bits to be tested in bits, length bits passed in bitLen, and parity type EVEN|ODD in type
-* @brief checkParity
-* @param bits pointer to the source bitstream of binary values 0|1
-* @param len number of bits to be checked
-* @param type use the defined values EVEN|ODD
-* @return 1 if passed
-*/
-uint8_t checkParity(uint32_t bits, uint8_t len, uint8_t type);
-
-// by marshmellow
-// takes a array of binary values, start position, length of bits per parity (includes parity bit),
-// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
-size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) {
- uint32_t parityWd = 0;
- size_t j = 0, bitcount = 0;
- for (int word = 0; word < (bLen); word += pLen) {
- for (int bit = 0; bit < pLen; ++bit) {
- parityWd = (parityWd << 1) | bits[startIdx + word + bit];
- bits[j++] = (bits[startIdx + word + bit]);
- }
- j--; // overwrite parity with next data
- // if parity fails then return 0
- switch (pType) {
- case 3:
- if (bits[j] == 1) return 0;
- break; //should be 0 spacer bit
- case 2:
- if (bits[j] == 0) return 0;
- break; //should be 1 spacer bit
- default: //test parity
- if (parityTest(parityWd, pLen, pType) == 0) return 0;
- break;
- }
- bitcount += (pLen - 1);
- parityWd = 0;
- }
- // if we got here then all the parities passed
- //return ID start index and size
- return bitcount;
-}
-
-
-// by marshmellow
-// takes a array of binary values, length of bits per parity (includes parity bit),
-// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
-// Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
-/*
-* @brief addParity
-* @param src pointer to the source bitstream of binary values
-* @param dest pointer to the destination where parities together with bits are added.
-* @param sourceLen number of
-* @param pLen length bits to be checked
-* @param pType EVEN|ODD|2 (always 1's)|3 (always 0's)
-* @return
-*/
-size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) {
- uint32_t parityWd = 0;
- size_t j = 0, bitCnt = 0;
- for (int word = 0; word < sourceLen; word += pLen - 1) {
- for (int bit = 0; bit < pLen - 1; ++bit) {
- parityWd = (parityWd << 1) | src[word + bit];
- dest[j++] = (src[word + bit]);
- }
-
- // if parity fails then return 0
- switch (pType) {
- case 3:
- dest[j++] = 0;
- break; // marker bit which should be a 0
- case 2:
- dest[j++] = 1;
- break; // marker bit which should be a 1
- default:
- dest[j++] = parityTest(parityWd, pLen - 1, pType) ^ 1;
- break;
- }
- bitCnt += pLen;
- parityWd = 0;
- }
- // if we got here then all the parities passed
- //return ID start index and size
- return bitCnt;
-}
-
-// by marshmellow
-/*
-* add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
-* @brief wiegand_add_parity
-* @param source pointer to source of binary data
-* @param dest pointer to the destination where wiegandparity has been appended
-* @param len number of bits which wiegand parity shall be calculated over. This number is without parities, so a wiegand 26 has 24 bits of data
-*/
-void wiegand_add_parity(uint8_t *source, uint8_t *dest, uint8_t len) {
-
- // Copy to destination, shifted one step to make room for EVEN parity
- memcpy(dest + 1, source, length);
-
- // half length, Even and Odd is calculated to the middle.
- uint8_t len_h2 = length >> 1;
-
- // add EVEN parity at the beginning
- *(dest) = GetParity(source, EVEN, len_h2);
-
- dest += length + 1;
-
- // add ODD parity at the very end
- *(dest) = GetParity(source + len_h2, ODD, len_h2);
-}
-
-//uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
-#define MAX_BITS_TXX55 6*4*8
-#define MAX_BYTES_TXX55 6*4
-/*
-* @brief num_to_wiegand_bytes
-* @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats
-* @param fc Facility code
-* @param cn Card number
-* @param dest pointer to the destination where wiegand bytes will be stored
-* @param formatlen
-*/
-void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen) {
-
- uint8_t data[MAX_BITS_TXX55] = {0};
- memset(data, 0, sizeof(data));
-
- num_to_wiegand_bits(oem, fc, cn, data, formatlen);
-
- // loop
- // (formatlen / 32 ) + 1
- // (formatlen >> 5) + 1
- for (int i = 0; i < formatlen ; ++i) {
- uint32_t value = bytebits_to_byte(data + (i * 32), 32);
- num_to_bytes(value, 32, dest + (i * 4));
- }
-
-}
-/*
-* @brief num_to_wiegand_bits
-* @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats
-* @param fc Facility code
-* @param cn Card number
-* @param dest pointer to the destination where wiegand bits will be stored
-* @param formatlen
-*/
-void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen) {
-
- uint8_t bits[MAX_BITS_TXX55] = {0};
- memset(bits, 0, sizeof(bits));
- uint8_t *temp = bits;
- uint64_t value = 0;
-
- switch (formatlen) {
- case 26 : // 26bit HID H10301
- fc &= 0xFF; // 8bits
- cn &= 0xFFFF; // 16bits
- value = fc << 16 | cn;
- num_to_bytebits(value, 24, temp);
- wiegand_add_parity(temp, dest, 24);
- break;
- case 261: // 26bit Indala
- fc &= 0xFFF; // 12bits
- cn &= 0xFFF; // 12bits
- value = fc << 12 | cn;
- num_to_bytebits(value, 24, temp);
- wiegand_add_parity(temp, dest, 24);
- break;
- case 34 : // 34bits HID
- fc &= 0xFFFF; // 16bits
- cn &= 0xFFFF; // 16bits
- value = fc << 16 | cn;
- num_to_bytebits(value, 32, temp);
- wiegand_add_parity(temp, dest, 32);
- break;
- case 35 : // 35bits HID
- fc &= 0xFFF; // 12bits
- cn &= 0xFFFFFF; // 20bits
- value = fc << 20 | cn;
- num_to_bytebits(value, 32, temp);
- wiegand_add_parity(temp, dest, 32);
- break;
- case 37 : // H10304
- fc &= 0xFFFF; // 16bits
- cn &= 0x7FFFF; // 19bits
- value = fc << 19 | cn;
- num_to_bytebits(value, 35, temp);
- wiegand_add_parity(temp, dest, 35);
- break;
- case 39 : // 39bit KERI System Pyramid
- fc &= 0x1FFFF; // 17bits
- cn &= 0xFFFFFFFF; // 20bits
- value = fc << 20 | cn;
- num_to_bytebits(value, 37, temp);
- wiegand_add_parity(temp, dest, 37);
- break;
- case 44 : // 44bit KERI system Pyramid
- oem &= 0xFF; // 8bits
- fc &= 0xFFF; // 12bits
- cn &= 0xFFFFFFFF; // 21bits
- value = oem << 20 | fc << 12 | cn;
- num_to_bytebits(value, 42, temp);
- wiegand_add_parity(temp, dest, 42);
- break;
- case 50 : // AWID 50 RBH
- fc &= 0xFFFF; // 16bits
- cn &= 0xFFFFFFFF; // 32bits
- value = fc << 32 | cn;
- num_to_bytebits(value, 48, temp);
- wiegand_add_parity(temp, dest, 48); // verify!
- break;
- default:
- break;
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/armsrc/wiegand.h b/pm3rdv4rrg/src/main/cpp/armsrc/wiegand.h
deleted file mode 100644
index ce219fad..00000000
--- a/pm3rdv4rrg/src/main/cpp/armsrc/wiegand.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Generic Wiegand Calculation code
-//-----------------------------------------------------------------------------
-
-#ifndef __WIEGAND_H
-#define __WIEGAND_H
-
-#include "common.h"
-
-uint8_t getParity(uint8_t *bits, uint8_t len, uint8_t type);
-uint8_t checkParity(uint32_t bits, uint8_t len, uint8_t type);
-
-void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen);
-void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen);
-
-#endif /* __WIEGAND_H */
diff --git a/pm3rdv4rrg/src/main/cpp/bootrom/Makefile b/pm3rdv4rrg/src/main/cpp/bootrom/Makefile
deleted file mode 100644
index 5c782389..00000000
--- a/pm3rdv4rrg/src/main/cpp/bootrom/Makefile
+++ /dev/null
@@ -1,76 +0,0 @@
-#-----------------------------------------------------------------------------
-# This code is licensed to you under the terms of the GNU GPL, version 2 or,
-# at your option, any later version. See the LICENSE.txt file for the text of
-# the license.
-#-----------------------------------------------------------------------------
-# Makefile for bootrom, see ../common_arm/Makefile.common for common settings
-#-----------------------------------------------------------------------------
-
-# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code
-ARMSRC =
-THUMBSRC = usb_cdc.c \
- clocks.c \
- bootrom.c
-
-ASMSRC = ram-reset.s flash-reset.s
-VERSIONSRC = version.c
-
-## There is a strange bug with the linker: Sometimes it will not emit the glue to call
-## BootROM from ARM mode. The symbol is emitted, but the section will be filled with
-## zeroes. As a temporary workaround, do not use thumb for the phase 2 bootloader
-## -- Henryk Plötz 2009-09-01
-# ARMSRC := $(ARMSRC) $(THUMBSRC)
-# THUMBSRC :=
-
-# stdint.h provided locally until GCC 4.5 becomes C99 compliant
-APP_CFLAGS = -I. -fno-strict-aliasing -ffunction-sections -fdata-sections
-
-# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
-APP_CFLAGS += -fno-stack-protector -fno-pie
-
-
-# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
-include ../common_arm/Makefile.common
-
-INSTALLFW = $(OBJDIR)/bootrom.elf
-
-OBJS = $(OBJDIR)/bootrom.s19
-
-# version.c should be remade on every compilation
-version.c: default_version.c
- $(info [=] GEN $@)
- $(Q)sh ../tools/mkversion.sh > $@ || perl ../tools/mkversion.pl > $@ || $(CP) $^ $@
-
-all: $(OBJS)
-
-tarbin: $(OBJS)
- $(info [=] GEN $@)
- $(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=bootrom/%) $(OBJS:%.s19=bootrom/%.elf)
-
-$(OBJDIR)/bootrom.elf: $(VERSIONOBJ) $(ASMOBJ) $(ARMOBJ) $(THUMBOBJ)
- $(info [=] LD $@)
- $(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript-flash,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
-
-clean:
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.o
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.elf
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.s19
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.map
- $(Q)$(RM) $(OBJDIR)$(PATHSEP)*.d
- $(Q)$(RM) version.c
-
-install: all
- $(info [@] Installing bootrom to $(DESTDIR)$(PREFIX)...)
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
- $(Q)$(CP) $(INSTALLFW) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
-
-uninstall:
- $(info [@] Uninstalling bootrom from $(DESTDIR)$(PREFIX)...)
- $(Q)$(RM) $(foreach fw,$(INSTALLFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
-
-.PHONY: all clean help install
-help:
- @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
- @echo Possible targets:
- @echo + all - Make $(OBJDIR)/bootrom.s19, the main bootrom
- @echo + clean - Clean $(OBJDIR)
diff --git a/pm3rdv4rrg/src/main/cpp/bootrom/bootrom.c b/pm3rdv4rrg/src/main/cpp/bootrom/bootrom.c
deleted file mode 100644
index aa633f44..00000000
--- a/pm3rdv4rrg/src/main/cpp/bootrom/bootrom.c
+++ /dev/null
@@ -1,335 +0,0 @@
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Main code for the bootloader
-//-----------------------------------------------------------------------------
-
-#include "clocks.h"
-#include "usb_cdc.h"
-
-#include "proxmark3_arm.h"
-
-struct common_area common_area __attribute__((section(".commonarea")));
-unsigned int start_addr, end_addr, bootrom_unlocked;
-extern char _bootrom_start, _bootrom_end, _flash_end;
-extern uint32_t _flash_start[AT91C_IFLASH_NB_OF_PAGES * AT91C_IFLASH_PAGE_SIZE / sizeof(uint32_t)];
-extern uint32_t _osimage_entry;
-
-static int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) {
- PacketResponseOLD txcmd;
-
- for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
- ((uint8_t *)&txcmd)[i] = 0x00;
-
- // Compose the outgoing command frame
- txcmd.cmd = cmd;
- txcmd.arg[0] = arg0;
- txcmd.arg[1] = arg1;
- txcmd.arg[2] = arg2;
-
- // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
- if (data && len) {
- len = MIN(len, PM3_CMD_DATA_SIZE);
- for (size_t i = 0; i < len; i++) {
- txcmd.d.asBytes[i] = ((uint8_t *)data)[i];
- }
- }
-
- int result = PM3_EUNDEF;
- // Send frame and make sure all bytes are transmitted
-
- result = usb_write((uint8_t *)&txcmd, sizeof(PacketResponseOLD));
-
- return result;
-}
-
-void DbpString(char *str) {
- uint8_t len = 0;
- while (str[len] != 0x00)
- len++;
-
- reply_old(CMD_DEBUG_PRINT_STRING, len, 0, 0, (uint8_t *)str, len);
-}
-
-static void ConfigClocks(void) {
- // we are using a 16 MHz crystal as the basis for everything
- // slow clock runs at 32kHz typical regardless of crystal
-
- // enable system clock and USB clock
- AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK | AT91C_PMC_UDP;
-
- // enable the clock to the following peripherals
- AT91C_BASE_PMC->PMC_PCER =
- (1 << AT91C_ID_PIOA) |
- (1 << AT91C_ID_ADC) |
- (1 << AT91C_ID_SPI) |
- (1 << AT91C_ID_SSC) |
- (1 << AT91C_ID_PWMC) |
- (1 << AT91C_ID_UDP);
-
- mck_from_slck_to_pll();
-}
-
-static void Fatal(void) {
- for (;;) {};
-}
-
-void UsbPacketReceived(uint8_t *packet, int len) {
- int i, dont_ack = 0;
- PacketCommandOLD *c = (PacketCommandOLD *)packet;
-
- //if ( len != sizeof(PacketCommandOLD`)) Fatal();
-
- uint32_t arg0 = (uint32_t)c->arg[0];
-
- switch (c->cmd) {
- case CMD_DEVICE_INFO: {
- dont_ack = 1;
- arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT |
- DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
- DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH |
- DEVICE_INFO_FLAG_UNDERSTANDS_CHIP_INFO |
- DEVICE_INFO_FLAG_UNDERSTANDS_VERSION;
- if (common_area.flags.osimage_present)
- arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
-
- reply_old(CMD_DEVICE_INFO, arg0, 1, 2, 0, 0);
- }
- break;
-
- case CMD_CHIP_INFO: {
- dont_ack = 1;
- arg0 = *(AT91C_DBGU_CIDR);
- reply_old(CMD_CHIP_INFO, arg0, 0, 0, 0, 0);
- }
- break;
-
- case CMD_BL_VERSION: {
- dont_ack = 1;
- arg0 = BL_VERSION_1_0_0;
- reply_old(CMD_BL_VERSION, arg0, 0, 0, 0, 0);
- }
- break;
-
- case CMD_FINISH_WRITE: {
- for (int j = 0; j < 2; j++) {
- uint32_t flash_address = arg0 + (0x100 * j);
- AT91PS_EFC efc_bank = AT91C_BASE_EFC0;
- int offset = 0;
- uint32_t page_n = (flash_address - ((uint32_t)_flash_start)) / AT91C_IFLASH_PAGE_SIZE;
- if (page_n >= AT91C_IFLASH_NB_OF_PAGES / 2) {
- page_n -= AT91C_IFLASH_NB_OF_PAGES / 2;
- efc_bank = AT91C_BASE_EFC1;
- // We need to offset the writes or it will not fill the correct bank write buffer.
- offset = (AT91C_IFLASH_NB_OF_PAGES / 2) * AT91C_IFLASH_PAGE_SIZE / sizeof(uint32_t);
- }
- for (i = 0 + (64 * j); i < 64 + (64 * j); i++) {
- _flash_start[offset + i] = c->d.asDwords[i];
- }
-
- /* Check that the address that we are supposed to write to is within our allowed region */
- if (((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr)) {
- /* Disallow write */
- dont_ack = 1;
- reply_old(CMD_NACK, 0, 0, 0, 0, 0);
- } else {
-
- efc_bank->EFC_FCR = MC_FLASH_COMMAND_KEY |
- MC_FLASH_COMMAND_PAGEN(page_n) |
- AT91C_MC_FCMD_START_PROG;
- }
-
- // Wait until flashing of page finishes
- uint32_t sr;
- while (!((sr = efc_bank->EFC_FSR) & AT91C_MC_FRDY));
- if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
- dont_ack = 1;
- reply_old(CMD_NACK, sr, 0, 0, 0, 0);
- }
- }
- }
- break;
-
- case CMD_HARDWARE_RESET: {
- usb_disable();
- AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
- }
- break;
-
- case CMD_START_FLASH: {
- if (c->arg[2] == START_FLASH_MAGIC)
- bootrom_unlocked = 1;
- else
- bootrom_unlocked = 0;
-
- int prot_start = (int)&_bootrom_start;
- int prot_end = (int)&_bootrom_end;
- int allow_start = (int)&_flash_start;
- int allow_end = (int)&_flash_end;
- int cmd_start = c->arg[0];
- int cmd_end = c->arg[1];
-
- /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected
- * bootrom area. In any case they must be within the flash area.
- */
- if ((bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) &&
- (cmd_start >= allow_start) &&
- (cmd_end <= allow_end)) {
- start_addr = cmd_start;
- end_addr = cmd_end;
- } else {
- start_addr = end_addr = 0;
- dont_ack = 1;
- reply_old(CMD_NACK, 0, 0, 0, 0, 0);
- }
- }
- break;
-
- default: {
- Fatal();
- }
- break;
- }
-
- if (!dont_ack)
- reply_old(CMD_ACK, arg0, 0, 0, 0, 0);
-}
-
-static void flash_mode(void) {
- start_addr = 0;
- end_addr = 0;
- bootrom_unlocked = 0;
- uint8_t rx[sizeof(PacketCommandOLD)];
- common_area.command = COMMON_AREA_COMMAND_NONE;
- if (!common_area.flags.button_pressed && BUTTON_PRESS())
- common_area.flags.button_pressed = 1;
-
- usb_enable();
-
- // wait for reset to be complete?
- for (volatile size_t i = 0; i < 0x100000; i++) {};
-
- for (;;) {
- WDT_HIT();
-
- // Check if there is a usb packet available
- if (usb_poll_validate_length()) {
- if (usb_read(rx, sizeof(rx))) {
- UsbPacketReceived(rx, sizeof(rx));
- }
- }
-
- if (common_area.flags.button_pressed && !BUTTON_PRESS()) {
- common_area.flags.button_pressed = 0;
- }
- if (!common_area.flags.button_pressed && BUTTON_PRESS()) {
- /* Perform a reset to leave flash mode */
- common_area.flags.button_pressed = 1;
- usb_disable();
- LED_B_ON();
- AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
- for (;;) {};
- }
- }
-}
-
-void BootROM(void) {
- //------------
- // First set up all the I/O pins; GPIOs configured directly, other ones
- // just need to be assigned to the appropriate peripheral.
-
- // Kill all the pullups, especially the one on USB D+; leave them for
- // the unused pins, though.
- AT91C_BASE_PIOA->PIO_PPUDR =
- GPIO_USB_PU |
- GPIO_LED_A |
- GPIO_LED_B |
- GPIO_LED_C |
- GPIO_LED_D |
- GPIO_FPGA_DIN |
- GPIO_FPGA_DOUT |
- GPIO_FPGA_CCLK |
- GPIO_FPGA_NINIT |
- GPIO_FPGA_NPROGRAM |
- GPIO_FPGA_DONE |
- GPIO_MUXSEL_HIPKD |
- GPIO_MUXSEL_HIRAW |
- GPIO_MUXSEL_LOPKD |
- GPIO_MUXSEL_LORAW |
- GPIO_RELAY |
- GPIO_NVDD_ON;
- // (and add GPIO_FPGA_ON)
- // These pins are outputs
- AT91C_BASE_PIOA->PIO_OER =
- GPIO_LED_A |
- GPIO_LED_B |
- GPIO_LED_C |
- GPIO_LED_D |
- GPIO_RELAY |
- GPIO_NVDD_ON;
- // PIO controls the following pins
- AT91C_BASE_PIOA->PIO_PER =
- GPIO_USB_PU |
- GPIO_LED_A |
- GPIO_LED_B |
- GPIO_LED_C |
- GPIO_LED_D;
-
- // USB_D_PLUS_PULLUP_OFF();
- usb_disable();
- LED_D_OFF();
- LED_C_ON();
- LED_B_OFF();
- LED_A_OFF();
-
- // Set the first 256kb memory flashspeed
- AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
-
- // 9 = 256, 10+ is 512kb
- uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8;
- if (id > 9)
- AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
-
- // Initialize all system clocks
- ConfigClocks();
-
- LED_A_ON();
-
- int common_area_present = 0;
- switch (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_RSTTYP) {
- case AT91C_RSTC_RSTTYP_WATCHDOG:
- case AT91C_RSTC_RSTTYP_SOFTWARE:
- case AT91C_RSTC_RSTTYP_USER:
- /* In these cases the common_area in RAM should be ok, retain it if it's there */
- if (common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1)
- common_area_present = 1;
- break;
- default: /* Otherwise, initialize it from scratch */
- break;
- }
-
- if (!common_area_present) {
- /* Common area not ok, initialize it */
- int i;
- /* Makeshift memset, no need to drag util.c into this */
- for (i = 0; i < sizeof(common_area); i++)
- ((char *)&common_area)[i] = 0;
-
- common_area.magic = COMMON_AREA_MAGIC;
- common_area.version = 1;
- }
- common_area.flags.bootrom_present = 1;
-
- if ((common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) ||
- (!common_area.flags.button_pressed && BUTTON_PRESS()) ||
- (_osimage_entry == 0xffffffffU)) {
- flash_mode();
- } else {
- // clear button status, even if button still pressed
- common_area.flags.button_pressed = 0;
- // jump to Flash address of the osimage entry point (LSBit set for thumb mode)
- __asm("bx %0\n" : : "r"(((int)&_osimage_entry) | 0x1));
- }
-}
diff --git a/pm3rdv4rrg/src/main/cpp/bootrom/flash-reset.s b/pm3rdv4rrg/src/main/cpp/bootrom/flash-reset.s
deleted file mode 100644
index efd0cccc..00000000
--- a/pm3rdv4rrg/src/main/cpp/bootrom/flash-reset.s
+++ /dev/null
@@ -1,51 +0,0 @@
-@-----------------------------------------------------------------------------
-@ This code is licensed to you under the terms of the GNU GPL, version 2 or,
-@ at your option, any later version. See the LICENSE.txt file for the text of
-@ the license.
-@-----------------------------------------------------------------------------
-@ Reset vector for running from FLASH
-@-----------------------------------------------------------------------------
-
-.section .startup,"ax"
-
-.arm
-
-.global flashstart
-flashstart:
- b reset
- b undefined_instruction
- b software_interrupt
- b prefetch_abort
- b data_abort
- b . @reserved
- ldr pc, [pc,#-0xF20] @ IRQ - read the AIC
- b fiq
-
-reset:
- ldr sp, =_stack_end @ initialize stack pointer to top of RAM
-
- @ copy bootloader to RAM (in case the user re-flashes the bootloader)
- ldr r0, =__bootphase2_src_start__
- ldr r1, =__bootphase2_start__
- ldr r2, =__bootphase2_end__
-1:
- ldr r3, [r0], #4
- str r3, [r1], #4
- cmp r1, r2
- blo 1b
-
- ldr r3, =ram_start @ start address of RAM bootloader
- bx r3 @ jump to it
-
- .ltorg
-
-undefined_instruction:
- b .
-software_interrupt:
- b .
-prefetch_abort:
- b .
-data_abort:
- b .
-fiq:
- b .
diff --git a/pm3rdv4rrg/src/main/cpp/bootrom/ldscript-flash b/pm3rdv4rrg/src/main/cpp/bootrom/ldscript-flash
deleted file mode 100644
index c9174ffc..00000000
--- a/pm3rdv4rrg/src/main/cpp/bootrom/ldscript-flash
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
------------------------------------------------------------------------------
- This code is licensed to you under the terms of the GNU GPL, version 2 or,
- at your option, any later version. See the LICENSE.txt file for the text of
- the license.
------------------------------------------------------------------------------
- Bootrom linker script
------------------------------------------------------------------------------
-*/
-
-INCLUDE ../common_arm/ldscript.common
-
-PHDRS
-{
- phase1 PT_LOAD;
- phase2 PT_LOAD;
- bss PT_LOAD;
-}
-
-ENTRY(flashstart)
-SECTIONS
-{
- .bootphase1 : {
- *(.startup)
-
- . = ALIGN(4);
- _version_information_start = .;
- KEEP(*(.version_information));
-
- . = LENGTH(bootphase1) - 0x4;
- LONG(_version_information_start);
- } >bootphase1 :phase1
-
- .bootphase2 : {
- *(.startphase2)
- *(.text)
- *(.text.*)
- *(.eh_frame)
- *(.glue_7)
- *(.glue_7t)
- *(.rodata)
- *(.rodata.*)
- *(.data)
- *(.data.*)
- . = ALIGN(4);
- } >ram AT>bootphase2 :phase2
-
- __bootphase2_src_start__ = LOADADDR(.bootphase2);
- __bootphase2_start__ = ADDR(.bootphase2);
- __bootphase2_end__ = __bootphase2_start__ + SIZEOF(.bootphase2);
-
- .bss : {
- __bss_start__ = .;
- *(.bss)
- *(.bss.*)
- . = ALIGN(4);
- __bss_end__ = .;
- } >ram AT>ram :bss
-
- .commonarea (NOLOAD) : {
- *(.commonarea)
- } >commonarea
-}
diff --git a/pm3rdv4rrg/src/main/cpp/bootrom/obj/.dummy b/pm3rdv4rrg/src/main/cpp/bootrom/obj/.dummy
deleted file mode 100644
index e69de29b..00000000
diff --git a/pm3rdv4rrg/src/main/cpp/bootrom/ram-reset.s b/pm3rdv4rrg/src/main/cpp/bootrom/ram-reset.s
deleted file mode 100644
index ab57ee29..00000000
--- a/pm3rdv4rrg/src/main/cpp/bootrom/ram-reset.s
+++ /dev/null
@@ -1,20 +0,0 @@
-@-----------------------------------------------------------------------------
-@ This code is licensed to you under the terms of the GNU GPL, version 2 or,
-@ at your option, any later version. See the LICENSE.txt file for the text of
-@ the license.
-@-----------------------------------------------------------------------------
-@ RAM reset vector for relaunching the bootloader
-@-----------------------------------------------------------------------------
-
-.extern BootROM
-
-.section .startphase2,"ax"
-
-.arm
-
-.global ram_start
-ram_start:
- ldr sp, =_stack_end
- bl BootROM
-
- .ltorg
diff --git a/pm3rdv4rrg/src/main/cpp/client/Makefile b/pm3rdv4rrg/src/main/cpp/client/Makefile
deleted file mode 100644
index 6e2ebd00..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/Makefile
+++ /dev/null
@@ -1,463 +0,0 @@
-#-----------------------------------------------------------------------------
-# This code is licensed to you under the terms of the GNU GPL, version 2 or,
-# at your option, any later version. See the LICENSE.txt file for the text of
-# the license.
-#-----------------------------------------------------------------------------
-
-# reveng will compile without macros, but these may be useful:
-# Add -DBMPMACRO to use bitmap size constant macros (edit config.h)
-# Add -DNOFORCE to disable the -F switch
-# Add -DPRESETS to compile with preset models (edit config.h)
-
-# Must be called before any Makefile include
-ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
-
-include ../Makefile.defs
-
-INSTALLBIN = proxmark3
-INSTALLSHARE = cmdscripts lualibs luascripts resources dictionaries
-
-VPATH = ../common uart
-vpath %.dic dictionaries
-OBJDIR = obj
-
-LDLIBS ?= -L/usr/local/lib
-LDLIBS += -lreadline -lpthread -lm
-
-# RPi Zero gcc requires -latomic
-# but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
-# doesn't recognize option --as-needed
-ifneq ($(platform),Darwin)
- LDLIBS += -Wl,--as-needed -latomic -Wl,--no-as-needed
-endif
-
-# local libraries
-LUALIBPATH = ./liblua
-LUALIB = $(LUALIBPATH)/liblua.a
-JANSSONLIBPATH = ./jansson
-JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a
-CBORLIBPATH = ./tinycbor
-CBORLIB = $(CBORLIBPATH)/tinycbor.a
-REVENGPATH = ./reveng
-REVENGLIB = $(REVENGPATH)/libreveng.a
-AMIIBOLIBPATH = ./amiitool
-AMIIBOLIB = $(AMIIBOLIBPATH)/libamiibo.a
-
-# common libraries
-MBEDTLSLIBPATH = ../common/mbedtls
-MBEDTLSLIB = $(OBJDIR)/libmbedtls.a
-ZLIBPATH = ../common/zlib
-ZLIB = $(OBJDIR)/libz.a
-
-LIBS = -I$(LUALIBPATH) -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -I$(ZLIBPATH) -I$(REVENGPATH) -I$(AMIIBOLIBPATH)
-INCLUDES_CLIENT = -I. -I../include -I../common -Iuart $(LIBS)
-CFLAGS ?= -Wall -Werror -g -O3
-# We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env:
-PM3CFLAGS = $(CFLAGS) -std=c99 -D_ISOC99_SOURCE $(INCLUDES_CLIENT)
-PREFIX ?= /usr/local
-ifneq (,$(findstring MINGW,$(platform)))
- PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850
-endif
-CXXFLAGS ?= -Wall -Werror -O3
-PM3CXXFLAGS = $(CXXFLAGS) -I../include
-
-LUAPLATFORM = generic
-ifneq (,$(findstring MINGW,$(platform)))
- LUAPLATFORM = mingw
-else
- ifeq ($(platform),Darwin)
- LUAPLATFORM = macosx
- OBJCSRCS = util_darwin.m
- LDFLAGS += -framework Foundation -framework AppKit
- LDLIBS := -L/usr/local/opt/readline/lib $(LDLIBS)
- LIBS := -I/usr/local/opt/readline/include $(LIBS)
-else
- LUALIB += -ldl
- LUAPLATFORM = linux
-endif
-endif
-
-ifneq ($(SKIPQT),1)
- # Check for correctly configured Qt5
- QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null)
- QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null)
- MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc
- UIC = $(shell pkg-config --variable=host_bins Qt5Core)/uic
- ifeq ($(QTINCLUDES), )
- # if Qt5 not found check for correctly configured Qt4
- QTINCLUDES = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null)
- QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
- MOC = $(shell pkg-config --variable=moc_location QtCore)
- UIC = $(shell pkg-config --variable=uic_location QtCore)
- else
- PM3CXXFLAGS += -std=c++11 -fPIC
- endif
- ifeq ($(QTINCLUDES), )
- # if both pkg-config commands failed, search in common places
- ifneq ($(QTDIR), )
- QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
- QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
- ifneq ($(wildcard $(QTDIR)/include/QtWidgets),)
- QTINCLUDES += -I$(QTDIR)/include/QtWidgets
- QTLDLIBS = -L$(QTDIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core
- PM3CXXFLAGS += -std=c++11 -fPIC
- endif
- MOC = $(QTDIR)/bin/moc
- UIC = $(QTDIR)/bin/uic
- endif
- endif
-endif
-
-ifneq ($(QTLDLIBS),)
- QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp
- QTGUIOBJS = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
- PM3CFLAGS += -DHAVE_GUI
-else
- QTGUISRCS = guidummy.cpp
- QTGUIOBJS = $(OBJDIR)/guidummy.o
-endif
-
-# Flags to generate temporary dependency files
-DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
-# make temporary to final dependency files after successful compilation
-POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
-
-CORESRCS = uart_posix.c \
- uart_win32.c \
- ui.c \
- commonutil.c \
- util.c \
- util_posix.c \
- scandir.c \
- crc16.c \
- comms.c
-
-CMDSRCS = crapto1/crapto1.c \
- crapto1/crypto1.c \
- mifare/mifaredefault.c \
- mifare/mfkey.c \
- tea.c \
- fido/additional_ca.c \
- fido/cose.c \
- fido/cbortools.c \
- fido/fidocore.c \
- crypto/asn1dump.c \
- crypto/libpcrypto.c\
- crypto/asn1utils.c\
- cliparser/argtable3.c\
- cliparser/cliparser.c\
- loclass/cipher.c \
- loclass/cipherutils.c \
- loclass/ikeys.c \
- loclass/elite_crack.c \
- fileutils.c \
- whereami.c \
- mifare/mifarehost.c \
- parity.c \
- crc.c \
- crc64.c \
- legic_prng.c \
- iso15693tools.c \
- prng.c \
- generator.c \
- graph.c \
- cmddata.c \
- lfdemod.c \
- emv/crypto_polarssl.c\
- emv/crypto.c\
- emv/emv_pk.c\
- emv/emv_pki.c\
- emv/emv_pki_priv.c\
- emv/test/cryptotest.c\
- emv/apduinfo.c \
- emv/dump.c \
- emv/tlv.c \
- emv/emv_tags.c \
- emv/dol.c \
- emv/emvjson.c\
- emv/emvcore.c \
- emv/test/crypto_test.c\
- emv/test/sda_test.c\
- emv/test/dda_test.c\
- emv/test/cda_test.c\
- emv/cmdemv.c \
- emv/emv_roca.c \
- mifare/mifare4.c \
- mifare/mad.c \
- mifare/ndef.c \
- cmdanalyse.c \
- cmdhf.c \
- cmdhflist.c \
- aidsearch.c \
- cmdhf14a.c \
- cmdhf14b.c \
- cmdhf15.c \
- cmdhfepa.c \
- cmdhflegic.c \
- cmdhficlass.c \
- cmdhfmf.c \
- cmdhfmfu.c \
- cmdhfmfp.c \
- cmdhfmfhard.c \
- hardnested/hardnested_bruteforce.c \
- cmdhfmfdes.c \
- cmdhftopaz.c \
- cmdhffido.c \
- cmdhffelica.c \
- cmdhfthinfilm.c \
- cmdhflto.c \
- cmdhw.c \
- cmdlf.c \
- cmdlfawid.c \
- cmdlfcotag.c \
- cmdlfem4x.c \
- cmdlffdx.c \
- cmdlfguard.c \
- cmdlfgallagher.c \
- cmdlfhid.c \
- cmdlfhitag.c \
- cmdlfio.c \
- cmdlfindala.c \
- cmdlfjablotron.c \
- cmdlfkeri.c \
- cmdlfnexwatch.c \
- cmdlfnedap.c \
- cmdlfnoralsy.c \
- cmdlfpac.c \
- cmdlfparadox.c \
- cmdlfpcf7931.c \
- cmdlfpresco.c \
- cmdlfpyramid.c \
- cmdlfsecurakey.c \
- cmdlft55xx.c \
- cmdlfti.c \
- cmdlfviking.c \
- cmdlfvisa2000.c \
- cmdlfmotorola.c \
- cmdtrace.c \
- cmdflashmem.c \
- cmdflashmemspiffs.c \
- cmdsmartcard.c \
- cmdusart.c \
- cmdwiegand.c \
- cmdparser.c \
- cmdmain.c \
- pm3_binlib.c \
- scripting.c \
- cmdscript.c \
- pm3_bitlib.c \
- cmdcrc.c \
- bucketsort.c \
- flash.c \
- wiegand_formats.c \
- wiegand_formatutils.c
-
-cpu_arch = $(shell uname -m)
-ifneq ($(findstring 86, $(cpu_arch)), )
- MULTIARCHSRCS = hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c
-endif
-ifneq ($(findstring amd64, $(cpu_arch)), )
- MULTIARCHSRCS = hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c
-endif
-ifeq ($(MULTIARCHSRCS), )
- CMDSRCS += hardnested/hardnested_bf_core.c hardnested/hardnested_bitarray_core.c
-endif
-
-
-COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
-CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
-OBJCOBJS = $(OBJCSRCS:%.m=$(OBJDIR)/%.o)
-MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \
- $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \
- $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_SSE2.o) \
- $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX.o) \
- $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX2.o)
-
-SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" )
-
-HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2
-HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2
-HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2
-HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2
-HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2
-HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f
-ifeq "$(SUPPORTS_AVX512)" "True"
- HARD_SWITCH_NOSIMD += -mno-avx512f
- HARD_SWITCH_MMX += -mno-avx512f
- HARD_SWITCH_SSE2 += -mno-avx512f
- HARD_SWITCH_AVX += -mno-avx512f
- HARD_SWITCH_AVX2 += -mno-avx512f
- MULTIARCHOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o)
-endif
-
-BINS = proxmark3
-CLEAN = $(BINS) *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
-# transition: make sure old flasher is gone too
-CLEAN += flasher
-
-# need to assign dependancies to build these first...
-all: $(BINS)
-
-all-static: LDLIBS:=-static $(LDLIBS)
-all-static: $(BINS)
-
-proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(ZLIB) $(REVENGLIB) $(AMIIBOLIB) $(QTLDLIBS)
-proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LUALIB) $(JANSSONLIB) $(CBORLIB) $(REVENGLIB) $(MBEDTLSLIB) $(ZLIB) $(AMIIBOLIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
- $(info [=] LD $@)
- $(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LDLIBS) -o $@
-
-proxgui.cpp: ui/ui_overlays.h
-
-proxguiqt.moc.cpp: proxguiqt.h
- $(info [-] MOC $@)
- $(Q)$(MOC) -o$@ $^
-
-ui/ui_overlays.h: ui/overlays.ui
- $(info [-] UIC $@)
- $(Q)$(UIC) $^ > $@
-
-lualibs/pm3_cmd.lua: ../include/pm3_cmd.h
- $(info [=] GEN $@)
- $(Q)awk -f pm3_cmd_h2lua.awk $^ > $@
-
-lualibs/mfc_default_keys.lua : mfc_default_keys.dic
- $(info [=] GEN $@)
- $(Q)awk -f default_keys_dic2lua.awk $^ > $@
-
-clean:
- $(Q)$(RM) $(CLEAN)
- $(Q)$(RMDIR) $(OBJDIR)
- $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) clean
- $(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) clean
- $(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) clean
- $(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) clean
- $(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) clean
-
-install: all
- $(info [@] Installing client to $(DESTDIR)$(PREFIX)...)
-ifneq (,$(INSTALLBIN))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
- $(Q)$(CP) $(INSTALLBIN) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
-endif
-ifneq (,$(INSTALLSHARE))
- $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
- $(Q)$(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
-endif
- @true
-
-uninstall:
- $(info [@] Uninstalling client from $(DESTDIR)$(PREFIX)...)
-ifneq (,$(INSTALLBIN))
- $(Q)$(RM) $(foreach tool,$(INSTALLBIN),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(tool)))
-endif
-ifneq (,$(INSTALLSHARE))
- $(Q)$(RMDIR) $(foreach tool,$(INSTALLSHARE),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(tool)))
-endif
- @true
-
-tarbin: $(BINS)
- $(info [=] TAR ../proxmark3-$(platform)-bin.tar)
- $(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%)
-
-# local libraries:
-$(LUALIB):
- $(info [*] MAKE liblua for $(LUAPLATFORM))
- $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM)
-
-$(JANSSONLIB):
- $(info [*] MAKE jansson)
- $(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all
-
-$(CBORLIB):
- $(info [*] MAKE tinycbor)
- $(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) all
-
-$(REVENGLIB):
- $(info [*] MAKE reveng)
- $(Q)$(MAKE) --no-print-directory -C $(REVENGPATH) all
-
-$(AMIIBOLIB):
- $(info [*] MAKE amiibo)
- $(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all
-
-# common libraries:
-$(MBEDTLSLIB):
- $(info [*] MAKE mbedtls)
- $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all
-
-$(ZLIB):
- $(info [*] MAKE zlib)
- $(Q)$(MAKE) --no-print-directory -C $(ZLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all
-
-.PHONY: all clean install uninstall
-
-# easy printing of MAKE VARIABLES
-print-%: ; @echo $* = $($*)
-
-$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d
- $(info [-] CC(NOSIMD) $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(PM3CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $<
- $(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d && $(TOUCH) $@
-
-$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d
- $(info [-] CC(MMX) $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(PM3CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $<
- $(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d && $(TOUCH) $@
-
-$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d
- $(info [-] CC(SSE2) $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(PM3CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $<
- $(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d && $(TOUCH) $@
-
-$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d
- $(info [-] CC(AVX) $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $<
- $(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d && $(TOUCH) $@
-
-$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d
- $(info [-] CC(AVX2) $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $<
- $(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d && $(TOUCH) $@
-
-$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d
- $(info [-] CC(AVX512) $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(PM3CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $<
- $(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d && $(TOUCH) $@
-
-%.o: %.c
-$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
- $(info [-] CC $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $<
- $(Q)$(POSTCOMPILE)
-
-%.o: %.cpp
-$(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d
- $(info [-] CXX $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CXX) $(DEPFLAGS) $(PM3CXXFLAGS) $(QTINCLUDES) -c -o $@ $<
- $(Q)$(POSTCOMPILE)
-
-%.o: %.m
-$(OBJDIR)/%.o : %.m $(OBJDIR)/%.d
- $(info [-] CC $<)
- $(Q)$(MKDIR) $(dir $@)
- $(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $<
- $(Q)$(POSTCOMPILE)
-
-DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(REVENGSRCS)) \
- $(patsubst %.o, %.d, $(MULTIARCHOBJS)) \
- $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \
- $(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \
- $(OBJDIR)/proxmark3.d
-
-$(DEPENDENCY_FILES): ;
-.PRECIOUS: $(DEPENDENCY_FILES)
-
--include $(DEPENDENCY_FILES)
diff --git a/pm3rdv4rrg/src/main/cpp/client/README-bitlib b/pm3rdv4rrg/src/main/cpp/client/README-bitlib
deleted file mode 100644
index 76683a2f..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/README-bitlib
+++ /dev/null
@@ -1,71 +0,0 @@
- bitlib
- ------
-
- by Reuben Thomas
- http://luaforge.net/projects/bitlib
-
-
-bitlib is a C library for Lua 5.1 that provides bitwise operations. It
-is copyright Reuben Thomas 2000-2009, and is released under the MIT
-license, like Lua (see http://www.lua.org/copyright.html; it's
-basically the same as the BSD license). There is no warranty.
-
-Please report bugs and make suggestions to the email address above, or
-use the LuaForge trackers.
-
-Thanks to John Passaniti for his bitwise operations library, some of
-whose ideas I used, to Shmuel Zeigerman for the test suite, to
-Thatcher Ulrich for portability fixes, and to Enrico Tassi, John
-Stiles and Eduardo Ochs for bug reports.
-
-
-Installation
-------------
-
-As normal:
-
- ./configure && make [&& make check] [&& make install]
-
-If you get warnings about integer constants being too large, don't
-worry. They won't be used.
-
-The following options may be of interest if you have Lua installed on
-non-default paths (as you are likely to on any system supporting more
-than one version of Lua):
-
- --libdir=DIR Install shared library in this directory
- --with-lua-prefix=DIR Lua files are in DIR
- --with-lua-includes=DIR Lua include files are in DIR
- --with-lua-libraries=DIR
- Lua library files are in DIR, or "no" if not used
- --with-lua-suffix=ARG Lua binary and library files are suffixed with ARG
-
-For example, on Debian or Ubuntu:
-
- ./configure --libdir=/usr/local/lib/lua/5.1 --with-lua-includes=/usr/include/lua5.1 --with-lua-suffix=5.1 --with-lua-libraries=no
-
-
-Use
----
-
-Make sure the library is installed on your LUA_CPATH, and require it.
-
-The library provides the constant bit.bits that gives the number of
-bits that can be used in bitwise operations, and the following
-functions:
-
-bit.cast(a) cast a to the internally-used integer type
-bit.bnot(a) returns the one's complement of a
-bit.band(w1, ...) returns the bitwise and of the w's
-bit.bor(w1, ...) returns the bitwise or of the w's
-bit.bxor(w1, ...) returns the bitwise exclusive or of the w's
-bit.lshift(a, b) returns a shifted left b places
-bit.rshift(a, b) returns a shifted logically right b places
-bit.arshift(a, b) returns a shifted arithmetically right b places
-
-All function arguments should be integers that fit into the C type
-lua_Integer.
-
-The logical operations start with "b" for "bit" to avoid clashing with
-reserved words; although "xor" isn't a reserved word, it seemed better
-to use "bxor" for consistency.
diff --git a/pm3rdv4rrg/src/main/cpp/client/aidsearch.c b/pm3rdv4rrg/src/main/cpp/client/aidsearch.c
deleted file mode 100644
index 676db4cc..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/aidsearch.c
+++ /dev/null
@@ -1,177 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2019 merlokk
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Proxmark3 RDV40 AID list library
-//-----------------------------------------------------------------------------
-#include "aidsearch.h"
-#include
-#include
-#include "fileutils.h"
-#include "pm3_cmd.h"
-
-int openAIDFile(json_t **root, bool verbose) {
- json_error_t error;
-
- char *path;
- int res = searchFile(&path, RESOURCES_SUBDIR, "aidlist", ".json", false);
- if (res != PM3_SUCCESS) {
- return PM3_EFILE;
- }
-
- int retval = PM3_SUCCESS;
- *root = json_load_file(path, 0, &error);
- if (!*root) {
- PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text);
- retval = PM3_ESOFT;
- goto out;
- }
-
- if (!json_is_array(*root)) {
- PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path);
- retval = PM3_ESOFT;
- goto out;
- }
-
- if (verbose) PrintAndLogEx(SUCCESS, "Loaded file (%s) OK. %zu records.", path, json_array_size(*root));
-out:
- free(path);
- return retval;
-}
-
-int closeAIDFile(json_t *root) {
-
- json_decref(root);
- return PM3_SUCCESS;
-}
-
-json_t *AIDSearchInit(bool verbose) {
- json_t *root = NULL;
- int res = openAIDFile(&root, verbose);
- if (res != PM3_SUCCESS)
- return NULL;
-
- return root;
-}
-
-json_t *AIDSearchGetElm(json_t *root, int elmindx) {
- json_t *data = json_array_get(root, elmindx);
- if (!json_is_object(data)) {
- PrintAndLogEx(ERR, "data [%d] is not an object\n", elmindx);
- return NULL;
- }
- return data;
-}
-
-int AIDSearchFree(json_t *root) {
-
- return closeAIDFile(root);
-}
-
-const char *jsonStrGet(json_t *data, char *name) {
- json_t *jstr;
-
- jstr = json_object_get(data, name);
- if (jstr == NULL)
- return NULL;
- if (!json_is_string(jstr)) {
- PrintAndLogEx(ERR, "`%s` is not a string", name);
- return NULL;
- }
-
- const char *cstr = json_string_value(jstr);
- if (strlen(cstr) == 0)
- return NULL;
- return cstr;
-}
-
-bool aidCompare(const char *aidlarge, const char *aidsmall) {
- if (strcmp(aidlarge, aidsmall) == 0)
- return true;
-
- if (strlen(aidlarge) > strlen(aidsmall))
- if (strncmp(aidlarge, aidsmall, strlen(aidsmall)) == 0)
- return true;
-
- return false;
-}
-
-bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen) {
- *aidlen = 0;
- const char *hexaid = jsonStrGet(data, "AID");
- if (hexaid == NULL || strlen(hexaid) == 0)
- return false;
-
- int res = param_gethex_to_eol(hexaid, 0, aid, aidmaxlen, aidlen);
- if (res)
- return false;
-
- return true;
-}
-
-int PrintAIDDescription(json_t *xroot, char *aid, bool verbose) {
- int retval = PM3_SUCCESS;
-
- json_t *root = xroot;
- if (root == NULL)
- root = AIDSearchInit(verbose);
- if (root == NULL)
- goto out;
-
- json_t *elm = NULL;
- int maxaidlen = 0;
- for (int elmindx = 0; elmindx < json_array_size(root); elmindx++) {
- json_t *data = AIDSearchGetElm(root, elmindx);
- if (data == NULL)
- continue;
- const char *dictaid = jsonStrGet(data, "AID");
- if (aidCompare(aid, dictaid)) { // dictaid may be less length than requested aid
- if (maxaidlen < strlen(dictaid) && strlen(dictaid) <= strlen(aid)) {
- maxaidlen = strlen(dictaid);
- elm = data;
- }
- }
- }
-
- if (elm == NULL)
- goto out;
-
- // print here
- const char *vaid = jsonStrGet(elm, "AID");
- const char *vendor = jsonStrGet(elm, "Vendor");
- const char *name = jsonStrGet(elm, "Name");
- const char *country = jsonStrGet(elm, "Country");
- const char *description = jsonStrGet(elm, "Description");
- const char *type = jsonStrGet(elm, "Type");
-
- if (!verbose) {
- PrintAndLogEx(SUCCESS, "AID %s | %s | %s", vaid, vendor, name);
- } else {
- PrintAndLogEx(SUCCESS, "Input AID: %s", aid);
- if (aid)
- PrintAndLogEx(SUCCESS, "Found AID: %s", vaid);
- if (vendor)
- PrintAndLogEx(SUCCESS, "Vendor: %s", vendor);
- if (type)
- PrintAndLogEx(SUCCESS, "Type: %s", type);
- if (name)
- PrintAndLogEx(SUCCESS, "Name: %s", name);
- if (country)
- PrintAndLogEx(SUCCESS, "Country: %s", country);
- if (description)
- PrintAndLogEx(SUCCESS, "Description: %s", description);
- }
-
-out:
- if (xroot == NULL)
- AIDSearchFree(root);
- return retval;
-}
-
-int PrintAIDDescriptionBuf(json_t *root, uint8_t *aid, size_t aidlen, bool verbose) {
- return PrintAIDDescription(root, sprint_hex_inrow(aid, aidlen), verbose);
-}
-
diff --git a/pm3rdv4rrg/src/main/cpp/client/aidsearch.h b/pm3rdv4rrg/src/main/cpp/client/aidsearch.h
deleted file mode 100644
index 00d2b134..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/aidsearch.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2019 merlokk
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Proxmark3 RDV40 AID list library
-//-----------------------------------------------------------------------------
-
-#ifndef AIDSEARCH_H__
-#define AIDSEARCH_H__
-
-#include "common.h"
-
-#include
-#include
-
-#include
-
-int PrintAIDDescription(json_t *xroot, char *aid, bool verbose);
-int PrintAIDDescriptionBuf(json_t *root, uint8_t *aid, size_t aidlen, bool verbose);
-json_t *AIDSearchInit(bool verbose);
-json_t *AIDSearchGetElm(json_t *root, int elmindx);
-bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen);
-int AIDSearchFree();
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/LICENSE b/pm3rdv4rrg/src/main/cpp/client/amiitool/LICENSE
deleted file mode 100644
index 35627b40..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-(c) 2015-2017 Marcos Del Sol Vives
-(c) 2016 javiMaD
-(c) 2016 Michael Armbruster
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/Makefile b/pm3rdv4rrg/src/main/cpp/client/amiitool/Makefile
deleted file mode 100644
index c473f58e..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-MYSRCPATHS =
-MYINCLUDES = -I. -I.. -I../jansson -I../../common/ -I../../include/
-MYCFLAGS = -std=c99 -D_ISOC99_SOURCE
-MYDEFS =
-MYSRCS = \
- amiibo.c \
- drbg.c \
- keygen.c
-
-LIB_A = libamiibo.a
-
-include ../../Makefile.host
-
-# just for testing amiitool before complete migration into a lib:
-
-amiitool:
- gcc $(CFLAGS) \
- amiitool.c $(MYSRCS) ../../common/commonutil.c ../ui.c -lreadline -lm ../../common/mbedtls/libmbedtls.a \
- -o amiitool
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/amiibo.c b/pm3rdv4rrg/src/main/cpp/client/amiitool/amiibo.c
deleted file mode 100644
index 809f611d..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/amiibo.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- * (c) 2016 javiMaD
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include "amiibo.h"
-#include "mbedtls/md.h"
-#include "mbedtls/aes.h"
-#include "commonutil.h"
-
-#define HMAC_POS_DATA 0x008
-#define HMAC_POS_TAG 0x1B4
-
-void nfc3d_amiibo_calc_seed(const uint8_t *dump, uint8_t *key) {
- memcpy(key + 0x00, dump + 0x029, 0x02);
- memset(key + 0x02, 0x00, 0x0E);
- memcpy(key + 0x10, dump + 0x1D4, 0x08);
- memcpy(key + 0x18, dump + 0x1D4, 0x08);
- memcpy(key + 0x20, dump + 0x1E8, 0x20);
-}
-
-void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys *masterKeys, const uint8_t *dump, nfc3d_keygen_derivedkeys *derivedKeys) {
- uint8_t seed[NFC3D_KEYGEN_SEED_SIZE];
-
- nfc3d_amiibo_calc_seed(dump, seed);
- nfc3d_keygen(masterKeys, seed, derivedKeys);
-}
-
-void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys *keys, const uint8_t *in, uint8_t *out) {
- mbedtls_aes_context aes;
- size_t nc_off = 0;
- unsigned char nonce_counter[16];
- unsigned char stream_block[16];
-
- mbedtls_aes_setkey_enc(&aes, keys->aesKey, 128);
- memset(nonce_counter, 0, sizeof(nonce_counter));
- memset(stream_block, 0, sizeof(stream_block));
- memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter));
- mbedtls_aes_crypt_ctr(&aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C);
-
- memcpy(out + 0x000, in + 0x000, 0x008);
- // Data signature NOT copied
- memcpy(out + 0x028, in + 0x028, 0x004);
- // Tag signature NOT copied
- memcpy(out + 0x1D4, in + 0x1D4, 0x034);
-}
-
-void nfc3d_amiibo_tag_to_internal(const uint8_t *tag, uint8_t *intl) {
- memcpy(intl + 0x000, tag + 0x008, 0x008);
- memcpy(intl + 0x008, tag + 0x080, 0x020);
- memcpy(intl + 0x028, tag + 0x010, 0x024);
- memcpy(intl + 0x04C, tag + 0x0A0, 0x168);
- memcpy(intl + 0x1B4, tag + 0x034, 0x020);
- memcpy(intl + 0x1D4, tag + 0x000, 0x008);
- memcpy(intl + 0x1DC, tag + 0x054, 0x02C);
-}
-
-void nfc3d_amiibo_internal_to_tag(const uint8_t *intl, uint8_t *tag) {
- memcpy(tag + 0x008, intl + 0x000, 0x008);
- memcpy(tag + 0x080, intl + 0x008, 0x020);
- memcpy(tag + 0x010, intl + 0x028, 0x024);
- memcpy(tag + 0x0A0, intl + 0x04C, 0x168);
- memcpy(tag + 0x034, intl + 0x1B4, 0x020);
- memcpy(tag + 0x000, intl + 0x1D4, 0x008);
- memcpy(tag + 0x054, intl + 0x1DC, 0x02C);
-}
-
-bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain) {
- uint8_t internal[NFC3D_AMIIBO_SIZE];
- nfc3d_keygen_derivedkeys dataKeys;
- nfc3d_keygen_derivedkeys tagKeys;
-
- // Convert format
- nfc3d_amiibo_tag_to_internal(tag, internal);
-
- // Generate keys
- nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys);
- nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys);
-
- // Decrypt
- nfc3d_amiibo_cipher(&dataKeys, internal, plain);
-
- // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
- plain + 0x1D4, 0x34, plain + HMAC_POS_TAG);
-
- // Regenerate data HMAC
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey),
- plain + 0x029, 0x1DF, plain + HMAC_POS_DATA);
-
- return
- memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 &&
- memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0;
-}
-
-void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag) {
- uint8_t cipher[NFC3D_AMIIBO_SIZE];
- nfc3d_keygen_derivedkeys tagKeys;
- nfc3d_keygen_derivedkeys dataKeys;
-
- // Generate keys
- nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys);
- nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys);
-
- // Generate tag HMAC
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
- plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG);
-
- // Init mbedtls HMAC context
- mbedtls_md_context_t ctx;
- mbedtls_md_init(&ctx);
- mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
-
- // Generate data HMAC
- mbedtls_md_hmac_starts(&ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey));
- mbedtls_md_hmac_update(&ctx, plain + 0x029, 0x18B); // Data
- mbedtls_md_hmac_update(&ctx, cipher + HMAC_POS_TAG, 0x20); // Tag HMAC
- mbedtls_md_hmac_update(&ctx, plain + 0x1D4, 0x34); // Here be dragons
-
- mbedtls_md_hmac_finish(&ctx, cipher + HMAC_POS_DATA);
-
- // HMAC cleanup
- mbedtls_md_free(&ctx);
-
- // Encrypt
- nfc3d_amiibo_cipher(&dataKeys, plain, cipher);
-
- // Convert back to hardware
- nfc3d_amiibo_internal_to_tag(cipher, tag);
-}
-
-bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path) {
- FILE *f = fopen(path, "rb");
- if (!f) {
- return false;
- }
-
- size_t len = fread(amiiboKeys, sizeof(*amiiboKeys), 1, f);
- fclose(f);
-
- if (len != sizeof(*amiiboKeys)) {
- return false;
- }
-
- if ((amiiboKeys->data.magicBytesSize > 16) ||
- (amiiboKeys->tag.magicBytesSize > 16)) {
- return false;
- }
-
- return true;
-}
-
-void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst) {
-
-
- //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29);
- //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4);
-
- /* increment write counters */
- //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1);
- //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1);
-
- uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1;
- uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1;
-
- num_to_bytes(ami_nb_wr, 2, dst + 0x29);
- num_to_bytes(cfg_nb_wr, 2, dst + 0xB4);
-
- /* copy flags */
- dst[0x2C] = src[0x2C];
- /* copy programID */
- memcpy(dst + 0xAC, src + 0xAC, 8);
- /* copy AppID */
- memcpy(dst + 0xB6, src + 0xB6, 4);
- /* copy AppData */
- memcpy(dst + 0xDC, src + 0xDC, 216);
-}
-
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/amiibo.h b/pm3rdv4rrg/src/main/cpp/client/amiitool/amiibo.h
deleted file mode 100644
index 47d54487..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/amiibo.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- * (c) 2016 javiMaD
- *
- * SPDX-License-Identifier: MIT
- */
-
-#ifndef HAVE_NFC3D_AMIIBO_H
-#define HAVE_NFC3D_AMIIBO_H
-
-#include
-#include
-#include
-#include
-#include "keygen.h"
-
-#define NFC3D_AMIIBO_SIZE 520
-
-#pragma pack(1)
-typedef struct {
- nfc3d_keygen_masterkeys data;
- nfc3d_keygen_masterkeys tag;
-} nfc3d_amiibo_keys;
-#pragma pack()
-
-bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain);
-void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag);
-bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path);
-void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/amiitool.c b/pm3rdv4rrg/src/main/cpp/client/amiitool/amiitool.c
deleted file mode 100644
index ca34a5c6..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/amiitool.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- * (c) 2016 javiMaD
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include
-#include
-#include "fileutils.h"
-#include "amiibo.h"
-#include "getopt.h"
-
-#define NTAG215_SIZE 540
-
-static char *self;
-
-void amiitool_usage() {
- fprintf(stderr,
- /*"amiitool build %i (commit %s-%08x)\n"*/
- "by Marcos Del Sol Vives \n"
- "\n"
- "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n"
- " -e encrypt and sign amiibo\n"
- " -d decrypt and test amiibo\n"
- " -c decrypt, copy AppData and encrypt amiibo\n"
- " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n"
- " -i input file. If not specified, stdin will be used.\n"
- " -s input save file, save from this file will replace input file ones.\n"
- " -o output file. If not specified, stdout will be used.\n"
- " -l decrypt files with invalid signatures.\n",
- self
- );
-}
-
-static bool LoadAmiikey(nfc3d_amiibo_keys keys, char *keyfile) {
-
- if (!nfc3d_amiibo_load_keys(&keys, keyfile)) {
- PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile);
- return false;
- }
- return true;
-}
-
-int main(int argc, char **argv) {
- self = argv[0];
-
- char *infile = NULL;
- char *savefile = NULL;
- char *outfile = NULL;
- char *keyfile = NULL;
- char op = '\0';
- bool lenient = false;
-
- char c;
- while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) {
- switch (c) {
- case 'e':
- case 'd':
- case 'c':
- op = c;
- break;
- case 'i':
- infile = optarg;
- break;
- case 'k':
- keyfile = optarg;
- break;
- case 's':
- savefile = optarg;
- break;
- case 'o':
- outfile = optarg;
- break;
- case 'l':
- lenient = true;
- break;
- default:
- amiitool_usage();
- return 2;
- }
- }
-
- if (op == '\0' || keyfile == NULL) {
- amiitool_usage();
- return 1;
- }
-
- nfc3d_amiibo_keys amiiboKeys;
- if (! LoadAmiikey(amiiboKeys, keyfile))
- return 5;
-
- uint8_t original[NTAG215_SIZE];
- uint8_t modified[NFC3D_AMIIBO_SIZE];
-
- FILE *f = stdin;
- if (infile) {
- f = fopen(infile, "rb");
- if (!f) {
- fprintf(stderr, "Could not open input file\n");
- return 3;
- }
- }
- size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f);
- if (readPages < NFC3D_AMIIBO_SIZE / 4) {
- fprintf(stderr, "Could not read from input\n");
- fclose(f);
- return 3;
- }
- fclose(f);
-
-
- if (op == 'e') {
- nfc3d_amiibo_pack(&amiiboKeys, original, modified);
- } else if (op == 'd') {
- if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) {
- fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n");
- if (!lenient) {
- return 6;
- }
- }
- } else { /* copy */
- uint8_t plain_base[NFC3D_AMIIBO_SIZE];
- uint8_t plain_save[NFC3D_AMIIBO_SIZE];
-
- if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) {
- fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n");
- if (!lenient) {
- return 6;
- }
- }
- if (savefile) {
- f = fopen(savefile, "rb");
- if (!f) {
- fprintf(stderr, "Could not open save file\n");
- return 3;
- }
- }
- size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f);
- if (readPages < NFC3D_AMIIBO_SIZE / 4) {
- fprintf(stderr, "Could not read from save\n");
- fclose(f);
- return 3;
- }
- fclose(f);
-
- if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) {
- fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n");
- if (!lenient) {
- return 6;
- }
- }
-
- nfc3d_amiibo_copy_app_data(plain_save, plain_base);
- nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified);
- }
-
- f = stdout;
- if (outfile) {
- f = fopen(outfile, "wb");
- if (!f) {
- fprintf(stderr, "Could not open output file\n");
- return 4;
- }
- }
- if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) {
- fprintf(stderr, "Could not write to output\n");
- fclose(f);
- return 4;
- }
- if (readPages > NFC3D_AMIIBO_SIZE / 4) {
- if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) {
- fprintf(stderr, "Could not write to output:\n");
- fclose(f);
- return 4;
- }
- }
- fclose(f);
- return 0;
-}
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/drbg.c b/pm3rdv4rrg/src/main/cpp/client/amiitool/drbg.c
deleted file mode 100644
index c1297920..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/drbg.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- * (c) 2016 javiMaD
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include "drbg.h"
-#include
-#include
-#include "mbedtls/md.h"
-
-void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize) {
- assert(ctx != NULL);
- assert(hmacKey != NULL);
- assert(seed != NULL);
- assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE);
-
- // Initialize primitives
- ctx->used = false;
- ctx->iteration = 0;
- ctx->bufferSize = sizeof(ctx->iteration) + seedSize;
-
- // The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start
- memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize);
-
- // Initialize underlying HMAC context
- mbedtls_md_init(&ctx->hmacCtx);
- mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
- mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize);
-}
-
-void nfc3d_drbg_step(nfc3d_drbg_ctx *ctx, uint8_t *output) {
- assert(ctx != NULL);
- assert(output != NULL);
-
- if (ctx->used) {
- // If used at least once, reinitialize the HMAC
- mbedtls_md_hmac_reset(&ctx->hmacCtx);
- } else {
- ctx->used = true;
- }
-
- // Store counter in big endian, and increment it
- ctx->buffer[0] = ctx->iteration >> 8;
- ctx->buffer[1] = ctx->iteration >> 0;
- ctx->iteration++;
-
- // Do HMAC magic
- mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize);
- mbedtls_md_hmac_finish(&ctx->hmacCtx, output);
-}
-
-void nfc3d_drbg_cleanup(nfc3d_drbg_ctx *ctx) {
- assert(ctx != NULL);
- mbedtls_md_free(&ctx->hmacCtx);
-}
-
-void nfc3d_drbg_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize) {
- uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE];
-
- nfc3d_drbg_ctx rngCtx;
- nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize);
-
- while (outputSize > 0) {
- if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) {
- nfc3d_drbg_step(&rngCtx, temp);
- memcpy(output, temp, outputSize);
- break;
- }
-
- nfc3d_drbg_step(&rngCtx, output);
- output += NFC3D_DRBG_OUTPUT_SIZE;
- outputSize -= NFC3D_DRBG_OUTPUT_SIZE;
- }
-
- nfc3d_drbg_cleanup(&rngCtx);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/drbg.h b/pm3rdv4rrg/src/main/cpp/client/amiitool/drbg.h
deleted file mode 100644
index d77d030a..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/drbg.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- * (c) 2016 javiMaD
- *
- * SPDX-License-Identifier: MIT
- */
-
-#ifndef HAVE_NFC3D_DRBG_H
-#define HAVE_NFC3D_DRBG_H
-
-#include
-#include
-#include "mbedtls/md.h"
-
-#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */
-#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */
-
-typedef struct {
- mbedtls_md_context_t hmacCtx;
- bool used;
- uint16_t iteration;
-
- uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE];
- size_t bufferSize;
-} nfc3d_drbg_ctx;
-
-void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize);
-void nfc3d_drbg_step(nfc3d_drbg_ctx *ctx, uint8_t *output);
-void nfc3d_drbg_cleanup(nfc3d_drbg_ctx *ctx);
-void nfc3d_drbg_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize);
-
-#endif
-
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/keygen.c b/pm3rdv4rrg/src/main/cpp/client/amiitool/keygen.c
deleted file mode 100644
index f148c0dc..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/keygen.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include "drbg.h"
-#include "keygen.h"
-#include
-#include
-#include
-
-void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, uint8_t *output, size_t *outputSize) {
- assert(baseKeys != NULL);
- assert(baseSeed != NULL);
- assert(output != NULL);
- assert(outputSize != NULL);
-
- uint8_t *start = output;
-
- // 1: Copy whole type string
- output = (uint8_t *)strcpy((char *)output, baseKeys->typeString);
-
- // 2: Append (16 - magicBytesSize) from the input seed
- size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize;
- memcpy(output, baseSeed, leadingSeedBytes);
- output += leadingSeedBytes;
-
- // 3: Append all bytes from magicBytes
- memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize);
- output += baseKeys->magicBytesSize;
-
- // 4: Append bytes 0x10-0x1F from input seed
- memcpy(output, baseSeed + 0x10, 16);
- output += 16;
-
- // 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them
- unsigned int i;
- for (i = 0; i < 32; i++) {
- output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i];
- }
- output += 32;
-
- *outputSize = output - start;
-}
-
-void nfc3d_keygen(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, nfc3d_keygen_derivedkeys *derivedKeys) {
- uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE];
- size_t preparedSeedSize;
-
- nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize);
- nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys));
-}
diff --git a/pm3rdv4rrg/src/main/cpp/client/amiitool/keygen.h b/pm3rdv4rrg/src/main/cpp/client/amiitool/keygen.h
deleted file mode 100644
index 4d1c21ce..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/amiitool/keygen.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * (c) 2015-2017 Marcos Del Sol Vives
- *
- * SPDX-License-Identifier: MIT
- */
-
-#ifndef HAVE_NFC3D_KEYGEN_H
-#define HAVE_NFC3D_KEYGEN_H
-
-#include
-#include
-
-#define NFC3D_KEYGEN_SEED_SIZE 64
-
-#pragma pack(1)
-typedef struct {
- uint8_t hmacKey[16];
- char typeString[14];
- uint8_t rfu;
- uint8_t magicBytesSize;
- uint8_t magicBytes[16];
- uint8_t xorPad[32];
-} nfc3d_keygen_masterkeys;
-
-typedef struct {
- const uint8_t aesKey[16];
- const uint8_t aesIV[16];
- const uint8_t hmacKey[16];
-} nfc3d_keygen_derivedkeys;
-#pragma pack()
-
-void nfc3d_keygen(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, nfc3d_keygen_derivedkeys *derivedKeys);
-
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/cliparser/README.md b/pm3rdv4rrg/src/main/cpp/client/cliparser/README.md
deleted file mode 100644
index 2b321946..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cliparser/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Command line parser
-
-cliparser - librari for proxmark with command line parsing high level functions.
-
-## External libraries:
-
-### argtable
-
-Argtable3 is a single-file, ANSI C, command-line parsing library that parses GNU-style command-line options.
-
-You can download argtable3 from this repository https://github.com/argtable/argtable3
-
-[argtable3 license](https://github.com/argtable/argtable3/blob/master/LICENSE)
diff --git a/pm3rdv4rrg/src/main/cpp/client/cliparser/argtable3.c b/pm3rdv4rrg/src/main/cpp/client/cliparser/argtable3.c
deleted file mode 100644
index 8d5b2de7..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cliparser/argtable3.c
+++ /dev/null
@@ -1,4711 +0,0 @@
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include "argtable3.h"
-
-// On Windows isspace crashes app in case of using Unicode character set and string to be above ASCII
-// so you have to use _istspace instead of space
-#ifdef UNICODE
-#include
-#define ISSPACE _istspace
-#else
-#define ISSPACE isspace
-#endif
-
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 2013 Tom G. Huang
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#ifndef ARG_UTILS_H
-#define ARG_UTILS_H
-
-#define ARG_ENABLE_TRACE 0
-#define ARG_ENABLE_LOG 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
- EMINCOUNT = 1,
- EMAXCOUNT,
- EBADINT,
- // The same name define EOVERFLOW in errno.h on windows platform
-#ifdef __STDC_WANT_SECURE_LIB__
- EOVERFLOW_,
-#else
-// in android, the name is define
-#ifdef __ANDROID_NDK__
- EOVERFLOW_,
-#else
- EOVERFLOW
-#endif
-#endif
- EBADDOUBLE,
- EBADDATE,
- EREGNOMATCH
-};
-
-
-#if defined(_MSC_VER)
-#define ARG_TRACE(x) \
- __pragma(warning(push)) \
- __pragma(warning(disable:4127)) \
- do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0) \
- __pragma(warning(pop))
-
-#define ARG_LOG(x) \
- __pragma(warning(push)) \
- __pragma(warning(disable:4127)) \
- do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) \
- __pragma(warning(pop))
-#else
-#define ARG_TRACE(x) \
- do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0)
-
-#define ARG_LOG(x) \
- do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0)
-#endif
-
-extern void dbg_printf(const char *fmt, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-#include
-
-
-void dbg_printf(const char *fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
-}
-
-#include "getopt.h"
-
-/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */
-/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */
-/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
-
-/*
- * Copyright (c) 2002 Todd C. Miller
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-
-// $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $"
-
-/*-
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Dieter Baron and Thomas Klausner.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if 0
-#include
-#endif
-#include
-#include
-#include
-
-
-#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
-
-#ifdef REPLACE_GETOPT
-int opterr = 1; /* if error message should be printed */
-int optind = 1; /* index into parent argv vector */
-int optopt = '?'; /* character checked for validity */
-int optreset; /* reset getopt */
-const char *optarg; /* argument associated with option */
-#endif
-
-#define PRINT_ERROR ((opterr) && (*options != ':'))
-
-#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
-#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
-#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
-
-/* return values */
-#define BADCH (int)'?'
-#define BADARG ((*options == ':') ? (int)':' : (int)'?')
-#define INORDER (int)1
-
-#define EMSG ""
-
-static int getopt_internal(int, char *const *, const char *,
- const struct option *, int *, int);
-static int parse_long_options(char *const *, const char *,
- const struct option *, int *, int);
-static int gcd(int, int);
-static void permute_args(int, int, int, char *const *);
-
-static const char *place = EMSG; /* option letter processing */
-
-/* XXX: set optreset to 1 rather than these two */
-static int nonopt_start = -1; /* first non option argument (for permute) */
-static int nonopt_end = -1; /* first option after non options (for permute) */
-
-/* Error messages */
-static const char recargchar[] = "option requires an argument -- %c";
-static const char recargstring[] = "option requires an argument -- %s";
-static const char ambig[] = "ambiguous option -- %.*s";
-static const char noarg[] = "option doesn't take an argument -- %.*s";
-static const char illoptchar[] = "unknown option -- %c";
-static const char illoptstring[] = "unknown option -- %s";
-
-
-
-#ifdef _WIN32
-
-/* Windows needs warnx(). We change the definition though:
- * 1. (another) global is defined, opterrmsg, which holds the error message
- * 2. errors are always printed out on stderr w/o the program name
- * Note that opterrmsg always gets set no matter what opterr is set to. The
- * error message will not be printed if opterr is 0 as usual.
- */
-
-#include
-#include
-
-#define MAX_OPTER_MSG_SIZE 128
-
-extern char opterrmsg[MAX_OPTER_MSG_SIZE];
-char opterrmsg[MAX_OPTER_MSG_SIZE]; /* buffer for the last error message */
-
-static void warnx(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- /*
- Make sure opterrmsg is always zero-terminated despite the _vsnprintf()
- implementation specifics and manually suppress the warning.
- */
- memset(opterrmsg, 0, sizeof opterrmsg);
- if (fmt != NULL)
-#ifdef __STDC_WANT_SECURE_LIB__
- _vsnprintf_s(opterrmsg, MAX_OPTER_MSG_SIZE, sizeof(opterrmsg) - 1, fmt, ap);
-#else
- _vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap);
-#endif
- va_end(ap);
-
- fprintf(stderr, "%s\n", opterrmsg);
-}
-
-#else
-#include
-#endif /*_WIN32*/
-
-
-/*
- * Compute the greatest common divisor of a and b.
- */
-static int
-gcd(int a, int b) {
- int c;
-
- c = a % b;
- while (c != 0) {
- a = b;
- b = c;
- c = a % b;
- }
-
- return (b);
-}
-
-/*
- * Exchange the block from nonopt_start to nonopt_end with the block
- * from nonopt_end to opt_end (keeping the same order of arguments
- * in each block).
- */
-static void
-permute_args(int panonopt_start, int panonopt_end, int opt_end,
- char *const *nargv) {
-
- /*
- * compute lengths of blocks and number and size of cycles
- */
- int nnonopts = panonopt_end - panonopt_start;
- int nopts = opt_end - panonopt_end;
- int ncycle = gcd(nnonopts, nopts);
- int cyclelen = (opt_end - panonopt_start) / ncycle;
-
- for (int i = 0; i < ncycle; i++) {
- int cstart = panonopt_end + i;
- int pos = cstart;
- for (int j = 0; j < cyclelen; j++) {
- if (pos >= panonopt_end)
- pos -= nnonopts;
- else
- pos += nopts;
- char *swap = nargv[pos];
- /* LINTED const cast */
- ((char **) nargv)[pos] = nargv[cstart];
- /* LINTED const cast */
- ((char **)nargv)[cstart] = swap;
- }
- }
-}
-
-/*
- * parse_long_options --
- * Parse long options in argc/argv argument vector.
- * Returns -1 if short_too is set and the option does not match long_options.
- */
-static int
-parse_long_options(char *const *nargv, const char *options,
- const struct option *long_options, int *idx, int short_too) {
- const char *current_argv, *has_equal;
- size_t current_argv_len;
- int i, match;
-
- current_argv = place;
- match = -1;
-
- optind++;
-
- if ((has_equal = strchr(current_argv, '=')) != NULL) {
- /* argument found (--option=arg) */
- current_argv_len = has_equal - current_argv;
- has_equal++;
- } else
- current_argv_len = strlen(current_argv);
-
- for (i = 0; long_options[i].name; i++) {
- /* find matching long option */
- if (strncmp(current_argv, long_options[i].name,
- current_argv_len))
- continue;
-
- if (strlen(long_options[i].name) == current_argv_len) {
- /* exact match */
- match = i;
- break;
- }
- /*
- * If this is a known short option, don't allow
- * a partial match of a single character.
- */
- if (short_too && current_argv_len == 1)
- continue;
-
- if (match == -1) /* partial match */
- match = i;
- else {
- /* ambiguous abbreviation */
- if (PRINT_ERROR)
- warnx(ambig, (int)current_argv_len,
- current_argv);
- optopt = 0;
- return (BADCH);
- }
- }
- if (match != -1) { /* option found */
- if (long_options[match].has_arg == no_argument
- && has_equal) {
- if (PRINT_ERROR)
- warnx(noarg, (int)current_argv_len,
- current_argv);
- /*
- * XXX: GNU sets optopt to val regardless of flag
- */
- if (long_options[match].flag == NULL)
- optopt = long_options[match].val;
- else
- optopt = 0;
- return (BADARG);
- }
- if (long_options[match].has_arg == required_argument ||
- long_options[match].has_arg == optional_argument) {
- if (has_equal)
- optarg = has_equal;
- else if (long_options[match].has_arg ==
- required_argument) {
- /*
- * optional argument doesn't use next nargv
- */
- optarg = nargv[optind++];
- }
- }
- if ((long_options[match].has_arg == required_argument)
- && (optarg == NULL)) {
- /*
- * Missing argument; leading ':' indicates no error
- * should be generated.
- */
- if (PRINT_ERROR)
- warnx(recargstring,
- current_argv);
- /*
- * XXX: GNU sets optopt to val regardless of flag
- */
- if (long_options[match].flag == NULL)
- optopt = long_options[match].val;
- else
- optopt = 0;
- --optind;
- return (BADARG);
- }
- } else { /* unknown option */
- if (short_too) {
- --optind;
- return (-1);
- }
- if (PRINT_ERROR)
- warnx(illoptstring, current_argv);
- optopt = 0;
- return (BADCH);
- }
- if (idx)
- *idx = match;
- if (long_options[match].flag) {
- *long_options[match].flag = long_options[match].val;
- return (0);
- } else
- return (long_options[match].val);
-}
-
-/*
- * getopt_internal --
- * Parse argc/argv argument vector. Called by user level routines.
- */
-static int
-getopt_internal(int nargc, char *const *nargv, const char *options,
- const struct option *long_options, int *idx, int flags) {
- char *oli; /* option letter list index */
- int optchar, short_too;
- static int posixly_correct = -1;
-#ifdef __STDC_WANT_SECURE_LIB__
- char *buffer = NULL;
- size_t buffer_size = 0;
- errno_t err = 0;
-#endif
-
- if (options == NULL)
- return (-1);
-
- /*
- * Disable GNU extensions if POSIXLY_CORRECT is set or options
- * string begins with a '+'.
- */
-
-#ifdef __STDC_WANT_SECURE_LIB__
- if (posixly_correct == -1) {
- err = _dupenv_s(&buffer, &buffer_size, "POSIXLY_CORRECT") == 0;
- posixly_correct = buffer != NULL;
- if (buffer != NULL && err == 0) {
- free(buffer);
- }
- }
-#else
- if (posixly_correct == -1)
- posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
-#endif
- if (posixly_correct || *options == '+')
- flags &= ~FLAG_PERMUTE;
- else if (*options == '-')
- flags |= FLAG_ALLARGS;
- if (*options == '+' || *options == '-')
- options++;
-
- /*
- * XXX Some GNU programs (like cvs) set optind to 0 instead of
- * XXX using optreset. Work around this braindamage.
- */
- if (optind == 0)
- optind = optreset = 1;
-
- optarg = NULL;
- if (optreset)
- nonopt_start = nonopt_end = -1;
-start:
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc) { /* end of argument vector */
- place = EMSG;
- if (nonopt_end != -1) {
- /* do permutation, if we have to */
- permute_args(nonopt_start, nonopt_end,
- optind, nargv);
- optind -= nonopt_end - nonopt_start;
- } else if (nonopt_start != -1) {
- /*
- * If we skipped non-options, set optind
- * to the first of them.
- */
- optind = nonopt_start;
- }
- nonopt_start = nonopt_end = -1;
- return (-1);
- }
- if (*(place = nargv[optind]) != '-' ||
- (place[1] == '\0' && strchr(options, '-') == NULL)) {
- place = EMSG; /* found non-option */
- if (flags & FLAG_ALLARGS) {
- /*
- * GNU extension:
- * return non-option as argument to option 1
- */
- optarg = nargv[optind++];
- return (INORDER);
- }
- if (!(flags & FLAG_PERMUTE)) {
- /*
- * If no permutation wanted, stop parsing
- * at first non-option.
- */
- return (-1);
- }
- /* do permutation */
- if (nonopt_start == -1)
- nonopt_start = optind;
- else if (nonopt_end != -1) {
- permute_args(nonopt_start, nonopt_end,
- optind, nargv);
- nonopt_start = optind -
- (nonopt_end - nonopt_start);
- nonopt_end = -1;
- }
- optind++;
- /* process next argument */
- goto start;
- }
- if (nonopt_start != -1 && nonopt_end == -1)
- nonopt_end = optind;
-
- /*
- * If we have "-" do nothing, if "--" we are done.
- */
- if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
- optind++;
- place = EMSG;
- /*
- * We found an option (--), so if we skipped
- * non-options, we have to permute.
- */
- if (nonopt_end != -1) {
- permute_args(nonopt_start, nonopt_end,
- optind, nargv);
- optind -= nonopt_end - nonopt_start;
- }
- nonopt_start = nonopt_end = -1;
- return (-1);
- }
- }
-
- /*
- * Check long options if:
- * 1) we were passed some
- * 2) the arg is not just "-"
- * 3) either the arg starts with -- we are getopt_long_only()
- */
- if (long_options != NULL && place != nargv[optind] &&
- (*place == '-' || (flags & FLAG_LONGONLY))) {
- short_too = 0;
- if (*place == '-')
- place++; /* --foo long option */
- else if (*place != ':' && strchr(options, *place) != NULL)
- short_too = 1; /* could be short option too */
-
- optchar = parse_long_options(nargv, options, long_options,
- idx, short_too);
- if (optchar != -1) {
- place = EMSG;
- return (optchar);
- }
- }
-
- if ((optchar = (int) * place++) == (int)':' ||
- (optchar == (int)'-' && *place != '\0') ||
- (oli = strchr(options, optchar)) == NULL) {
- /*
- * If the user specified "-" and '-' isn't listed in
- * options, return -1 (non-option) as per POSIX.
- * Otherwise, it is an unknown option character (or ':').
- */
- if (optchar == (int)'-' && *place == '\0')
- return (-1);
- if (!*place)
- ++optind;
- if (PRINT_ERROR)
- warnx(illoptchar, optchar);
- optopt = optchar;
- return (BADCH);
- }
- if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
- /* -W long-option */
- if (*place) /* no space */
- /* NOTHING */;
- else if (++optind >= nargc) { /* no arg */
- place = EMSG;
- if (PRINT_ERROR)
- warnx(recargchar, optchar);
- optopt = optchar;
- return (BADARG);
- } else /* white space */
- place = nargv[optind];
- optchar = parse_long_options(nargv, options, long_options,
- idx, 0);
- place = EMSG;
- return (optchar);
- }
- if (*++oli != ':') { /* doesn't take argument */
- if (!*place)
- ++optind;
- } else { /* takes (optional) argument */
- optarg = NULL;
- if (*place) /* no white space */
- optarg = place;
- else if (oli[1] != ':') { /* arg not optional */
- if (++optind >= nargc) { /* no arg */
- place = EMSG;
- if (PRINT_ERROR)
- warnx(recargchar, optchar);
- optopt = optchar;
- return (BADARG);
- } else
- optarg = nargv[optind];
- }
- place = EMSG;
- ++optind;
- }
- /* dump back option letter */
- return (optchar);
-}
-
-#ifdef REPLACE_GETOPT
-/*
- * getopt --
- * Parse argc/argv argument vector.
- *
- * [eventually this will replace the BSD getopt]
- */
-int
-getopt(int nargc, char *const *nargv, const char *options) {
-
- /*
- * We don't pass FLAG_PERMUTE to getopt_internal() since
- * the BSD getopt(3) (unlike GNU) has never done this.
- *
- * Furthermore, since many privileged programs call getopt()
- * before dropping privileges it makes sense to keep things
- * as simple (and bug-free) as possible.
- */
- return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
-}
-#endif /* REPLACE_GETOPT */
-
-/*
- * getopt_long --
- * Parse argc/argv argument vector.
- */
-int
-getopt_long(int nargc, char *const *nargv, const char *options,
- const struct option *long_options, int *idx) {
-
- return (getopt_internal(nargc, nargv, options, long_options, idx,
- FLAG_PERMUTE));
-}
-
-/*
- * getopt_long_only --
- * Parse argc/argv argument vector.
- */
-int
-getopt_long_only(int nargc, char *const *nargv, const char *options,
- const struct option *long_options, int *idx) {
-
- return (getopt_internal(nargc, nargv, options, long_options, idx,
- FLAG_PERMUTE | FLAG_LONGONLY));
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-#include
-
-#include "argtable3.h"
-
-
-char *arg_strptime(const char *buf, const char *fmt, struct tm *tm);
-
-
-static void arg_date_resetfn(struct arg_date *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-
-static int arg_date_scanfn(struct arg_date *parent, const char *argval) {
- int errorcode = 0;
-
- if (parent->count == parent->hdr.maxcount) {
- errorcode = EMAXCOUNT;
- } else if (!argval) {
- /* no argument value was given, leave parent->tmval[] unaltered but still count it */
- parent->count++;
- } else {
- const char *pend;
- struct tm tm = parent->tmval[parent->count];
-
- /* parse the given argument value, store result in parent->tmval[] */
- pend = arg_strptime(argval, parent->format, &tm);
- if (pend && pend[0] == '\0')
- parent->tmval[parent->count++] = tm;
- else
- errorcode = EBADDATE;
- }
-
- ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static int arg_date_checkfn(struct arg_date *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
-
- ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static void arg_date_errorfn(
- struct arg_date *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- /* make argval NULL safe */
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (errorcode) {
- case EMINCOUNT:
- fputs("missing option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
- case EMAXCOUNT:
- fputs("excess option ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
-
- case EBADDATE: {
- struct tm tm;
- char buff[200];
-
- fprintf(fp, "illegal timestamp format \"%s\"\n", argval);
- memset(&tm, 0, sizeof(tm));
- arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm);
- strftime(buff, sizeof(buff), parent->format, &tm);
- printf("correct format is \"%s\"\n", buff);
- break;
- }
- }
-}
-
-
-struct arg_date *arg_date0(
- const char *shortopts,
- const char *longopts,
- const char *format,
- const char *datatype,
- const char *glossary) {
- return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary);
-}
-
-
-struct arg_date *arg_date1(
- const char *shortopts,
- const char *longopts,
- const char *format,
- const char *datatype,
- const char *glossary) {
- return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary);
-}
-
-
-struct arg_date *arg_daten(
- const char *shortopts,
- const char *longopts,
- const char *format,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary) {
- size_t nbytes;
- struct arg_date *result;
-
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- /* default time format is the national date format for the locale */
- if (!format)
- format = "%x";
-
- nbytes = sizeof(struct arg_date) /* storage for struct arg_date */
- + maxcount * sizeof(struct tm); /* storage for tmval[maxcount] array */
-
- /* allocate storage for the arg_date struct + tmval[] array. */
- /* we use calloc because we want the tmval[] array zero filled. */
- result = (struct arg_date *)calloc(1, nbytes);
- if (result) {
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_HASVALUE;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.datatype = datatype ? datatype : format;
- result->hdr.glossary = glossary;
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_date_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_date_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_date_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_date_errorfn;
-
- /* store the tmval[maxcount] array immediately after the arg_date struct */
- result->tmval = (struct tm *)(result + 1);
-
- /* init the remaining arg_date member variables */
- result->count = 0;
- result->format = format;
- }
-
- ARG_TRACE(("arg_daten() returns %p\n", result));
- return result;
-}
-
-
-/*-
- * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code was contributed to The NetBSD Foundation by Klaus Klein.
- * Heavily optimised by David Laight
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include
-#include
-#include
-
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define ALT_E 0x01
-#define ALT_O 0x02
-#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
-#define TM_YEAR_BASE (1900)
-
-static int conv_num(const char * *, int *, int, int);
-
-static const char *day[7] = {
- "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
- "Friday", "Saturday"
-};
-
-static const char *abday[7] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-static const char *mon[12] = {
- "January", "February", "March", "April", "May", "June", "July",
- "August", "September", "October", "November", "December"
-};
-
-static const char *abmon[12] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-static const char *am_pm[2] = {
- "AM", "PM"
-};
-
-
-static int arg_strcasecmp(const char *s1, const char *s2) {
- const unsigned char *us1 = (const unsigned char *)s1;
- const unsigned char *us2 = (const unsigned char *)s2;
- while (tolower(*us1) == tolower(*us2++))
- if (*us1++ == '\0')
- return 0;
-
- return tolower(*us1) - tolower(*--us2);
-}
-
-
-static int arg_strncasecmp(const char *s1, const char *s2, size_t n) {
- if (n != 0) {
- const unsigned char *us1 = (const unsigned char *)s1;
- const unsigned char *us2 = (const unsigned char *)s2;
- do {
- if (tolower(*us1) != tolower(*us2++))
- return tolower(*us1) - tolower(*--us2);
-
- if (*us1++ == '\0')
- break;
- } while (--n != 0);
- }
-
- return 0;
-}
-
-
-char *arg_strptime(const char *buf, const char *fmt, struct tm *tm) {
- char c;
- const char *bp;
- size_t len = 0;
- int alt_format, i, split_year = 0;
-
- bp = buf;
-
- while ((c = *fmt) != '\0') {
- /* Clear `alternate' modifier prior to new conversion. */
- alt_format = 0;
-
- /* Eat up white-space. */
- if (ISSPACE(c)) {
- while (ISSPACE(*bp))
- bp++;
-
- fmt++;
- continue;
- }
-
- if ((c = *fmt++) != '%')
- goto literal;
-
-
-again:
- switch (c = *fmt++) {
- case '%': /* "%%" is converted to "%". */
-literal:
- if (c != *bp++)
- return (0);
- break;
-
- /*
- * "Alternative" modifiers. Just set the appropriate flag
- * and start over again.
- */
- case 'E': /* "%E?" alternative conversion modifier. */
- LEGAL_ALT(0);
- alt_format |= ALT_E;
- goto again;
-
- case 'O': /* "%O?" alternative conversion modifier. */
- LEGAL_ALT(0);
- alt_format |= ALT_O;
- goto again;
-
- /*
- * "Complex" conversion rules, implemented through recursion.
- */
- case 'c': /* Date and time, using the locale's format. */
- LEGAL_ALT(ALT_E);
- bp = arg_strptime(bp, "%x %X", tm);
- if (!bp)
- return (0);
- break;
-
- case 'D': /* The date as "%m/%d/%y". */
- LEGAL_ALT(0);
- bp = arg_strptime(bp, "%m/%d/%y", tm);
- if (!bp)
- return (0);
- break;
-
- case 'R': /* The time as "%H:%M". */
- LEGAL_ALT(0);
- bp = arg_strptime(bp, "%H:%M", tm);
- if (!bp)
- return (0);
- break;
-
- case 'r': /* The time in 12-hour clock representation. */
- LEGAL_ALT(0);
- bp = arg_strptime(bp, "%I:%M:%S %p", tm);
- if (!bp)
- return (0);
- break;
-
- case 'T': /* The time as "%H:%M:%S". */
- LEGAL_ALT(0);
- bp = arg_strptime(bp, "%H:%M:%S", tm);
- if (!bp)
- return (0);
- break;
-
- case 'X': /* The time, using the locale's format. */
- LEGAL_ALT(ALT_E);
- bp = arg_strptime(bp, "%H:%M:%S", tm);
- if (!bp)
- return (0);
- break;
-
- case 'x': /* The date, using the locale's format. */
- LEGAL_ALT(ALT_E);
- bp = arg_strptime(bp, "%m/%d/%y", tm);
- if (!bp)
- return (0);
- break;
-
- /*
- * "Elementary" conversion rules.
- */
- case 'A': /* The day of week, using the locale's form. */
- case 'a':
- LEGAL_ALT(0);
- for (i = 0; i < 7; i++) {
- /* Full name. */
- len = strlen(day[i]);
- if (arg_strncasecmp(day[i], bp, len) == 0)
- break;
-
- /* Abbreviated name. */
- len = strlen(abday[i]);
- if (arg_strncasecmp(abday[i], bp, len) == 0)
- break;
- }
-
- /* Nothing matched. */
- if (i == 7)
- return (0);
-
- tm->tm_wday = i;
- bp += len;
- break;
-
- case 'B': /* The month, using the locale's form. */
- case 'b':
- case 'h':
- LEGAL_ALT(0);
- for (i = 0; i < 12; i++) {
- /* Full name. */
- len = strlen(mon[i]);
- if (arg_strncasecmp(mon[i], bp, len) == 0)
- break;
-
- /* Abbreviated name. */
- len = strlen(abmon[i]);
- if (arg_strncasecmp(abmon[i], bp, len) == 0)
- break;
- }
-
- /* Nothing matched. */
- if (i == 12)
- return (0);
-
- tm->tm_mon = i;
- bp += len;
- break;
-
- case 'C': /* The century number. */
- LEGAL_ALT(ALT_E);
- if (!(conv_num(&bp, &i, 0, 99)))
- return (0);
-
- if (split_year) {
- tm->tm_year = (tm->tm_year % 100) + (i * 100);
- } else {
- tm->tm_year = i * 100;
- split_year = 1;
- }
- break;
-
- case 'd': /* The day of month. */
- case 'e':
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
- return (0);
- break;
-
- case 'k': /* The hour (24-hour clock representation). */
- LEGAL_ALT(0);
- /* FALLTHROUGH */
- case 'H':
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
- return (0);
- break;
-
- case 'l': /* The hour (12-hour clock representation). */
- LEGAL_ALT(0);
- /* FALLTHROUGH */
- case 'I':
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
- return (0);
- if (tm->tm_hour == 12)
- tm->tm_hour = 0;
- break;
-
- case 'j': /* The day of year. */
- LEGAL_ALT(0);
- if (!(conv_num(&bp, &i, 1, 366)))
- return (0);
- tm->tm_yday = i - 1;
- break;
-
- case 'M': /* The minute. */
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
- return (0);
- break;
-
- case 'm': /* The month. */
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &i, 1, 12)))
- return (0);
- tm->tm_mon = i - 1;
- break;
-
- case 'p': /* The locale's equivalent of AM/PM. */
- LEGAL_ALT(0);
- /* AM? */
- if (arg_strcasecmp(am_pm[0], bp) == 0) {
- if (tm->tm_hour > 11)
- return (0);
-
- bp += strlen(am_pm[0]);
- break;
- }
- /* PM? */
- else if (arg_strcasecmp(am_pm[1], bp) == 0) {
- if (tm->tm_hour > 11)
- return (0);
-
- tm->tm_hour += 12;
- bp += strlen(am_pm[1]);
- break;
- }
-
- /* Nothing matched. */
- return (0);
-
- case 'S': /* The seconds. */
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
- return (0);
- break;
-
- case 'U': /* The week of year, beginning on sunday. */
- case 'W': /* The week of year, beginning on monday. */
- LEGAL_ALT(ALT_O);
- /*
- * XXX This is bogus, as we can not assume any valid
- * information present in the tm structure at this
- * point to calculate a real value, so just check the
- * range for now.
- */
- if (!(conv_num(&bp, &i, 0, 53)))
- return (0);
- break;
-
- case 'w': /* The day of week, beginning on sunday. */
- LEGAL_ALT(ALT_O);
- if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
- return (0);
- break;
-
- case 'Y': /* The year. */
- LEGAL_ALT(ALT_E);
- if (!(conv_num(&bp, &i, 0, 9999)))
- return (0);
-
- tm->tm_year = i - TM_YEAR_BASE;
- break;
-
- case 'y': /* The year within 100 years of the epoch. */
- LEGAL_ALT(ALT_E | ALT_O);
- if (!(conv_num(&bp, &i, 0, 99)))
- return (0);
-
- if (split_year) {
- tm->tm_year = ((tm->tm_year / 100) * 100) + i;
- break;
- }
- split_year = 1;
- if (i <= 68)
- tm->tm_year = i + 2000 - TM_YEAR_BASE;
- else
- tm->tm_year = i + 1900 - TM_YEAR_BASE;
- break;
-
- /*
- * Miscellaneous conversions.
- */
- case 'n': /* Any kind of white-space. */
- case 't':
- LEGAL_ALT(0);
- while (ISSPACE(*bp))
- bp++;
- break;
-
-
- default: /* Unknown/unsupported conversion. */
- return (0);
- }
-
-
- }
-
- /* LINTED functional specification */
- return ((char *)bp);
-}
-
-
-static int conv_num(const char * *buf, int *dest, int llim, int ulim) {
- int result = 0;
-
- /* The limit also determines the number of valid digits. */
- int rulim = ulim;
-
- if (**buf < '0' || **buf > '9')
- return (0);
-
- do {
- result *= 10;
- result += *(*buf)++ - '0';
- rulim /= 10;
- } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
-
- if (result < llim || result > ulim)
- return (0);
-
- *dest = result;
- return (1);
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-
-#include "argtable3.h"
-
-
-static void arg_dbl_resetfn(struct arg_dbl *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-
-static int arg_dbl_scanfn(struct arg_dbl *parent, const char *argval) {
- int errorcode = 0;
-
- if (parent->count == parent->hdr.maxcount) {
- /* maximum number of arguments exceeded */
- errorcode = EMAXCOUNT;
- } else if (!argval) {
- /* a valid argument with no argument value was given. */
- /* This happens when an optional argument value was invoked. */
- /* leave parent argument value unaltered but still count the argument. */
- parent->count++;
- } else {
- double val;
- char *end;
-
- /* extract double from argval into val */
- val = strtod(argval, &end);
-
- /* if success then store result in parent->dval[] array otherwise return error*/
- if (*end == 0)
- parent->dval[parent->count++] = val;
- else
- errorcode = EBADDOUBLE;
- }
-
- ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static int arg_dbl_checkfn(struct arg_dbl *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
-
- ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static void arg_dbl_errorfn(
- struct arg_dbl *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- /* make argval NULL safe */
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (errorcode) {
- case EMINCOUNT:
- fputs("missing option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
- case EMAXCOUNT:
- fputs("excess option ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
-
- case EBADDOUBLE:
- fprintf(fp, "invalid argument \"%s\" to option ", argval);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
- }
-}
-
-
-struct arg_dbl *arg_dbl0(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary);
-}
-
-
-struct arg_dbl *arg_dbl1(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary);
-}
-
-
-struct arg_dbl *arg_dbln(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary) {
- size_t nbytes;
- struct arg_dbl *result;
-
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- nbytes = sizeof(struct arg_dbl) /* storage for struct arg_dbl */
- + (maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */
-
- result = (struct arg_dbl *)malloc(nbytes);
- if (result) {
- size_t addr;
- size_t rem;
-
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_HASVALUE;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.datatype = datatype ? datatype : "";
- result->hdr.glossary = glossary;
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_dbl_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_dbl_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_dbl_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_dbl_errorfn;
-
- /* Store the dval[maxcount] array on the first double boundary that
- * immediately follows the arg_dbl struct. We do the memory alignment
- * purely for SPARC and Motorola systems. They require floats and
- * doubles to be aligned on natural boundaries.
- */
- addr = (size_t)(result + 1);
- rem = addr % sizeof(double);
- result->dval = (double *)(addr + sizeof(double) - rem);
- ARG_TRACE(("addr=%zu, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem));
-
- result->count = 0;
- }
-
- ARG_TRACE(("arg_dbln() returns %p\n", result));
- return result;
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-
-#include "argtable3.h"
-
-
-static void arg_end_resetfn(struct arg_end *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-static void arg_end_errorfn(
- void *parent,
- FILE *fp,
- int error,
- const char *argval,
- const char *progname) {
- /* suppress unreferenced formal parameter warning */
- (void)parent;
-
- progname = progname ? progname : "";
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (error) {
- case ARG_ELIMIT:
- fputs("too many errors to display", fp);
- break;
- case ARG_EMALLOC:
- fputs("insufficent memory", fp);
- break;
- case ARG_ENOMATCH:
- fprintf(fp, "unexpected argument \"%s\"", argval);
- break;
- case ARG_EMISSARG:
- fprintf(fp, "option \"%s\" requires an argument", argval);
- break;
- case ARG_ELONGOPT:
- fprintf(fp, "invalid option \"%s\"", argval);
- break;
- default:
- fprintf(fp, "invalid option \"-%c\"", error);
- break;
- }
-
- fputc('\n', fp);
-}
-
-
-struct arg_end *arg_end(int maxcount) {
- size_t nbytes;
- struct arg_end *result;
-
- nbytes = sizeof(struct arg_end)
- + maxcount * sizeof(int) /* storage for int error[maxcount] array*/
- + maxcount * sizeof(void *) /* storage for void* parent[maxcount] array */
- + maxcount * sizeof(char *); /* storage for char* argval[maxcount] array */
-
- result = (struct arg_end *)malloc(nbytes);
- if (result) {
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_TERMINATOR;
- result->hdr.shortopts = NULL;
- result->hdr.longopts = NULL;
- result->hdr.datatype = NULL;
- result->hdr.glossary = NULL;
- result->hdr.mincount = 1;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_end_resetfn;
- result->hdr.scanfn = NULL;
- result->hdr.checkfn = NULL;
- result->hdr.errorfn = (arg_errorfn *)arg_end_errorfn;
-
- /* store error[maxcount] array immediately after struct arg_end */
- result->error = (int *)(result + 1);
-
- /* store parent[maxcount] array immediately after error[] array */
- result->parent = (void * *)(result->error + maxcount);
-
- /* store argval[maxcount] array immediately after parent[] array */
- result->argval = (const char * *)(result->parent + maxcount);
- }
-
- ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result));
- return result;
-}
-
-
-void arg_print_errors(FILE *fp, struct arg_end *end, const char *progname) {
- int i;
- ARG_TRACE(("arg_errors()\n"));
- for (i = 0; i < end->count; i++) {
- struct arg_hdr *errorparent = (struct arg_hdr *)(end->parent[i]);
- if (errorparent->errorfn)
- errorparent->errorfn(end->parent[i],
- fp,
- end->error[i],
- end->argval[i],
- progname);
- }
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-#include
-
-#include "argtable3.h"
-
-#ifdef WIN32
-# define FILESEPARATOR1 '\\'
-# define FILESEPARATOR2 '/'
-#else
-# define FILESEPARATOR1 '/'
-# define FILESEPARATOR2 '/'
-#endif
-
-
-static void arg_file_resetfn(struct arg_file *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-
-/* Returns ptr to the base filename within *filename */
-static const char *arg_basename(const char *filename) {
- const char *result = NULL, *result1, *result2;
-
- /* Find the last occurrence of eother file separator character. */
- /* Two alternative file separator chars are supported as legal */
- /* file separators but not both together in the same filename. */
- result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL);
- result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL);
-
- if (result2)
- result = result2 + 1; /* using FILESEPARATOR2 (the alternative file separator) */
-
- if (result1)
- result = result1 + 1; /* using FILESEPARATOR1 (the preferred file separator) */
-
- if (!result)
- result = filename; /* neither file separator was found so basename is the whole filename */
-
- /* special cases of "." and ".." are not considered basenames */
- if (result && (strcmp(".", result) == 0 || strcmp("..", result) == 0))
- result = filename + strlen(filename);
-
- return result;
-}
-
-
-/* Returns ptr to the file extension within *basename */
-static const char *arg_extension(const char *basename) {
- /* find the last occurrence of '.' in basename */
- const char *result = (basename ? strrchr(basename, '.') : NULL);
-
- /* if no '.' was found then return pointer to end of basename */
- if (basename && !result)
- result = basename + strlen(basename);
-
- /* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */
- if (basename && result == basename)
- result = basename + strlen(basename);
-
- /* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */
- if (basename && result && result[1] == '\0')
- result = basename + strlen(basename);
-
- return result;
-}
-
-
-static int arg_file_scanfn(struct arg_file *parent, const char *argval) {
- int errorcode = 0;
-
- if (parent->count == parent->hdr.maxcount) {
- /* maximum number of arguments exceeded */
- errorcode = EMAXCOUNT;
- } else if (!argval) {
- /* a valid argument with no argument value was given. */
- /* This happens when an optional argument value was invoked. */
- /* leave parent arguiment value unaltered but still count the argument. */
- parent->count++;
- } else {
- parent->filename[parent->count] = argval;
- parent->basename[parent->count] = arg_basename(argval);
- parent->extension[parent->count] =
- arg_extension(parent->basename[parent->count]); /* only seek extensions within the basename (not the file path)*/
- parent->count++;
- }
-
- ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static int arg_file_checkfn(struct arg_file *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
-
- ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static void arg_file_errorfn(
- struct arg_file *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- /* make argval NULL safe */
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (errorcode) {
- case EMINCOUNT:
- fputs("missing option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
- case EMAXCOUNT:
- fputs("excess option ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
-
- default:
- fprintf(fp, "unknown error at \"%s\"\n", argval);
- }
-}
-
-
-struct arg_file *arg_file0(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_filen(shortopts, longopts, datatype, 0, 1, glossary);
-}
-
-
-struct arg_file *arg_file1(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_filen(shortopts, longopts, datatype, 1, 1, glossary);
-}
-
-
-struct arg_file *arg_filen(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary) {
- size_t nbytes;
- struct arg_file *result;
-
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- nbytes = sizeof(struct arg_file) /* storage for struct arg_file */
- + sizeof(char *) * maxcount /* storage for filename[maxcount] array */
- + sizeof(char *) * maxcount /* storage for basename[maxcount] array */
- + sizeof(char *) * maxcount; /* storage for extension[maxcount] array */
-
- result = (struct arg_file *)malloc(nbytes);
- if (result) {
- int i;
-
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_HASVALUE;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.glossary = glossary;
- result->hdr.datatype = datatype ? datatype : "";
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_file_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_file_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_file_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_file_errorfn;
-
- /* store the filename,basename,extension arrays immediately after the arg_file struct */
- result->filename = (const char * *)(result + 1);
- result->basename = result->filename + maxcount;
- result->extension = result->basename + maxcount;
- result->count = 0;
-
- /* foolproof the string pointers by initialising them with empty strings */
- for (i = 0; i < maxcount; i++) {
- result->filename[i] = "";
- result->basename[i] = "";
- result->extension[i] = "";
- }
- }
-
- ARG_TRACE(("arg_filen() returns %p\n", result));
- return result;
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-#include
-#include
-
-#include "argtable3.h"
-
-
-static void arg_int_resetfn(struct arg_int *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-
-/* strtol0x() is like strtol() except that the numeric string is */
-/* expected to be prefixed by "0X" where X is a user supplied char. */
-/* The string may optionally be prefixed by white space and + or - */
-/* as in +0X123 or -0X123. */
-/* Once the prefix has been scanned, the remainder of the numeric */
-/* string is converted using strtol() with the given base. */
-/* eg: to parse hex str="-0X12324", specify X='X' and base=16. */
-/* eg: to parse oct str="+0o12324", specify X='O' and base=8. */
-/* eg: to parse bin str="-0B01010", specify X='B' and base=2. */
-/* Failure of conversion is indicated by result where *endptr==str. */
-static long int strtol0X(const char *str,
- const char * *endptr,
- char X,
- int base) {
- long int val; /* stores result */
- int s = 1; /* sign is +1 or -1 */
- const char *ptr = str; /* ptr to current position in str */
-
- /* skip leading whitespace */
- while (ISSPACE(*ptr))
- ptr++;
- /* printf("1) %s\n",ptr); */
-
- /* scan optional sign character */
- switch (*ptr) {
- case '+':
- ptr++;
- s = 1;
- break;
- case '-':
- ptr++;
- s = -1;
- break;
- default:
- s = 1;
- break;
- }
- /* printf("2) %s\n",ptr); */
-
- /* '0X' prefix */
- if ((*ptr++) != '0') {
- /* printf("failed to detect '0'\n"); */
- *endptr = str;
- return 0;
- }
- /* printf("3) %s\n",ptr); */
- if (toupper(*ptr++) != toupper(X)) {
- /* printf("failed to detect '%c'\n",X); */
- *endptr = str;
- return 0;
- }
- /* printf("4) %s\n",ptr); */
-
- /* attempt conversion on remainder of string using strtol() */
- val = strtol(ptr, (char * *)endptr, base);
- if (*endptr == ptr) {
- /* conversion failed */
- *endptr = str;
- return 0;
- }
-
- /* success */
- return s * val;
-}
-
-
-/* Returns 1 if str matches suffix (case insensitive). */
-/* Str may contain trailing whitespace, but nothing else. */
-static int detectsuffix(const char *str, const char *suffix) {
- /* scan pairwise through strings until mismatch detected */
- while (toupper(*str) == toupper(*suffix)) {
- /* printf("'%c' '%c'\n", *str, *suffix); */
-
- /* return 1 (success) if match persists until the string terminator */
- if (*str == '\0')
- return 1;
-
- /* next chars */
- str++;
- suffix++;
- }
- /* printf("'%c' '%c' mismatch\n", *str, *suffix); */
-
- /* return 0 (fail) if the matching did not consume the entire suffix */
- if (*suffix != 0)
- return 0; /* failed to consume entire suffix */
-
- /* skip any remaining whitespace in str */
- while (ISSPACE(*str))
- str++;
-
- /* return 1 (success) if we have reached end of str else return 0 (fail) */
- return (*str == '\0') ? 1 : 0;
-}
-
-
-static int arg_int_scanfn(struct arg_int *parent, const char *argval) {
- int errorcode = 0;
-
- if (parent->count == parent->hdr.maxcount) {
- /* maximum number of arguments exceeded */
- errorcode = EMAXCOUNT;
- } else if (!argval) {
- /* a valid argument with no argument value was given. */
- /* This happens when an optional argument value was invoked. */
- /* leave parent arguiment value unaltered but still count the argument. */
- parent->count++;
- } else {
- long int val;
- const char *end;
-
- /* attempt to extract hex integer (eg: +0x123) from argval into val conversion */
- val = strtol0X(argval, &end, 'X', 16);
- if (end == argval) {
- /* hex failed, attempt octal conversion (eg +0o123) */
- val = strtol0X(argval, &end, 'O', 8);
- if (end == argval) {
- /* octal failed, attempt binary conversion (eg +0B101) */
- val = strtol0X(argval, &end, 'B', 2);
- if (end == argval) {
- /* binary failed, attempt decimal conversion with no prefix (eg 1234) */
- val = strtol(argval, (char * *)&end, 10);
- if (end == argval) {
- /* all supported number formats failed */
- return EBADINT;
- }
- }
- }
- }
-
- /* Safety check for integer overflow. WARNING: this check */
- /* achieves nothing on machines where size(int)==size(long). */
- if (val > INT_MAX || val < INT_MIN)
-#ifdef __STDC_WANT_SECURE_LIB__
- errorcode = EOVERFLOW_;
-#else
- errorcode = EOVERFLOW;
-#endif
-
- /* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */
- /* We need to be mindful of integer overflows when using such big numbers. */
- if (detectsuffix(end, "KB")) { /* kilobytes */
- if (val > (INT_MAX / 1024) || val < (INT_MIN / 1024))
-#ifdef __STDC_WANT_SECURE_LIB__
- errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */
-#else
- errorcode = EOVERFLOW; /* Overflow would occur if we proceed */
-#endif
- else
- val *= 1024; /* 1KB = 1024 */
- } else if (detectsuffix(end, "MB")) { /* megabytes */
- if (val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576))
-#ifdef __STDC_WANT_SECURE_LIB__
- errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */
-#else
- errorcode = EOVERFLOW; /* Overflow would occur if we proceed */
-#endif
- else
- val *= 1048576; /* 1MB = 1024*1024 */
- } else if (detectsuffix(end, "GB")) { /* gigabytes */
- if (val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824))
-#ifdef __STDC_WANT_SECURE_LIB__
- errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */
-#else
- errorcode = EOVERFLOW; /* Overflow would occur if we proceed */
-#endif
- else
- val *= 1073741824; /* 1GB = 1024*1024*1024 */
- } else if (!detectsuffix(end, ""))
- errorcode = EBADINT; /* invalid suffix detected */
-
- /* if success then store result in parent->ival[] array */
- if (errorcode == 0)
- parent->ival[parent->count++] = val;
- }
-
- /* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */
- return errorcode;
-}
-
-
-static int arg_int_checkfn(struct arg_int *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
- /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
- return errorcode;
-}
-
-
-static void arg_int_errorfn(
- struct arg_int *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- /* make argval NULL safe */
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (errorcode) {
- case EMINCOUNT:
- fputs("missing option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
- case EMAXCOUNT:
- fputs("excess option ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
-
- case EBADINT:
- fprintf(fp, "invalid argument \"%s\" to option ", argval);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
-#ifdef __STDC_WANT_SECURE_LIB__
- case EOVERFLOW_:
-#else
- case EOVERFLOW:
-#endif
- fputs("integer overflow at option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, " ");
- fprintf(fp, "(%s is too large)\n", argval);
- break;
- }
-}
-
-
-struct arg_int *arg_int0(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_intn(shortopts, longopts, datatype, 0, 1, glossary);
-}
-
-
-struct arg_int *arg_int1(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_intn(shortopts, longopts, datatype, 1, 1, glossary);
-}
-
-
-struct arg_int *arg_intn(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary) {
- size_t nbytes;
- struct arg_int *result;
-
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- nbytes = sizeof(struct arg_int) /* storage for struct arg_int */
- + maxcount * sizeof(int); /* storage for ival[maxcount] array */
-
- result = (struct arg_int *)malloc(nbytes);
- if (result) {
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_HASVALUE;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.datatype = datatype ? datatype : "";
- result->hdr.glossary = glossary;
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_int_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_int_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_int_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_int_errorfn;
-
- /* store the ival[maxcount] array immediately after the arg_int struct */
- result->ival = (int *)(result + 1);
- result->count = 0;
- }
-
- ARG_TRACE(("arg_intn() returns %p\n", result));
- return result;
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-
-#include "argtable3.h"
-
-
-static void arg_lit_resetfn(struct arg_lit *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-
-static int arg_lit_scanfn(struct arg_lit *parent, const char *argval) {
- int errorcode = 0;
- if (parent->count < parent->hdr.maxcount)
- parent->count++;
- else
- errorcode = EMAXCOUNT;
-
- ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval,
- errorcode));
- return errorcode;
-}
-
-
-static int arg_lit_checkfn(struct arg_lit *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
- ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static void arg_lit_errorfn(
- struct arg_lit *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- switch (errorcode) {
- case EMINCOUNT:
- fprintf(fp, "%s: missing option ", progname);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- fprintf(fp, "\n");
- break;
-
- case EMAXCOUNT:
- fprintf(fp, "%s: extraneous option ", progname);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
- }
-
- ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, fp,
- errorcode, argval, progname));
-}
-
-
-struct arg_lit *arg_lit0(
- const char *shortopts,
- const char *longopts,
- const char *glossary) {
- return arg_litn(shortopts, longopts, 0, 1, glossary);
-}
-
-
-struct arg_lit *arg_lit1(
- const char *shortopts,
- const char *longopts,
- const char *glossary) {
- return arg_litn(shortopts, longopts, 1, 1, glossary);
-}
-
-
-struct arg_lit *arg_litn(
- const char *shortopts,
- const char *longopts,
- int mincount,
- int maxcount,
- const char *glossary) {
- struct arg_lit *result;
-
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- result = (struct arg_lit *)malloc(sizeof(struct arg_lit));
- if (result) {
- /* init the arg_hdr struct */
- result->hdr.flag = 0;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.datatype = NULL;
- result->hdr.glossary = glossary;
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_lit_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_lit_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_lit_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_lit_errorfn;
-
- /* init local variables */
- result->count = 0;
- }
-
- ARG_TRACE(("arg_litn() returns %p\n", result));
- return result;
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-
-#include "argtable3.h"
-
-struct arg_rem *arg_rem(const char *datatype, const char *glossary) {
- struct arg_rem *result = (struct arg_rem *)malloc(sizeof(struct arg_rem));
- if (result) {
- result->hdr.flag = 0;
- result->hdr.shortopts = NULL;
- result->hdr.longopts = NULL;
- result->hdr.datatype = datatype;
- result->hdr.glossary = glossary;
- result->hdr.mincount = 1;
- result->hdr.maxcount = 1;
- result->hdr.parent = result;
- result->hdr.resetfn = NULL;
- result->hdr.scanfn = NULL;
- result->hdr.checkfn = NULL;
- result->hdr.errorfn = NULL;
- }
-
- ARG_TRACE(("arg_rem() returns %p\n", result));
- return result;
-}
-
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-#include
-
-#include "argtable3.h"
-
-
-#ifndef _TREX_H_
-#define _TREX_H_
-/***************************************************************
- T-Rex a tiny regular expression library
-
- Copyright (C) 2003-2006 Alberto Demichelis
-
- This software is provided 'as-is', without any express
- or implied warranty. In no event will the authors be held
- liable for any damages arising from the use of this software.
-
- Permission is granted to anyone to use this software for
- any purpose, including commercial applications, and to alter
- it and redistribute it freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented;
- you must not claim that you wrote the original software.
- If you use this software in a product, an acknowledgment
- in the product documentation would be appreciated but
- is not required.
-
- 2. Altered source versions must be plainly marked as such,
- and must not be misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any
- source distribution.
-
-****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _UNICODE
-#define TRexChar unsigned short
-#define MAX_CHAR 0xFFFF
-#define _TREXC(c) L##c
-#define trex_strlen wcslen
-#define trex_printf wprintf
-#else
-#define TRexChar char
-#define MAX_CHAR 0xFF
-#define _TREXC(c) (c)
-#define trex_strlen strlen
-#define trex_printf printf
-#endif
-
-#ifndef TREX_API
-#define TREX_API extern
-#endif
-
-#define TRex_True 1
-#define TRex_False 0
-
-#define TREX_ICASE ARG_REX_ICASE
-
-typedef unsigned int TRexBool;
-typedef struct TRex TRex;
-
-typedef struct {
- const TRexChar *begin;
- int len;
-} TRexMatch;
-
-TREX_API TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags);
-TREX_API void trex_free(TRex *exp);
-TREX_API TRexBool trex_match(TRex *exp, const TRexChar *text);
-TREX_API TRexBool trex_search(TRex *exp, const TRexChar *text, const TRexChar **out_begin, const TRexChar **out_end);
-TREX_API TRexBool trex_searchrange(TRex *exp, const TRexChar *text_begin, const TRexChar *text_end, const TRexChar **out_begin, const TRexChar **out_end);
-TREX_API int trex_getsubexpcount(TRex *exp);
-TREX_API TRexBool trex_getsubexp(TRex *exp, int n, TRexMatch *subexp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
-struct privhdr {
- const char *pattern;
- int flags;
-};
-
-
-static void arg_rex_resetfn(struct arg_rex *parent) {
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
-}
-
-static int arg_rex_scanfn(struct arg_rex *parent, const char *argval) {
- int errorcode = 0;
- const TRexChar *error = NULL;
- TRex *rex = NULL;
- TRexBool is_match;
-
- if (parent->count == parent->hdr.maxcount) {
- /* maximum number of arguments exceeded */
- errorcode = EMAXCOUNT;
- } else if (!argval) {
- /* a valid argument with no argument value was given. */
- /* This happens when an optional argument value was invoked. */
- /* leave parent argument value unaltered but still count the argument. */
- parent->count++;
- } else {
- struct privhdr *priv = (struct privhdr *)parent->hdr.priv;
-
- /* test the current argument value for a match with the regular expression */
- /* if a match is detected, record the argument value in the arg_rex struct */
-
- rex = trex_compile(priv->pattern, &error, priv->flags);
- is_match = trex_match(rex, argval);
- if (!is_match)
- errorcode = EREGNOMATCH;
- else
- parent->sval[parent->count++] = argval;
-
- trex_free(rex);
- }
-
- ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-static int arg_rex_checkfn(struct arg_rex *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
- //struct privhdr *priv = (struct privhdr*)parent->hdr.priv;
-
- /* free the regex "program" we constructed in resetfn */
- //regfree(&(priv->regex));
-
- /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
- return errorcode;
-}
-
-static void arg_rex_errorfn(struct arg_rex *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- /* make argval NULL safe */
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (errorcode) {
- case EMINCOUNT:
- fputs("missing option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
- case EMAXCOUNT:
- fputs("excess option ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
-
- case EREGNOMATCH:
- fputs("illegal value ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
-
- default: {
- //char errbuff[256];
- //regerror(errorcode, NULL, errbuff, sizeof(errbuff));
- //printf("%s\n", errbuff);
- }
- break;
- }
-}
-
-
-struct arg_rex *arg_rex0(const char *shortopts,
- const char *longopts,
- const char *pattern,
- const char *datatype,
- int flags,
- const char *glossary) {
- return arg_rexn(shortopts,
- longopts,
- pattern,
- datatype,
- 0,
- 1,
- flags,
- glossary);
-}
-
-struct arg_rex *arg_rex1(const char *shortopts,
- const char *longopts,
- const char *pattern,
- const char *datatype,
- int flags,
- const char *glossary) {
- return arg_rexn(shortopts,
- longopts,
- pattern,
- datatype,
- 1,
- 1,
- flags,
- glossary);
-}
-
-
-struct arg_rex *arg_rexn(const char *shortopts,
- const char *longopts,
- const char *pattern,
- const char *datatype,
- int mincount,
- int maxcount,
- int flags,
- const char *glossary) {
- size_t nbytes;
- struct arg_rex *result;
- struct privhdr *priv;
- int i;
- const TRexChar *error = NULL;
- TRex *rex = NULL;
-
- if (!pattern) {
- printf(
- "argtable: ERROR - illegal regular expression pattern \"(NULL)\"\n");
- printf("argtable: Bad argument table.\n");
- return NULL;
- }
-
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- nbytes = sizeof(struct arg_rex) /* storage for struct arg_rex */
- + sizeof(struct privhdr) /* storage for private arg_rex data */
- + maxcount * sizeof(char *); /* storage for sval[maxcount] array */
-
- result = (struct arg_rex *)malloc(nbytes);
- if (result == NULL)
- return result;
-
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_HASVALUE;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.datatype = datatype ? datatype : pattern;
- result->hdr.glossary = glossary;
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_rex_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_rex_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_rex_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_rex_errorfn;
-
- /* store the arg_rex_priv struct immediately after the arg_rex struct */
- result->hdr.priv = result + 1;
- priv = (struct privhdr *)(result->hdr.priv);
- priv->pattern = pattern;
- priv->flags = flags;
-
- /* store the sval[maxcount] array immediately after the arg_rex_priv struct */
- result->sval = (const char * *)(priv + 1);
- result->count = 0;
-
- /* foolproof the string pointers by initializing them to reference empty strings */
- for (i = 0; i < maxcount; i++)
- result->sval[i] = "";
-
- /* here we construct and destroy a regex representation of the regular
- * expression for no other reason than to force any regex errors to be
- * trapped now rather than later. If we don't, then errors may go undetected
- * until an argument is actually parsed.
- */
-
- rex = trex_compile(priv->pattern, &error, priv->flags);
- if (rex == NULL) {
- ARG_LOG(("argtable: %s \"%s\"\n", error ? error : _TREXC("undefined"), priv->pattern));
- ARG_LOG(("argtable: Bad argument table.\n"));
- }
-
- trex_free(rex);
-
- ARG_TRACE(("arg_rexn() returns %p\n", result));
- return result;
-}
-
-
-
-/* see copyright notice in trex.h */
-#include
-#include
-#include
-#include
-
-#ifdef _UINCODE
-#define scisprint iswprint
-#define scstrlen wcslen
-#define scprintf wprintf
-#define _SC(x) L(x)
-#else
-#define scisprint isprint
-#define scstrlen strlen
-#define scprintf printf
-#define _SC(x) (x)
-#endif
-
-#ifdef _DEBUG
-#include
-
-static const TRexChar *g_nnames[] = {
- _SC("NONE"), _SC("OP_GREEDY"), _SC("OP_OR"),
- _SC("OP_EXPR"), _SC("OP_NOCAPEXPR"), _SC("OP_DOT"), _SC("OP_CLASS"),
- _SC("OP_CCLASS"), _SC("OP_NCLASS"), _SC("OP_RANGE"), _SC("OP_CHAR"),
- _SC("OP_EOL"), _SC("OP_BOL"), _SC("OP_WB")
-};
-
-#endif
-#define OP_GREEDY (MAX_CHAR+1) // * + ? {n}
-#define OP_OR (MAX_CHAR+2)
-#define OP_EXPR (MAX_CHAR+3) //parentesis ()
-#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:)
-#define OP_DOT (MAX_CHAR+5)
-#define OP_CLASS (MAX_CHAR+6)
-#define OP_CCLASS (MAX_CHAR+7)
-#define OP_NCLASS (MAX_CHAR+8) //negates class the [^
-#define OP_RANGE (MAX_CHAR+9)
-#define OP_CHAR (MAX_CHAR+10)
-#define OP_EOL (MAX_CHAR+11)
-#define OP_BOL (MAX_CHAR+12)
-#define OP_WB (MAX_CHAR+13)
-
-#define TREX_SYMBOL_ANY_CHAR ('.')
-#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
-#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
-#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
-#define TREX_SYMBOL_BRANCH ('|')
-#define TREX_SYMBOL_END_OF_STRING ('$')
-#define TREX_SYMBOL_BEGINNING_OF_STRING ('^')
-#define TREX_SYMBOL_ESCAPE_CHAR ('\\')
-
-
-typedef int TRexNodeType;
-
-typedef struct tagTRexNode {
- TRexNodeType type;
- int left;
- int right;
- int next;
-} TRexNode;
-
-struct TRex {
- const TRexChar *_eol;
- const TRexChar *_bol;
- const TRexChar *_p;
- int _first;
- int _op;
- TRexNode *_nodes;
- int _nallocated;
- int _nsize;
- int _nsubexpr;
- TRexMatch *_matches;
- int _currsubexp;
- void *_jmpbuf;
- const TRexChar **_error;
- int _flags;
-};
-
-static int trex_list(TRex *exp);
-
-static int trex_newnode(TRex *exp, TRexNodeType type) {
- TRexNode n;
- int newid;
- n.type = type;
- n.next = n.right = n.left = -1;
- if (type == OP_EXPR)
- n.right = exp->_nsubexpr++;
- if (exp->_nallocated < (exp->_nsize + 1)) {
- exp->_nallocated *= 2;
- exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode));
- }
- exp->_nodes[exp->_nsize++] = n;
- newid = exp->_nsize - 1;
- return (int)newid;
-}
-
-static void trex_error(TRex *exp, const TRexChar *error) {
- if (exp->_error) *exp->_error = error;
- longjmp(*((jmp_buf *)exp->_jmpbuf), -1);
-}
-
-static void trex_expect(TRex *exp, int n) {
- if ((*exp->_p) != n)
- trex_error(exp, _SC("expected paren"));
- exp->_p++;
-}
-
-static TRexChar trex_escapechar(TRex *exp) {
- if (*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) {
- exp->_p++;
- switch (*exp->_p) {
- case 'v':
- exp->_p++;
- return '\v';
- case 'n':
- exp->_p++;
- return '\n';
- case 't':
- exp->_p++;
- return '\t';
- case 'r':
- exp->_p++;
- return '\r';
- case 'f':
- exp->_p++;
- return '\f';
- default:
- return (*exp->_p++);
- }
- } else if (!scisprint(*exp->_p)) trex_error(exp, _SC("letter expected"));
- return (*exp->_p++);
-}
-
-static int trex_charclass(TRex *exp, int classid) {
- int n = trex_newnode(exp, OP_CCLASS);
- exp->_nodes[n].left = classid;
- return n;
-}
-
-static int trex_charnode(TRex *exp, TRexBool isclass) {
- TRexChar t;
- if (*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) {
- exp->_p++;
- switch (*exp->_p) {
- case 'n':
- exp->_p++;
- return trex_newnode(exp, '\n');
- case 't':
- exp->_p++;
- return trex_newnode(exp, '\t');
- case 'r':
- exp->_p++;
- return trex_newnode(exp, '\r');
- case 'f':
- exp->_p++;
- return trex_newnode(exp, '\f');
- case 'v':
- exp->_p++;
- return trex_newnode(exp, '\v');
- case 'a':
- case 'A':
- case 'w':
- case 'W':
- case 's':
- case 'S':
- case 'd':
- case 'D':
- case 'x':
- case 'X':
- case 'c':
- case 'C':
- case 'p':
- case 'P':
- case 'l':
- case 'u': {
- t = *exp->_p;
- exp->_p++;
- return trex_charclass(exp, t);
- }
- case 'b':
- case 'B':
- if (!isclass) {
- int node = trex_newnode(exp, OP_WB);
- exp->_nodes[node].left = *exp->_p;
- exp->_p++;
- return node;
- } //else default
- default:
- t = *exp->_p;
- exp->_p++;
- return trex_newnode(exp, t);
- }
- } else if (!scisprint(*exp->_p)) {
-
- trex_error(exp, _SC("letter expected"));
- }
- t = *exp->_p;
- exp->_p++;
- return trex_newnode(exp, t);
-}
-static int trex_class(TRex *exp) {
- int ret = -1;
- int first = -1, chain;
- if (*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) {
- ret = trex_newnode(exp, OP_NCLASS);
- exp->_p++;
- } else ret = trex_newnode(exp, OP_CLASS);
-
- if (*exp->_p == ']') trex_error(exp, _SC("empty class"));
- chain = ret;
- while (*exp->_p != ']' && exp->_p != exp->_eol) {
- if (*exp->_p == '-' && first != -1) {
- int r, t;
- if (*exp->_p++ == ']') {
- trex_error(exp, _SC("unfinished range"));
- }
-
- r = trex_newnode(exp, OP_RANGE);
- if (first > *exp->_p) {
- trex_error(exp, _SC("invalid range"));
- }
-
- if (exp->_nodes[first].type == OP_CCLASS) {
- trex_error(exp, _SC("cannot use character classes in ranges"));
- }
-
- exp->_nodes[r].left = exp->_nodes[first].type;
- t = trex_escapechar(exp);
- exp->_nodes[r].right = t;
- exp->_nodes[chain].next = r;
- chain = r;
- first = -1;
- } else {
- if (first != -1) {
- int c = first;
- exp->_nodes[chain].next = c;
- chain = c;
- first = trex_charnode(exp, TRex_True);
- } else {
- first = trex_charnode(exp, TRex_True);
- }
- }
- }
- if (first != -1) {
- int c = first;
- exp->_nodes[chain].next = c;
- }
- /* hack? */
- exp->_nodes[ret].left = exp->_nodes[ret].next;
- exp->_nodes[ret].next = -1;
- return ret;
-}
-
-static int trex_parsenumber(TRex *exp) {
- int ret = *exp->_p - '0';
- int positions = 10;
- exp->_p++;
- while (isdigit(*exp->_p)) {
- ret = ret * 10 + (*exp->_p++ -'0');
- if (positions == 1000000000) trex_error(exp, _SC("overflow in numeric constant"));
- positions *= 10;
- };
- return ret;
-}
-
-static int trex_element(TRex *exp) {
- int ret = -1;
- switch (*exp->_p) {
- case '(': {
- int expr, newn;
- exp->_p++;
-
-
- if (*exp->_p == '?') {
- exp->_p++;
- trex_expect(exp, ':');
- expr = trex_newnode(exp, OP_NOCAPEXPR);
- } else
- expr = trex_newnode(exp, OP_EXPR);
- newn = trex_list(exp);
- exp->_nodes[expr].left = newn;
- ret = expr;
- trex_expect(exp, ')');
- }
- break;
- case '[':
- exp->_p++;
- ret = trex_class(exp);
- trex_expect(exp, ']');
- break;
- case TREX_SYMBOL_END_OF_STRING:
- exp->_p++;
- ret = trex_newnode(exp, OP_EOL);
- break;
- case TREX_SYMBOL_ANY_CHAR:
- exp->_p++;
- ret = trex_newnode(exp, OP_DOT);
- break;
- default:
- ret = trex_charnode(exp, TRex_False);
- break;
- }
-
- {
- TRexBool isgreedy = TRex_False;
- unsigned short p0 = 0, p1 = 0;
- switch (*exp->_p) {
- case TREX_SYMBOL_GREEDY_ZERO_OR_MORE:
- p0 = 0;
- p1 = 0xFFFF;
- exp->_p++;
- isgreedy = TRex_True;
- break;
- case TREX_SYMBOL_GREEDY_ONE_OR_MORE:
- p0 = 1;
- p1 = 0xFFFF;
- exp->_p++;
- isgreedy = TRex_True;
- break;
- case TREX_SYMBOL_GREEDY_ZERO_OR_ONE:
- p0 = 0;
- p1 = 1;
- exp->_p++;
- isgreedy = TRex_True;
- break;
- case '{':
- exp->_p++;
- if (!isdigit(*exp->_p)) trex_error(exp, _SC("number expected"));
- p0 = (unsigned short)trex_parsenumber(exp);
- /*******************************/
- switch (*exp->_p) {
- case '}':
- p1 = p0;
- exp->_p++;
- break;
- case ',':
- exp->_p++;
- p1 = 0xFFFF;
- if (isdigit(*exp->_p)) {
- p1 = (unsigned short)trex_parsenumber(exp);
- }
- trex_expect(exp, '}');
- break;
- default:
- trex_error(exp, _SC(", or } expected"));
- }
- /*******************************/
- isgreedy = TRex_True;
- break;
-
- }
- if (isgreedy) {
- int nnode = trex_newnode(exp, OP_GREEDY);
- exp->_nodes[nnode].left = ret;
- exp->_nodes[nnode].right = ((p0) << 16) | p1;
- ret = nnode;
- }
- }
- if ((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
- int nnode = trex_element(exp);
- exp->_nodes[ret].next = nnode;
- }
-
- return ret;
-}
-
-static int trex_list(TRex *exp) {
- int ret = -1, e;
- if (*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) {
- exp->_p++;
- ret = trex_newnode(exp, OP_BOL);
- }
- e = trex_element(exp);
- if (ret != -1) {
- exp->_nodes[ret].next = e;
- } else ret = e;
-
- if (*exp->_p == TREX_SYMBOL_BRANCH) {
- int temp, tright;
- exp->_p++;
- temp = trex_newnode(exp, OP_OR);
- exp->_nodes[temp].left = ret;
- tright = trex_list(exp);
- exp->_nodes[temp].right = tright;
- ret = temp;
- }
- return ret;
-}
-
-static TRexBool trex_matchcclass(int cclass, TRexChar c) {
- switch (cclass) {
- case 'a':
- return isalpha(c) ? TRex_True : TRex_False;
- case 'A':
- return !isalpha(c) ? TRex_True : TRex_False;
- case 'w':
- return (isalnum(c) || c == '_') ? TRex_True : TRex_False;
- case 'W':
- return (!isalnum(c) && c != '_') ? TRex_True : TRex_False;
- case 's':
- return ISSPACE(c) ? TRex_True : TRex_False;
- case 'S':
- return !ISSPACE(c) ? TRex_True : TRex_False;
- case 'd':
- return isdigit(c) ? TRex_True : TRex_False;
- case 'D':
- return !isdigit(c) ? TRex_True : TRex_False;
- case 'x':
- return isxdigit(c) ? TRex_True : TRex_False;
- case 'X':
- return !isxdigit(c) ? TRex_True : TRex_False;
- case 'c':
- return iscntrl(c) ? TRex_True : TRex_False;
- case 'C':
- return !iscntrl(c) ? TRex_True : TRex_False;
- case 'p':
- return ispunct(c) ? TRex_True : TRex_False;
- case 'P':
- return !ispunct(c) ? TRex_True : TRex_False;
- case 'l':
- return islower(c) ? TRex_True : TRex_False;
- case 'u':
- return isupper(c) ? TRex_True : TRex_False;
- }
- return TRex_False; /*cannot happen*/
-}
-
-static TRexBool trex_matchclass(TRex *exp, TRexNode *node, TRexChar c) {
- do {
- switch (node->type) {
- case OP_RANGE:
- if (exp->_flags & TREX_ICASE) {
- if (c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True;
- if (c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True;
- } else {
- if (c >= node->left && c <= node->right) return TRex_True;
- }
- break;
- case OP_CCLASS:
- if (trex_matchcclass(node->left, c)) return TRex_True;
- break;
- default:
- if (exp->_flags & TREX_ICASE) {
- if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True;
- } else {
- if (c == node->type)return TRex_True;
- }
-
- }
- } while ((node->next != -1) && (node = &exp->_nodes[node->next]));
- return TRex_False;
-}
-
-static const TRexChar *trex_matchnode(TRex *exp, TRexNode *node, const TRexChar *str, TRexNode *next) {
-
- TRexNodeType type = node->type;
- switch (type) {
- case OP_GREEDY: {
- //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
- TRexNode *greedystop = NULL;
- int p0 = (node->right >> 16) & 0x0000FFFF, p1 = node->right & 0x0000FFFF, nmaches = 0;
- const TRexChar *s = str, *good = str;
-
- if (node->next != -1) {
- greedystop = &exp->_nodes[node->next];
- } else {
- greedystop = next;
- }
-
- while ((nmaches == 0xFFFF || nmaches < p1)) {
-
- const TRexChar *stop;
- if (!(s = trex_matchnode(exp, &exp->_nodes[node->left], s, greedystop)))
- break;
- nmaches++;
- good = s;
- if (greedystop) {
- //checks that 0 matches satisfy the expression(if so skips)
- //if not would always stop(for instance if is a '?')
- if (greedystop->type != OP_GREEDY ||
- (greedystop->type == OP_GREEDY && ((greedystop->right >> 16) & 0x0000FFFF) != 0)) {
- TRexNode *gnext = NULL;
- if (greedystop->next != -1) {
- gnext = &exp->_nodes[greedystop->next];
- } else if (next && next->next != -1) {
- gnext = &exp->_nodes[next->next];
- }
- stop = trex_matchnode(exp, greedystop, s, gnext);
- if (stop) {
- //if satisfied stop it
- if (p0 == p1 && p0 == nmaches) break;
- else if (nmaches >= p0 && p1 == 0xFFFF) break;
- else if (nmaches >= p0 && nmaches <= p1) break;
- }
- }
- }
-
- if (s >= exp->_eol)
- break;
- }
- if (p0 == p1 && p0 == nmaches) return good;
- else if (nmaches >= p0 && p1 == 0xFFFF) return good;
- else if (nmaches >= p0 && nmaches <= p1) return good;
- return NULL;
- }
- case OP_OR: {
- const TRexChar *asd = str;
- TRexNode *temp = &exp->_nodes[node->left];
- while ((asd = trex_matchnode(exp, temp, asd, NULL))) {
- if (temp->next != -1)
- temp = &exp->_nodes[temp->next];
- else
- return asd;
- }
- asd = str;
- temp = &exp->_nodes[node->right];
- while ((asd = trex_matchnode(exp, temp, asd, NULL))) {
- if (temp->next != -1)
- temp = &exp->_nodes[temp->next];
- else
- return asd;
- }
- return NULL;
- }
- case OP_EXPR:
- case OP_NOCAPEXPR: {
- TRexNode *n = &exp->_nodes[node->left];
- const TRexChar *cur = str;
- int capture = -1;
- if (node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
- capture = exp->_currsubexp;
- exp->_matches[capture].begin = cur;
- exp->_currsubexp++;
- }
-
- do {
- TRexNode *subnext = NULL;
- if (n->next != -1) {
- subnext = &exp->_nodes[n->next];
- } else {
- subnext = next;
- }
- if (!(cur = trex_matchnode(exp, n, cur, subnext))) {
- if (capture != -1) {
- exp->_matches[capture].begin = 0;
- exp->_matches[capture].len = 0;
- }
- return NULL;
- }
- } while ((n->next != -1) && (n = &exp->_nodes[n->next]));
-
- if (capture != -1)
- exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin);
- return cur;
- }
- case OP_WB:
- if ((str == exp->_bol && !ISSPACE(*str))
- || ((str == exp->_eol && !ISSPACE(*(str - 1))))
- || ((!ISSPACE(*str) && ISSPACE(*(str + 1))))
- || ((ISSPACE(*str) && !ISSPACE(*(str + 1))))) {
- return (node->left == 'b') ? str : NULL;
- }
- return (node->left == 'b') ? NULL : str;
- case OP_BOL:
- if (str == exp->_bol) return str;
- return NULL;
- case OP_EOL:
- if (str == exp->_eol) return str;
- return NULL;
- case OP_DOT:
- str++;
- return str;
- case OP_NCLASS:
- case OP_CLASS:
- if (trex_matchclass(exp, &exp->_nodes[node->left], *str) ? (type == OP_CLASS ? TRex_True : TRex_False) : (type == OP_NCLASS ? TRex_True : TRex_False)) {
- str++;
- return str;
- }
- return NULL;
- case OP_CCLASS:
- if (trex_matchcclass(node->left, *str)) {
- str++;
- return str;
- }
- return NULL;
- default: /* char */
- if (exp->_flags & TREX_ICASE) {
- if (*str != tolower(node->type) && *str != toupper(node->type)) return NULL;
- } else {
- if (*str != node->type) return NULL;
- }
- str++;
- return str;
- }
- return NULL;
-}
-
-/* public api */
-TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags) {
- TRex *exp = (TRex *)malloc(sizeof(TRex));
- exp->_eol = exp->_bol = NULL;
- exp->_p = pattern;
- exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar);
- exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode));
- exp->_nsize = 0;
- exp->_matches = 0;
- exp->_nsubexpr = 0;
- exp->_first = trex_newnode(exp, OP_EXPR);
- exp->_error = error;
- exp->_jmpbuf = malloc(sizeof(jmp_buf));
- exp->_flags = flags;
- if (setjmp(*((jmp_buf *)exp->_jmpbuf)) == 0) {
- int res = trex_list(exp);
- exp->_nodes[exp->_first].left = res;
- if (*exp->_p != '\0')
- trex_error(exp, _SC("unexpected character"));
-#ifdef _DEBUG
- {
- int nsize, i;
- TRexNode *t;
- nsize = exp->_nsize;
- t = &exp->_nodes[0];
- scprintf(_SC("\n"));
- for (i = 0; i < nsize; i++) {
- if (exp->_nodes[i].type > MAX_CHAR)
- scprintf(_SC("[%02d] %10s "), i, g_nnames[exp->_nodes[i].type - MAX_CHAR]);
- else
- scprintf(_SC("[%02d] %10c "), i, exp->_nodes[i].type);
- scprintf(_SC("left %02d right %02d next %02d\n"), exp->_nodes[i].left, exp->_nodes[i].right, exp->_nodes[i].next);
- }
- scprintf(_SC("\n"));
- }
-#endif
- exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch));
- memset(exp->_matches, 0, exp->_nsubexpr * sizeof(TRexMatch));
- } else {
- trex_free(exp);
- return NULL;
- }
- return exp;
-}
-
-void trex_free(TRex *exp) {
- if (exp) {
- if (exp->_nodes) free(exp->_nodes);
- if (exp->_jmpbuf) free(exp->_jmpbuf);
- if (exp->_matches) free(exp->_matches);
- free(exp);
- }
-}
-
-TRexBool trex_match(TRex *exp, const TRexChar *text) {
- const TRexChar *res = NULL;
- exp->_bol = text;
- exp->_eol = text + scstrlen(text);
- exp->_currsubexp = 0;
- res = trex_matchnode(exp, exp->_nodes, text, NULL);
- if (res == NULL || res != exp->_eol)
- return TRex_False;
- return TRex_True;
-}
-
-TRexBool trex_searchrange(TRex *exp, const TRexChar *text_begin, const TRexChar *text_end, const TRexChar **out_begin, const TRexChar **out_end) {
- const TRexChar *cur = NULL;
- int node = exp->_first;
- if (text_begin >= text_end) return TRex_False;
- exp->_bol = text_begin;
- exp->_eol = text_end;
- do {
- cur = text_begin;
- while (node != -1) {
- exp->_currsubexp = 0;
- cur = trex_matchnode(exp, &exp->_nodes[node], cur, NULL);
- if (!cur)
- break;
- node = exp->_nodes[node].next;
- }
- text_begin++;
- } while (cur == NULL && text_begin != text_end);
-
- if (cur == NULL)
- return TRex_False;
-
- --text_begin;
-
- if (out_begin) *out_begin = text_begin;
- if (out_end) *out_end = cur;
- return TRex_True;
-}
-
-TRexBool trex_search(TRex *exp, const TRexChar *text, const TRexChar **out_begin, const TRexChar **out_end) {
- return trex_searchrange(exp, text, text + scstrlen(text), out_begin, out_end);
-}
-
-int trex_getsubexpcount(TRex *exp) {
- return exp->_nsubexpr;
-}
-
-TRexBool trex_getsubexp(TRex *exp, int n, TRexMatch *subexp) {
- if (n < 0 || n >= exp->_nsubexpr) return TRex_False;
- *subexp = exp->_matches[n];
- return TRex_True;
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-
-#include "argtable3.h"
-
-
-static void arg_str_resetfn(struct arg_str *parent) {
- int i;
- ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
- parent->count = 0;
- for (i = 0; i < parent->count; i++) {
- parent->sval[i] = "";
- }
-}
-
-
-static int arg_str_scanfn(struct arg_str *parent, const char *argval) {
- int errorcode = 0;
-
- if (parent->count == parent->hdr.maxcount) {
- /* maximum number of arguments exceeded */
- errorcode = EMAXCOUNT;
- } else if (!argval) {
- /* a valid argument with no argument value was given. */
- /* This happens when an optional argument value was invoked. */
- /* leave parent arguiment value unaltered but still count the argument. */
- parent->count++;
- } else {
- parent->sval[parent->count++] = argval;
- }
-
- ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static int arg_str_checkfn(struct arg_str *parent) {
- int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
-
- ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
- return errorcode;
-}
-
-
-static void arg_str_errorfn(
- struct arg_str *parent,
- FILE *fp,
- int errorcode,
- const char *argval,
- const char *progname) {
- const char *shortopts = parent->hdr.shortopts;
- const char *longopts = parent->hdr.longopts;
- const char *datatype = parent->hdr.datatype;
-
- /* make argval NULL safe */
- argval = argval ? argval : "";
-
- fprintf(fp, "%s: ", progname);
- switch (errorcode) {
- case EMINCOUNT:
- fputs("missing option ", fp);
- arg_print_option(fp, shortopts, longopts, datatype, "\n");
- break;
-
- case EMAXCOUNT:
- fputs("excess option ", fp);
- arg_print_option(fp, shortopts, longopts, argval, "\n");
- break;
- }
-}
-
-
-struct arg_str *arg_str0(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_strn(shortopts, longopts, datatype, 0, 1, glossary);
-}
-
-
-struct arg_str *arg_str1(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary) {
- return arg_strn(shortopts, longopts, datatype, 1, 1, glossary);
-}
-
-
-struct arg_str *arg_strn(
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary) {
- size_t nbytes;
- struct arg_str *result;
-
- /* should not allow this stupid error */
- /* we should return an error code warning this logic error */
- /* foolproof things by ensuring maxcount is not less than mincount */
- maxcount = (maxcount < mincount) ? mincount : maxcount;
-
- nbytes = sizeof(struct arg_str) /* storage for struct arg_str */
- + maxcount * sizeof(char *); /* storage for sval[maxcount] array */
-
- result = (struct arg_str *)malloc(nbytes);
- if (result) {
- int i;
-
- /* init the arg_hdr struct */
- result->hdr.flag = ARG_HASVALUE;
- result->hdr.shortopts = shortopts;
- result->hdr.longopts = longopts;
- result->hdr.datatype = datatype ? datatype : "";
- result->hdr.glossary = glossary;
- result->hdr.mincount = mincount;
- result->hdr.maxcount = maxcount;
- result->hdr.parent = result;
- result->hdr.resetfn = (arg_resetfn *)arg_str_resetfn;
- result->hdr.scanfn = (arg_scanfn *)arg_str_scanfn;
- result->hdr.checkfn = (arg_checkfn *)arg_str_checkfn;
- result->hdr.errorfn = (arg_errorfn *)arg_str_errorfn;
-
- /* store the sval[maxcount] array immediately after the arg_str struct */
- result->sval = (const char * *)(result + 1);
- result->count = 0;
-
- /* foolproof the string pointers by initialising them to reference empty strings */
- for (i = 0; i < maxcount; i++)
- result->sval[i] = "";
- }
-
- ARG_TRACE(("arg_strn() returns %p\n", result));
- return result;
-}
-/*******************************************************************************
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#include
-#include
-#include
-#include
-
-#include "argtable3.h"
-
-static
-void arg_register_error(struct arg_end *end,
- void *parent,
- int error,
- const char *argval) {
- /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */
- if (end->count < end->hdr.maxcount) {
- end->error[end->count] = error;
- end->parent[end->count] = parent;
- end->argval[end->count] = argval;
- end->count++;
- } else {
- end->error[end->hdr.maxcount - 1] = ARG_ELIMIT;
- end->parent[end->hdr.maxcount - 1] = end;
- end->argval[end->hdr.maxcount - 1] = NULL;
- }
-}
-
-
-/*
- * Return index of first table entry with a matching short option
- * or -1 if no match was found.
- */
-static int find_shortoption(struct arg_hdr **table, char shortopt) {
- int tabindex;
- for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) {
- if (table[tabindex]->shortopts &&
- strchr(table[tabindex]->shortopts, shortopt))
- return tabindex;
- }
- return -1;
-}
-
-struct longoptions {
- int getoptval;
- int noptions;
- struct option *options;
-};
-
-#if 0
-static
-void dump_longoptions(struct longoptions *longoptions) {
- int i;
- printf("getoptval = %d\n", longoptions->getoptval);
- printf("noptions = %d\n", longoptions->noptions);
- for (i = 0; i < longoptions->noptions; i++) {
- printf("options[%d].name = \"%s\"\n",
- i,
- longoptions->options[i].name);
- printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg);
- printf("options[%d].flag = %p\n", i, longoptions->options[i].flag);
- printf("options[%d].val = %d\n", i, longoptions->options[i].val);
- }
-}
-#endif
-
-static struct longoptions *alloc_longoptions(struct arg_hdr **table) {
- struct longoptions *result;
- size_t nbytes;
- int noptions = 1;
- size_t longoptlen = 0;
- int tabindex;
-
- /*
- * Determine the total number of option structs required
- * by counting the number of comma separated long options
- * in all table entries and return the count in noptions.
- * note: noptions starts at 1 not 0 because we getoptlong
- * requires a NULL option entry to terminate the option array.
- * While we are at it, count the number of chars required
- * to store private copies of all the longoption strings
- * and return that count in logoptlen.
- */
- tabindex = 0;
- do {
- const char *longopts = table[tabindex]->longopts;
- longoptlen += (longopts ? strlen(longopts) : 0) + 1;
- while (longopts) {
- noptions++;
- longopts = strchr(longopts + 1, ',');
- }
- } while (!(table[tabindex++]->flag & ARG_TERMINATOR));
- /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/
-
-
- /* allocate storage for return data structure as: */
- /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */
- nbytes = sizeof(struct longoptions)
- + sizeof(struct option) * noptions
- + longoptlen;
- result = (struct longoptions *)malloc(nbytes);
- if (result) {
- int option_index = 0;
- char *store;
-
- result->getoptval = 0;
- result->noptions = noptions;
- result->options = (struct option *)(result + 1);
- store = (char *)(result->options + noptions);
-
- for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) {
- const char *longopts = table[tabindex]->longopts;
-
- while (longopts && *longopts) {
- char *storestart = store;
-
- /* copy progressive longopt strings into the store */
- while (*longopts != 0 && *longopts != ',')
- *store++ = *longopts++;
- *store++ = 0;
- if (*longopts == ',')
- longopts++;
- /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/
-
- result->options[option_index].name = storestart;
- result->options[option_index].flag = &(result->getoptval);
- result->options[option_index].val = tabindex;
- if (table[tabindex]->flag & ARG_HASOPTVALUE)
- result->options[option_index].has_arg = 2;
- else if (table[tabindex]->flag & ARG_HASVALUE)
- result->options[option_index].has_arg = 1;
- else
- result->options[option_index].has_arg = 0;
-
- option_index++;
- }
- }
- /* terminate the options array with a zero-filled entry */
- result->options[option_index].name = 0;
- result->options[option_index].has_arg = 0;
- result->options[option_index].flag = 0;
- result->options[option_index].val = 0;
- }
-
- /*dump_longoptions(result);*/
- return result;
-}
-
-static char *alloc_shortoptions(struct arg_hdr **table) {
- char *result;
- size_t len = 2;
- int tabindex;
-
- /* determine the total number of option chars required */
- for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) {
- struct arg_hdr *hdr = table[tabindex];
- len += 3 * (hdr->shortopts ? strlen(hdr->shortopts) : 0);
- }
-
- result = malloc(len);
- if (result) {
- char *res = result;
-
- /* add a leading ':' so getopt return codes distinguish */
- /* unrecognised option and options missing argument values */
- *res++ = ':';
-
- for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) {
- struct arg_hdr *hdr = table[tabindex];
- const char *shortopts = hdr->shortopts;
- while (shortopts && *shortopts) {
- *res++ = *shortopts++;
- if (hdr->flag & ARG_HASVALUE)
- *res++ = ':';
- if (hdr->flag & ARG_HASOPTVALUE)
- *res++ = ':';
- }
- }
- /* null terminate the string */
- *res = 0;
- }
-
- /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/
- return result;
-}
-
-
-/* return index of the table terminator entry */
-static int arg_endindex(struct arg_hdr **table) {
- int tabindex = 0;
- while (!(table[tabindex]->flag & ARG_TERMINATOR))
- tabindex++;
- return tabindex;
-}
-
-
-static void arg_parse_tagged(int argc,
- char **argv,
- struct arg_hdr **table,
- struct arg_end *endtable) {
- struct longoptions *longoptions;
- char *shortoptions;
- int copt;
-
- /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/
-
- /* allocate short and long option arrays for the given opttable[]. */
- /* if the allocs fail then put an error msg in the last table entry. */
- longoptions = alloc_longoptions(table);
- shortoptions = alloc_shortoptions(table);
- if (!longoptions || !shortoptions) {
- /* one or both memory allocs failed */
- arg_register_error(endtable, endtable, ARG_EMALLOC, NULL);
- /* free anything that was allocated (this is null safe) */
- free(shortoptions);
- free(longoptions);
- return;
- }
-
- /*dump_longoptions(longoptions);*/
-
- /* reset getopts internal option-index to zero, and disable error reporting */
- optind = 0;
- opterr = 0;
-
- /* fetch and process args using getopt_long */
- while ((copt =
- getopt_long(argc, argv, shortoptions, longoptions->options,
- NULL)) != -1) {
- /*
- printf("optarg='%s'\n",optarg);
- printf("optind=%d\n",optind);
- printf("copt=%c\n",(char)copt);
- printf("optopt=%c (%d)\n",optopt, (int)(optopt));
- */
- switch (copt) {
- case 0: {
- int tabindex = longoptions->getoptval;
- void *parent = table[tabindex]->parent;
- /*printf("long option detected from argtable[%d]\n", tabindex);*/
- if (optarg && optarg[0] == 0 &&
- (table[tabindex]->flag & ARG_HASVALUE)) {
- /* printf(": long option %s requires an argument\n",argv[optind-1]); */
- arg_register_error(endtable, endtable, ARG_EMISSARG,
- argv[optind - 1]);
- /* continue to scan the (empty) argument value to enforce argument count checking */
- }
- if (table[tabindex]->scanfn) {
- int errorcode = table[tabindex]->scanfn(parent, optarg);
- if (errorcode != 0)
- arg_register_error(endtable, parent, errorcode, optarg);
- }
- }
- break;
-
- case '?':
- /*
- * getopt_long() found an unrecognised short option.
- * if it was a short option its value is in optopt
- * if it was a long option then optopt=0
- */
- switch (optopt) {
- case 0:
- /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/
- arg_register_error(endtable, endtable, ARG_ELONGOPT,
- argv[optind - 1]);
- break;
- default:
- /*printf("?* unrecognised short option '%c'\n",optopt);*/
- arg_register_error(endtable, endtable, optopt, NULL);
- break;
- }
- break;
-
- case ':':
- /*
- * getopt_long() found an option with its argument missing.
- */
- /*printf(": option %s requires an argument\n",argv[optind-1]); */
- arg_register_error(endtable, endtable, ARG_EMISSARG,
- argv[optind - 1]);
- break;
-
- default: {
- /* getopt_long() found a valid short option */
- int tabindex = find_shortoption(table, (char)copt);
- /*printf("short option detected from argtable[%d]\n", tabindex);*/
- if (tabindex == -1) {
- /* should never get here - but handle it just in case */
- /*printf("unrecognised short option %d\n",copt);*/
- arg_register_error(endtable, endtable, copt, NULL);
- } else {
- if (table[tabindex]->scanfn) {
- void *parent = table[tabindex]->parent;
- int errorcode = table[tabindex]->scanfn(parent, optarg);
- if (errorcode != 0)
- arg_register_error(endtable, parent, errorcode, optarg);
- }
- }
- break;
- }
- }
- }
-
- free(shortoptions);
- free(longoptions);
-}
-
-
-static void arg_parse_untagged(int argc,
- char **argv,
- struct arg_hdr **table,
- struct arg_end *endtable) {
- int tabindex = 0;
- int errorlast = 0;
- const char *optarglast = NULL;
- void *parentlast = NULL;
-
- /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/
- while (!(table[tabindex]->flag & ARG_TERMINATOR)) {
- void *parent;
- int errorcode;
-
- /* if we have exhausted our argv[optind] entries then we have finished */
- if (optind >= argc) {
- /*printf("arg_parse_untagged(): argv[] exhausted\n");*/
- return;
- }
-
- /* skip table entries with non-null long or short options (they are not untagged entries) */
- if (table[tabindex]->longopts || table[tabindex]->shortopts) {
- /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/
- tabindex++;
- continue;
- }
-
- /* skip table entries with NULL scanfn */
- if (!(table[tabindex]->scanfn)) {
- /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/
- tabindex++;
- continue;
- }
-
- /* attempt to scan the current argv[optind] with the current */
- /* table[tabindex] entry. If it succeeds then keep it, otherwise */
- /* try again with the next table[] entry. */
- parent = table[tabindex]->parent;
- errorcode = table[tabindex]->scanfn(parent, argv[optind]);
- if (errorcode == 0) {
- /* success, move onto next argv[optind] but stay with same table[tabindex] */
- /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/
- optind++;
-
- /* clear the last tentative error */
- errorlast = 0;
- } else {
- /* failure, try same argv[optind] with next table[tabindex] entry */
- /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/
- tabindex++;
-
- /* remember this as a tentative error we may wish to reinstate later */
- errorlast = errorcode;
- optarglast = argv[optind];
- parentlast = parent;
- }
- }
-
- /* if a tenative error still remains at this point then register it as a proper error */
- if (errorlast) {
- arg_register_error(endtable, parentlast, errorlast, optarglast);
- optind++;
- }
-
- /* only get here when not all argv[] entries were consumed */
- /* register an error for each unused argv[] entry */
- while (optind < argc) {
- /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/
- arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]);
- }
-
- return;
-}
-
-
-static void arg_parse_check(struct arg_hdr **table, struct arg_end *endtable) {
- int tabindex = 0;
- /* printf("arg_parse_check()\n"); */
- do {
- if (table[tabindex]->checkfn) {
- void *parent = table[tabindex]->parent;
- int errorcode = table[tabindex]->checkfn(parent);
- if (errorcode != 0)
- arg_register_error(endtable, parent, errorcode, NULL);
- }
- } while (!(table[tabindex++]->flag & ARG_TERMINATOR));
-}
-
-
-static void arg_reset(void **argtable) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int tabindex = 0;
- /*printf("arg_reset(%p)\n",argtable);*/
- do {
- if (table[tabindex]->resetfn)
- table[tabindex]->resetfn(table[tabindex]->parent);
- } while (!(table[tabindex++]->flag & ARG_TERMINATOR));
-}
-
-
-int arg_parse(int argc, char * *argv, void * *argtable) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- struct arg_end *endtable;
- int endindex;
- char * *argvcopy = NULL;
-
- /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/
-
- /* reset any argtable data from previous invocations */
- arg_reset(argtable);
-
- /* locate the first end-of-table marker within the array */
- endindex = arg_endindex(table);
- endtable = (struct arg_end *)table[endindex];
-
- /* Special case of argc==0. This can occur on Texas Instruments DSP. */
- /* Failure to trap this case results in an unwanted NULL result from */
- /* the malloc for argvcopy (next code block). */
- if (argc == 0) {
- /* We must still perform post-parse checks despite the absence of command line arguments */
- arg_parse_check(table, endtable);
-
- /* Now we are finished */
- return endtable->count;
- }
-
- argvcopy = (char **)malloc(sizeof(char *) * (argc + 1));
- if (argvcopy) {
- int i;
-
- /*
- Fill in the local copy of argv[]. We need a local copy
- because getopt rearranges argv[] which adversely affects
- susbsequent parsing attempts.
- */
- for (i = 0; i < argc; i++)
- argvcopy[i] = argv[i];
-
- argvcopy[argc] = NULL;
-
- /* parse the command line (local copy) for tagged options */
- arg_parse_tagged(argc, argvcopy, table, endtable);
-
- /* parse the command line (local copy) for untagged options */
- arg_parse_untagged(argc, argvcopy, table, endtable);
-
- /* if no errors so far then perform post-parse checks otherwise dont bother */
- if (endtable->count == 0)
- arg_parse_check(table, endtable);
-
- /* release the local copt of argv[] */
- free(argvcopy);
- } else {
- /* memory alloc failed */
- arg_register_error(endtable, endtable, ARG_EMALLOC, NULL);
- }
-
- return endtable->count;
-}
-
-
-/*
- * Concatenate contents of src[] string onto *pdest[] string.
- * The *pdest pointer is altered to point to the end of the
- * target string and *pndest is decremented by the same number
- * of chars.
- * Does not append more than *pndest chars into *pdest[]
- * so as to prevent buffer overruns.
- * Its something like strncat() but more efficient for repeated
- * calls on the same destination string.
- * Example of use:
- * char dest[30] = "good"
- * size_t ndest = sizeof(dest);
- * char *pdest = dest;
- * arg_char(&pdest,"bye ",&ndest);
- * arg_char(&pdest,"cruel ",&ndest);
- * arg_char(&pdest,"world!",&ndest);
- * Results in:
- * dest[] == "goodbye cruel world!"
- * ndest == 10
- */
-static void arg_cat(char **pdest, const char *src, size_t *pndest) {
- char *dest = *pdest;
- char *end = dest + *pndest;
-
- /*locate null terminator of dest string */
- while (dest < end && *dest != 0)
- dest++;
-
- /* concat src string to dest string */
- while (dest < end && *src != 0)
- *dest++ = *src++;
-
- /* null terminate dest string */
- *dest = 0;
-
- /* update *pdest and *pndest */
- *pndest = end - dest;
- *pdest = dest;
-}
-
-
-static void arg_cat_option(char *dest,
- size_t ndest,
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- int optvalue) {
- if (shortopts) {
- char option[3];
-
- /* note: option array[] is initialiazed dynamically here to satisfy */
- /* a deficiency in the watcom compiler wrt static array initializers. */
- option[0] = '-';
- option[1] = shortopts[0];
- option[2] = 0;
-
- arg_cat(&dest, option, &ndest);
- if (datatype) {
- arg_cat(&dest, " ", &ndest);
- if (optvalue) {
- arg_cat(&dest, "[", &ndest);
- arg_cat(&dest, datatype, &ndest);
- arg_cat(&dest, "]", &ndest);
- } else
- arg_cat(&dest, datatype, &ndest);
- }
- } else if (longopts) {
- size_t ncspn;
-
- /* add "--" tag prefix */
- arg_cat(&dest, "--", &ndest);
-
- /* add comma separated option tag */
- ncspn = strcspn(longopts, ",");
-#ifdef __STDC_WANT_SECURE_LIB__
- strncat_s(dest, ndest, longopts, (ncspn < ndest) ? ncspn : ndest);
-#else
- strncat(dest, longopts, (ncspn < ndest) ? ncspn : ndest);
-#endif
-
- if (datatype) {
- arg_cat(&dest, "=", &ndest);
- if (optvalue) {
- arg_cat(&dest, "[", &ndest);
- arg_cat(&dest, datatype, &ndest);
- arg_cat(&dest, "]", &ndest);
- } else
- arg_cat(&dest, datatype, &ndest);
- }
- } else if (datatype) {
- if (optvalue) {
- arg_cat(&dest, "[", &ndest);
- arg_cat(&dest, datatype, &ndest);
- arg_cat(&dest, "]", &ndest);
- } else
- arg_cat(&dest, datatype, &ndest);
- }
-}
-
-static void arg_cat_optionv(char *dest,
- size_t ndest,
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- int optvalue,
- const char *separator) {
- separator = separator ? separator : "";
-
- if (shortopts) {
- const char *c = shortopts;
- while (*c) {
- /* "-a|-b|-c" */
- char shortopt[3];
-
- /* note: shortopt array[] is initialiazed dynamically here to satisfy */
- /* a deficiency in the watcom compiler wrt static array initializers. */
- shortopt[0] = '-';
- shortopt[1] = *c;
- shortopt[2] = 0;
-
- arg_cat(&dest, shortopt, &ndest);
- if (*++c)
- arg_cat(&dest, separator, &ndest);
- }
- }
-
- /* put separator between long opts and short opts */
- if (shortopts && longopts)
- arg_cat(&dest, separator, &ndest);
-
- if (longopts) {
- const char *c = longopts;
- while (*c) {
- size_t ncspn;
-
- /* add "--" tag prefix */
- arg_cat(&dest, "--", &ndest);
-
- /* add comma separated option tag */
- ncspn = strcspn(c, ",");
-#ifdef __STDC_WANT_SECURE_LIB__
- strncat_s(dest, ndest, c, (ncspn < ndest) ? ncspn : ndest);
-#else
- strncat(dest, c, (ncspn < ndest) ? ncspn : ndest);
-#endif
- c += ncspn;
-
- /* add given separator in place of comma */
- if (*c == ',') {
- arg_cat(&dest, separator, &ndest);
- c++;
- }
- }
- }
-
- if (datatype) {
- if (longopts)
- arg_cat(&dest, "=", &ndest);
- else if (shortopts)
- arg_cat(&dest, " ", &ndest);
-
- if (optvalue) {
- arg_cat(&dest, "[", &ndest);
- arg_cat(&dest, datatype, &ndest);
- arg_cat(&dest, "]", &ndest);
- } else
- arg_cat(&dest, datatype, &ndest);
- }
-}
-
-
-/* this function should be deprecated because it doesnt consider optional argument values (ARG_HASOPTVALUE) */
-void arg_print_option(FILE *fp,
- const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *suffix) {
- char syntax[200] = "";
- suffix = suffix ? suffix : "";
-
- /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */
- arg_cat_optionv(syntax,
- sizeof(syntax),
- shortopts,
- longopts,
- datatype,
- 0,
- "|");
-
- fputs(syntax, fp);
- fputs(suffix, fp);
-}
-
-
-/*
- * Print a GNU style [OPTION] string in which all short options that
- * do not take argument values are presented in abbreviated form, as
- * in: -xvfsd, or -xvf[sd], or [-xvsfd]
- */
-static
-void arg_print_gnuswitch(FILE *fp, struct arg_hdr * *table) {
- int tabindex;
- const char *format1 = " -%c";
- const char *format2 = " [-%c";
- const char *suffix = "";
-
- /* print all mandatory switches that are without argument values */
- for (tabindex = 0;
- table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
- tabindex++) {
- /* skip optional options */
- if (table[tabindex]->mincount < 1)
- continue;
-
- /* skip non-short options */
- if (table[tabindex]->shortopts == NULL)
- continue;
-
- /* skip options that take argument values */
- if (table[tabindex]->flag & ARG_HASVALUE)
- continue;
-
- /* print the short option (only the first short option char, ignore multiple choices)*/
- fprintf(fp, format1, table[tabindex]->shortopts[0]);
- format1 = "%c";
- format2 = "[%c";
- }
-
- /* print all optional switches that are without argument values */
- for (tabindex = 0;
- table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
- tabindex++) {
- /* skip mandatory args */
- if (table[tabindex]->mincount > 0)
- continue;
-
- /* skip args without short options */
- if (table[tabindex]->shortopts == NULL)
- continue;
-
- /* skip args with values */
- if (table[tabindex]->flag & ARG_HASVALUE)
- continue;
-
- /* print first short option */
- fprintf(fp, format2, table[tabindex]->shortopts[0]);
- format2 = "%c";
- suffix = "]";
- }
-
- fprintf(fp, "%s", suffix);
-}
-
-
-void arg_print_syntax(FILE *fp, void * *argtable, const char *suffix) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int i, tabindex;
-
- /* print GNU style [OPTION] string */
- arg_print_gnuswitch(fp, table);
-
- /* print remaining options in abbreviated style */
- for (tabindex = 0;
- table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
- tabindex++) {
- char syntax[200] = "";
- const char *shortopts, *longopts, *datatype;
-
- /* skip short options without arg values (they were printed by arg_print_gnu_switch) */
- if (table[tabindex]->shortopts &&
- !(table[tabindex]->flag & ARG_HASVALUE))
- continue;
-
- shortopts = table[tabindex]->shortopts;
- longopts = table[tabindex]->longopts;
- datatype = table[tabindex]->datatype;
- arg_cat_option(syntax,
- sizeof(syntax),
- shortopts,
- longopts,
- datatype,
- table[tabindex]->flag & ARG_HASOPTVALUE);
-
- if (strlen(syntax) > 0) {
- /* print mandatory instances of this option */
- for (i = 0; i < table[tabindex]->mincount; i++)
- fprintf(fp, " %s", syntax);
-
- /* print optional instances enclosed in "[..]" */
- switch (table[tabindex]->maxcount - table[tabindex]->mincount) {
- case 0:
- break;
- case 1:
- fprintf(fp, " [%s]", syntax);
- break;
- case 2:
- fprintf(fp, " [%s] [%s]", syntax, syntax);
- break;
- default:
- fprintf(fp, " [%s]...", syntax);
- break;
- }
- }
- }
-
- if (suffix)
- fprintf(fp, "%s", suffix);
-}
-
-
-void arg_print_syntaxv(FILE *fp, void * *argtable, const char *suffix) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int i, tabindex;
-
- /* print remaining options in abbreviated style */
- for (tabindex = 0;
- table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
- tabindex++) {
- char syntax[200] = "";
- const char *shortopts, *longopts, *datatype;
-
- shortopts = table[tabindex]->shortopts;
- longopts = table[tabindex]->longopts;
- datatype = table[tabindex]->datatype;
- arg_cat_optionv(syntax,
- sizeof(syntax),
- shortopts,
- longopts,
- datatype,
- table[tabindex]->flag & ARG_HASOPTVALUE,
- "|");
-
- /* print mandatory options */
- for (i = 0; i < table[tabindex]->mincount; i++)
- fprintf(fp, " %s", syntax);
-
- /* print optional args enclosed in "[..]" */
- switch (table[tabindex]->maxcount - table[tabindex]->mincount) {
- case 0:
- break;
- case 1:
- fprintf(fp, " [%s]", syntax);
- break;
- case 2:
- fprintf(fp, " [%s] [%s]", syntax, syntax);
- break;
- default:
- fprintf(fp, " [%s]...", syntax);
- break;
- }
- }
-
- if (suffix)
- fprintf(fp, "%s", suffix);
-}
-
-
-void arg_print_glossary(FILE *fp, void * *argtable, const char *format) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int tabindex;
-
- format = format ? format : " %-20s %s\n";
- for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) {
- if (table[tabindex]->glossary) {
- char syntax[200] = "";
- const char *shortopts = table[tabindex]->shortopts;
- const char *longopts = table[tabindex]->longopts;
- const char *datatype = table[tabindex]->datatype;
- const char *glossary = table[tabindex]->glossary;
- arg_cat_optionv(syntax,
- sizeof(syntax),
- shortopts,
- longopts,
- datatype,
- table[tabindex]->flag & ARG_HASOPTVALUE,
- ", ");
- fprintf(fp, format, syntax, glossary);
- }
- }
-}
-
-
-/**
- * Print a piece of text formatted, which means in a column with a
- * left and a right margin. The lines are wrapped at whitspaces next
- * to right margin. The function does not indent the first line, but
- * only the following ones.
- *
- * Example:
- * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." )
- * will result in the following output:
- *
- * Some
- * text
- * that
- * doesn'
- * t fit.
- *
- * Too long lines will be wrapped in the middle of a word.
- *
- * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." )
- * will result in the following output:
- *
- * Some
- * text
- * that
- * doesn'
- * t fit.
- *
- * As you see, the first line is not indented. This enables output of
- * lines, which start in a line where output already happened.
- *
- * Author: Uli Fouquet
- */
-static
-void arg_print_formatted(FILE *fp,
- const unsigned lmargin,
- const unsigned rmargin,
- const char *text) {
- const unsigned textlen = (unsigned)strlen(text);
- unsigned line_start = 0;
- unsigned line_end = textlen + 1;
- const unsigned colwidth = (rmargin - lmargin) + 1;
-
- /* Someone doesn't like us... */
- if (line_end == line_start) {
- fprintf(fp, "%s\n", text);
- }
-
- while (line_end - 1 > line_start) {
- /* Eat leading whitespaces. This is essential because while
- wrapping lines, there will often be a whitespace at beginning
- of line */
- while (ISSPACE(*(text + line_start)))
- { line_start++; }
-
- if ((line_end - line_start) > colwidth)
- { line_end = line_start + colwidth; }
-
- /* Find last whitespace, that fits into line */
- while ((line_end > line_start)
- && (line_end - line_start > colwidth)
- && !ISSPACE(*(text + line_end)))
- { line_end--; }
-
- /* Do not print trailing whitespace. If this text
- has got only one line, line_end now points to the
- last char due to initialization. */
- line_end--;
-
- /* Output line of text */
- while (line_start < line_end) {
- fputc(*(text + line_start), fp);
- line_start++;
- }
- fputc('\n', fp);
-
- /* Initialize another line */
- if (line_end + 1 < textlen) {
- unsigned i;
-
- for (i = 0; i < lmargin; i++)
- { fputc(' ', fp); }
-
- line_end = textlen;
- }
-
- /* If we have to print another line, get also the last char. */
- line_end++;
-
- } /* lines of text */
-}
-
-/**
- * Prints the glossary in strict GNU format.
- * Differences to arg_print_glossary() are:
- * - wraps lines after 80 chars
- * - indents lines without shortops
- * - does not accept formatstrings
- *
- * Contributed by Uli Fouquet
- */
-void arg_print_glossary_gnu(FILE *fp, void * *argtable) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int tabindex;
-
- for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) {
- if (table[tabindex]->glossary) {
- char syntax[200] = "";
- const char *shortopts = table[tabindex]->shortopts;
- const char *longopts = table[tabindex]->longopts;
- const char *datatype = table[tabindex]->datatype;
- const char *glossary = table[tabindex]->glossary;
-
- if (!shortopts && longopts) {
- /* Indent trailing line by 4 spaces... */
- memset(syntax, ' ', 4);
- *(syntax + 4) = '\0';
- }
-
- arg_cat_optionv(syntax,
- sizeof(syntax),
- shortopts,
- longopts,
- datatype,
- table[tabindex]->flag & ARG_HASOPTVALUE,
- ", ");
-
- /* If syntax fits not into column, print glossary in new line... */
- if (strlen(syntax) > 25) {
- fprintf(fp, " %-25s %s\n", syntax, "");
- *syntax = '\0';
- }
-
- fprintf(fp, " %-25s ", syntax);
- arg_print_formatted(fp, 28, 79, glossary);
- }
- } /* for each table entry */
-
- fputc('\n', fp);
-}
-
-
-/**
- * Checks the argtable[] array for NULL entries and returns 1
- * if any are found, zero otherwise.
- */
-int arg_nullcheck(void * *argtable) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int tabindex;
- /*printf("arg_nullcheck(%p)\n",argtable);*/
-
- if (!table)
- return 1;
-
- tabindex = 0;
- do {
- /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/
- if (!table[tabindex])
- return 1;
- } while (!(table[tabindex++]->flag & ARG_TERMINATOR));
-
- return 0;
-}
-
-/*
- * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design.
- * The flaw results in memory leak in the (very rare) case that an intermediate
- * entry in the argtable array failed its memory allocation while others following
- * that entry were still allocated ok. Those subsequent allocations will not be
- * deallocated by arg_free().
- * Despite the unlikeliness of the problem occurring, and the even unlikelier event
- * that it has any deliterious effect, it is fixed regardless by replacing arg_free()
- * with the newer arg_freetable() function.
- * We still keep arg_free() for backwards compatibility.
- */
-void arg_free(void * *argtable) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- int tabindex = 0;
- int flag;
- /*printf("arg_free(%p)\n",argtable);*/
- do {
- /*
- if we encounter a NULL entry then somewhat incorrectly we presume
- we have come to the end of the array. It isnt strictly true because
- an intermediate entry could be NULL with other non-NULL entries to follow.
- The subsequent argtable entries would then not be freed as they should.
- */
- if (table[tabindex] == NULL)
- break;
-
- flag = table[tabindex]->flag;
- free(table[tabindex]);
- table[tabindex++] = NULL;
-
- } while (!(flag & ARG_TERMINATOR));
-}
-
-/* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */
-void arg_freetable(void * *argtable, size_t n) {
- struct arg_hdr * *table = (struct arg_hdr * *)argtable;
- size_t tabindex = 0;
- /*printf("arg_freetable(%p)\n",argtable);*/
- for (tabindex = 0; tabindex < n; tabindex++) {
- if (table[tabindex] == NULL)
- continue;
-
- free(table[tabindex]);
- table[tabindex] = NULL;
- };
-}
-
diff --git a/pm3rdv4rrg/src/main/cpp/client/cliparser/argtable3.h b/pm3rdv4rrg/src/main/cpp/client/cliparser/argtable3.h
deleted file mode 100644
index d8e3c53c..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cliparser/argtable3.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*******************************************************************************
- * argtable3: Declares the main interfaces of the library
- *
- * This file is part of the argtable3 library.
- *
- * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of STEWART HEITMANN nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-#ifndef ARGTABLE3
-#define ARGTABLE3
-
-#include /* FILE */
-#include /* struct tm */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ARG_REX_ICASE 1
-#define ARG_DSTR_SIZE 200
-#define ARG_CMD_NAME_LEN 100
-#define ARG_CMD_DESCRIPTION_LEN 256
-
-#ifndef ARG_REPLACE_GETOPT
-#define ARG_REPLACE_GETOPT 1 /* use the embedded getopt as the system getopt(3) */
-#endif /* ARG_REPLACE_GETOPT */
-
-/* bit masks for arg_hdr.flag */
-enum {
- ARG_TERMINATOR = 0x1,
- ARG_HASVALUE = 0x2,
- ARG_HASOPTVALUE = 0x4
-};
-
-typedef void (arg_resetfn)(void *parent);
-typedef int (arg_scanfn)(void *parent, const char *argval);
-typedef int (arg_checkfn)(void *parent);
-typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval, const char *progname);
-
-
-/*
-* The arg_hdr struct defines properties that are common to all arg_xxx structs.
-* The argtable library requires each arg_xxx struct to have an arg_hdr
-* struct as its first data member.
-* The argtable library functions then use this data to identify the
-* properties of the command line option, such as its option tags,
-* datatype string, and glossary strings, and so on.
-* Moreover, the arg_hdr struct contains pointers to custom functions that
-* are provided by each arg_xxx struct which perform the tasks of parsing
-* that particular arg_xxx arguments, performing post-parse checks, and
-* reporting errors.
-* These functions are private to the individual arg_xxx source code
-* and are the pointer to them are initiliased by that arg_xxx struct's
-* constructor function. The user could alter them after construction
-* if desired, but the original intention is for them to be set by the
-* constructor and left unaltered.
-*/
-struct arg_hdr {
- char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */
- const char *shortopts; /* String defining the short options */
- const char *longopts; /* String defiing the long options */
- const char *datatype; /* Description of the argument data type */
- const char *glossary; /* Description of the option as shown by arg_print_glossary function */
- int mincount; /* Minimum number of occurences of this option accepted */
- int maxcount; /* Maximum number of occurences if this option accepted */
- void *parent; /* Pointer to parent arg_xxx struct */
- arg_resetfn *resetfn; /* Pointer to parent arg_xxx reset function */
- arg_scanfn *scanfn; /* Pointer to parent arg_xxx scan function */
- arg_checkfn *checkfn; /* Pointer to parent arg_xxx check function */
- arg_errorfn *errorfn; /* Pointer to parent arg_xxx error function */
- void *priv; /* Pointer to private header data for use by arg_xxx functions */
-};
-
-struct arg_rem {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
-};
-
-struct arg_lit {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of matching command line args */
-};
-
-struct arg_int {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of matching command line args */
- int *ival; /* Array of parsed argument values */
-};
-
-struct arg_dbl {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of matching command line args */
- double *dval; /* Array of parsed argument values */
-};
-
-struct arg_str {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of matching command line args */
- const char **sval; /* Array of parsed argument values */
-};
-
-struct arg_rex {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of matching command line args */
- const char **sval; /* Array of parsed argument values */
-};
-
-struct arg_file {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of matching command line args*/
- const char **filename; /* Array of parsed filenames (eg: /home/foo.bar) */
- const char **basename; /* Array of parsed basenames (eg: foo.bar) */
- const char **extension; /* Array of parsed extensions (eg: .bar) */
-};
-
-struct arg_date {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- const char *format; /* strptime format string used to parse the date */
- int count; /* Number of matching command line args */
- struct tm *tmval; /* Array of parsed time values */
-};
-
-enum {ARG_ELIMIT = 1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG};
-struct arg_end {
- struct arg_hdr hdr; /* The mandatory argtable header struct */
- int count; /* Number of errors encountered */
- int *error; /* Array of error codes */
- void **parent; /* Array of pointers to offending arg_xxx struct */
- const char **argval; /* Array of pointers to offending argv[] string */
-};
-
-/*
-typedef struct arg_cmd_info {
- char name[ARG_CMD_NAME_LEN];
- char description[ARG_CMD_DESCRIPTION_LEN];
- arg_cmdfn* proc;
-} arg_cmd_info_t;
-*/
-
-/**** arg_xxx constructor functions *********************************/
-
-struct arg_rem *arg_rem(const char *datatype, const char *glossary);
-
-struct arg_lit *arg_lit0(const char *shortopts,
- const char *longopts,
- const char *glossary);
-struct arg_lit *arg_lit1(const char *shortopts,
- const char *longopts,
- const char *glossary);
-struct arg_lit *arg_litn(const char *shortopts,
- const char *longopts,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_key *arg_key0(const char *keyword,
- int flags,
- const char *glossary);
-struct arg_key *arg_key1(const char *keyword,
- int flags,
- const char *glossary);
-struct arg_key *arg_keyn(const char *keyword,
- int flags,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_int *arg_int0(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_int *arg_int1(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_int *arg_intn(const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_dbl *arg_dbl0(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_dbl *arg_dbl1(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_dbl *arg_dbln(const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_str *arg_str0(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_str *arg_str1(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_str *arg_strn(const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_rex *arg_rex0(const char *shortopts,
- const char *longopts,
- const char *pattern,
- const char *datatype,
- int flags,
- const char *glossary);
-struct arg_rex *arg_rex1(const char *shortopts,
- const char *longopts,
- const char *pattern,
- const char *datatype,
- int flags,
- const char *glossary);
-struct arg_rex *arg_rexn(const char *shortopts,
- const char *longopts,
- const char *pattern,
- const char *datatype,
- int mincount,
- int maxcount,
- int flags,
- const char *glossary);
-
-struct arg_file *arg_file0(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_file *arg_file1(const char *shortopts,
- const char *longopts,
- const char *datatype,
- const char *glossary);
-struct arg_file *arg_filen(const char *shortopts,
- const char *longopts,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_date *arg_date0(const char *shortopts,
- const char *longopts,
- const char *format,
- const char *datatype,
- const char *glossary);
-struct arg_date *arg_date1(const char *shortopts,
- const char *longopts,
- const char *format,
- const char *datatype,
- const char *glossary);
-struct arg_date *arg_daten(const char *shortopts,
- const char *longopts,
- const char *format,
- const char *datatype,
- int mincount,
- int maxcount,
- const char *glossary);
-
-struct arg_end *arg_end(int maxcount);
-
-
-/**** other functions *******************************************/
-int arg_nullcheck(void **argtable);
-int arg_parse(int argc, char **argv, void **argtable);
-void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix);
-void arg_print_syntax(FILE *fp, void **argtable, const char *suffix);
-void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix);
-void arg_print_glossary(FILE *fp, void **argtable, const char *format);
-void arg_print_glossary_gnu(FILE *fp, void **argtable);
-void arg_print_errors(FILE *fp, struct arg_end *end, const char *progname);
-void arg_freetable(void **argtable, size_t n);
-
-/**** deprecated functions, for back-compatibility only ********/
-void arg_free(void **argtable);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/cliparser/cliparser.c b/pm3rdv4rrg/src/main/cpp/client/cliparser/cliparser.c
deleted file mode 100644
index 02746c0f..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cliparser/cliparser.c
+++ /dev/null
@@ -1,203 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2017 Merlok
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Command line parser core commands
-//-----------------------------------------------------------------------------
-
-#include "cliparser.h"
-#include
-
-void **argtable = NULL;
-size_t argtableLen = 0;
-const char *programName = NULL;
-const char *programHint = NULL;
-const char *programHelp = NULL;
-char buf[500] = {0};
-
-int CLIParserInit(const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) {
- argtable = NULL;
- argtableLen = 0;
- programName = vprogramName;
- programHint = vprogramHint;
- programHelp = vprogramHelp;
- memset(buf, 0x00, 500);
- return 0;
-}
-
-int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
- int nerrors;
-
- argtable = vargtable;
- argtableLen = vargtableLen;
-
- /* verify the argtable[] entries were allocated sucessfully */
- if (arg_nullcheck(argtable) != 0) {
- /* NULL entries were detected, some allocations must have failed */
- printf("ERROR: Insufficient memory\n");
- return 2;
- }
- /* Parse the command line as defined by argtable[] */
- nerrors = arg_parse(argc, argv, argtable);
-
- /* special case: '--help' takes precedence over error reporting */
- if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record
- printf("Usage: %s", programName);
- arg_print_syntaxv(stdout, argtable, "\n");
- if (programHint)
- printf("%s\n\n", programHint);
- arg_print_glossary(stdout, argtable, " %-20s %s\n");
- printf("\n");
- if (programHelp)
- printf("%s \n", programHelp);
-
- return 1;
- }
-
- /* If the parser returned any errors then display them and exit */
- if (nerrors > 0) {
- /* Display the error details contained in the arg_end struct.*/
- arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName);
- printf("Try '%s --help' for more information.\n", programName);
-
- return 3;
- }
-
- return 0;
-}
-
-enum ParserState {
- PS_FIRST,
- PS_ARGUMENT,
- PS_OPTION,
-};
-
-#define isSpace(c)(c == ' ' || c == '\t')
-
-int CLIParserParseString(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
- return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false);
-}
-
-int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) {
- int argc = 0;
- char *argv[200] = {NULL};
-
- int len = strlen(str);
- char *bufptr = buf;
- char *spaceptr = NULL;
- enum ParserState state = PS_FIRST;
-
- argv[argc++] = bufptr;
- // param0 = program name
- memcpy(buf, programName, strlen(programName) + 1); // with 0x00
- bufptr += strlen(programName) + 1;
- if (len)
- argv[argc++] = bufptr;
-
- // parse params
- for (int i = 0; i < len; i++) {
- switch (state) {
- case PS_FIRST: // first char
- if (!clueData || str[i] == '-') { // first char before space is '-' - next element - option OR not "clueData" for not-option fields
- state = PS_OPTION;
-
- if (spaceptr) {
- bufptr = spaceptr;
- *bufptr = 0x00;
- bufptr++;
- argv[argc++] = bufptr;
- }
- }
- spaceptr = NULL;
- case PS_ARGUMENT:
- if (state == PS_FIRST)
- state = PS_ARGUMENT;
- if (isSpace(str[i])) {
- spaceptr = bufptr;
- state = PS_FIRST;
- }
- *bufptr = str[i];
- bufptr++;
- break;
- case PS_OPTION:
- if (isSpace(str[i])) {
- state = PS_FIRST;
-
- *bufptr = 0x00;
- bufptr++;
- argv[argc++] = bufptr;
- break;
- }
-
- *bufptr = str[i];
- bufptr++;
- break;
- }
- }
-
- return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec);
-}
-
-void CLIParserFree() {
- arg_freetable(argtable, argtableLen);
- argtable = NULL;
-
- return;
-}
-
-// convertors
-int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
- *datalen = 0;
-
- int ibuf = 0;
- uint8_t tmp_buf[256] = {0};
- int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX
- if (res || !ibuf)
- return res;
-
- switch (param_gethex_to_eol((char *)tmp_buf, 0, data, maxdatalen, datalen)) {
- case 1:
- printf("Parameter error: Invalid HEX value.\n");
- return 1;
- case 2:
- printf("Parameter error: parameter too large.\n");
- return 2;
- case 3:
- printf("Parameter error: Hex string must have even number of digits.\n");
- return 3;
- }
-
- return 0;
-}
-
-int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
- *datalen = 0;
- if (!argstr->count)
- return 0;
-
- uint8_t tmp_buf[256] = {0};
- int ibuf = 0;
-
- for (int i = 0; i < argstr->count; i++) {
- int len = strlen(argstr->sval[i]);
- memcpy(&tmp_buf[ibuf], argstr->sval[i], len);
- ibuf += len;
- }
- tmp_buf[ibuf] = 0;
-
- if (!ibuf)
- return 0;
-
- if (ibuf > maxdatalen)
- return 2;
-
- memcpy(data, tmp_buf, ibuf);
- *datalen = ibuf;
-
- return 0;
-}
-
-
diff --git a/pm3rdv4rrg/src/main/cpp/client/cliparser/cliparser.h b/pm3rdv4rrg/src/main/cpp/client/cliparser/cliparser.h
deleted file mode 100644
index 866ee07d..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cliparser/cliparser.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2017 Merlok
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Command line parser core commands
-//-----------------------------------------------------------------------------
-
-#ifndef __CLIPARSER_H
-#define __CLIPARSER_H
-#include "argtable3.h"
-#include "util.h"
-
-#define arg_param_begin arg_lit0("hH", "help", "This help")
-#define arg_param_end arg_end(20)
-
-#define arg_getsize(a) (sizeof(a) / sizeof(a[0]))
-#define arg_get_lit(n) (((struct arg_lit*)argtable[n])->count)
-#define arg_get_int_count(n)(((struct arg_int*)argtable[n])->count)
-#define arg_get_int(n) (((struct arg_int*)argtable[n])->ival[0])
-#define arg_get_int_def(n, def)(arg_get_int_count(n) ? (arg_get_int(n)) : (def))
-#define arg_get_str(n) ((struct arg_str*)argtable[n])
-#define arg_get_str_len(n) (strlen(((struct arg_str*)argtable[n])->sval[0]))
-
-#define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary)))
-#define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary)))
-
-#define CLIExecWithReturn(cmd, atbl, ifempty) if (CLIParserParseString(cmd, atbl, arg_getsize(atbl), ifempty)){CLIParserFree();return PM3_ESOFT;}
-#define CLIGetHexBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return PM3_ESOFT;}
-#define CLIGetHexWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return PM3_ESOFT;}
-#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return PM3_ESOFT;}
-
-int CLIParserInit(const char *vprogramName, const char *vprogramHint, const char *vprogramHelp);
-int CLIParserParseString(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec);
-int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData);
-int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec);
-void CLIParserFree(void);
-
-int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
-int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/cliparser/getopt.h b/pm3rdv4rrg/src/main/cpp/client/cliparser/getopt.h
deleted file mode 100644
index bf645feb..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cliparser/getopt.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
-/* $FreeBSD$ */
-
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-NetBSD
- *
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Dieter Baron and Thomas Klausner.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _GETOPT_H_
-#define _GETOPT_H_
-
-#include
-
-/*
- * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
- * getopt() is declared here too for GNU programs.
- */
-#define no_argument 0
-#define required_argument 1
-#define optional_argument 2
-
-struct option {
- /* name of long option */
- const char *name;
- /*
- * one of no_argument, required_argument, and optional_argument:
- * whether option takes an argument
- */
- int has_arg;
- /* if not NULL, set *flag to val when option found */
- int *flag;
- /* if flag not NULL, value to set *flag to; else return value */
- int val;
-};
-
-__BEGIN_DECLS
-int getopt_long(int, char *const *, const char *,
- const struct option *, int *);
-int getopt_long_only(int, char *const *, const char *,
- const struct option *, int *);
-#ifndef _GETOPT_DECLARED
-#define _GETOPT_DECLARED
-int getopt(int, char *const [], const char *);
-
-extern const char *optarg; /* getopt(3) external variables */
-extern int optind, opterr, optopt;
-#endif
-#ifndef _OPTRESET_DECLARED
-#define _OPTRESET_DECLARED
-extern int optreset; /* getopt(3) external variable */
-#endif
-__END_DECLS
-
-#endif /* !_GETOPT_H_ */
diff --git a/pm3rdv4rrg/src/main/cpp/client/cmdanalyse.c b/pm3rdv4rrg/src/main/cpp/client/cmdanalyse.c
deleted file mode 100644
index f7243fa3..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cmdanalyse.c
+++ /dev/null
@@ -1,950 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2016 iceman
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Analyse bytes commands
-//-----------------------------------------------------------------------------
-#include "cmdanalyse.h"
-
-#include // size_t
-#include
-#include // tolower
-#include // printf
-#include "commonutil.h" // reflect...
-#include "comms.h" // clearCommandBuffer
-#include "cmdparser.h" // command_t
-#include "ui.h" // PrintAndLog
-#include "crc.h"
-#include "crc16.h" // crc16 ccitt
-#include "tea.h"
-#include "legic_prng.h"
-#include "cmddata.h" // demodbuffer
-
-static int CmdHelp(const char *Cmd);
-
-static int usage_analyse_lcr(void) {
- PrintAndLogEx(NORMAL, "Specifying the bytes of a UID with a known LRC will find the last byte value");
- PrintAndLogEx(NORMAL, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX.");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: analyse lcr [h] ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " bytes to calc missing XOR in a LCR");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Examples:");
- PrintAndLogEx(NORMAL, " analyse lcr 04008064BA");
- PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A");
- return PM3_SUCCESS;
-}
-static int usage_analyse_checksum(void) {
- PrintAndLogEx(NORMAL, "The bytes will be added with eachother and than limited with the applied mask");
- PrintAndLogEx(NORMAL, "Finally compute ones' complement of the least significant bytes");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: analyse chksum [h] [v] b m ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " v suppress header");
- PrintAndLogEx(NORMAL, " b bytes to calc missing XOR in a LCR");
- PrintAndLogEx(NORMAL, " m bit mask to limit the outpuyt");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Examples:");
- PrintAndLogEx(NORMAL, " analyse chksum b 137AF00A0A0D m FF");
- PrintAndLogEx(NORMAL, "expected output: 0x61");
- return PM3_SUCCESS;
-}
-static int usage_analyse_crc(void) {
- PrintAndLogEx(NORMAL, "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: analyse crc [h] ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " bytes to calc crc");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Examples:");
- PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D");
- return PM3_SUCCESS;
-}
-static int usage_analyse_nuid(void) {
- PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: analyse hid [h] ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " input bytes (14 hexsymbols)");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Examples:");
- PrintAndLogEx(NORMAL, " analyse nuid 11223344556677");
- return PM3_SUCCESS;
-}
-static int usage_analyse_a(void) {
- PrintAndLogEx(NORMAL, "Iceman's personal garbage test command");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: analyse a [h] d ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " d bytes to write to devices");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Examples:");
- PrintAndLogEx(NORMAL, " analyse a d 137AF00A0A0D");
- return PM3_SUCCESS;
-}
-static int usage_analyse_demodbuffer(void) {
- PrintAndLogEx(NORMAL, "loads a binary string into demod buffer");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: analyse demodbuff [h] ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " Binary string to load");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Examples:");
- PrintAndLogEx(NORMAL, " analyse demodbuff 0011101001001011");
- return PM3_SUCCESS;
-}
-
-static uint8_t calculateLRC(uint8_t *bytes, uint8_t len) {
- uint8_t LRC = 0;
- for (uint8_t i = 0; i < len; i++)
- LRC ^= bytes[i];
- return LRC;
-}
-/*
-static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){
- -----------
- 0x9c | 1001 1100
- 0x97 | 1001 0111
- 0x72 | 0111 0010
- 0x5e | 0101 1110
- -----------------
- C32F 9d74
-
- return 0;
-}
-*/
-/*
-static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){
- return 0;
-}
-*/
-static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum += CRUMB(bytes[i], 0);
- sum += CRUMB(bytes[i], 2);
- sum += CRUMB(bytes[i], 4);
- sum += CRUMB(bytes[i], 6);
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumCrumbAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
- return (~calcSumCrumbAdd(bytes, len, mask) & mask);
-}
-static uint16_t calcSumNibbleAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum += NIBBLE_LOW(bytes[i]);
- sum += NIBBLE_HIGH(bytes[i]);
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumNibbleAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
- return (~calcSumNibbleAdd(bytes, len, mask) & mask);
-}
-static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum ^= CRUMB(bytes[i], 0);
- sum ^= CRUMB(bytes[i], 2);
- sum ^= CRUMB(bytes[i], 4);
- sum ^= CRUMB(bytes[i], 6);
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumNibbleXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum ^= NIBBLE_LOW(bytes[i]);
- sum ^= NIBBLE_HIGH(bytes[i]);
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumByteXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum ^= bytes[i];
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumByteAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum += bytes[i];
- }
- sum &= mask;
- return sum;
-}
-// Ones complement
-static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
- return (~calcSumByteAdd(bytes, len, mask) & mask);
-}
-
-static uint16_t calcSumByteSub(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint8_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum -= bytes[i];
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumByteSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
- return (~calcSumByteSub(bytes, len, mask) & mask);
-}
-static uint16_t calcSumNibbleSub(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint8_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum -= NIBBLE_LOW(bytes[i]);
- sum -= NIBBLE_HIGH(bytes[i]);
- }
- sum &= mask;
- return sum;
-}
-static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
- return (~calcSumNibbleSub(bytes, len, mask) & mask);
-}
-
-// BSD shift checksum 8bit version
-static uint16_t calcBSDchecksum8(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator
- sum += bytes[i]; // add next byte
- sum &= 0xFF; //
- }
- sum &= mask;
- return sum;
-}
-// BSD shift checksum 4bit version
-static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) {
- uint16_t sum = 0;
- for (uint8_t i = 0; i < len; i++) {
- sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
- sum += NIBBLE_HIGH(bytes[i]); // add high nibble
- sum &= 0xF; //
- sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
- sum += NIBBLE_LOW(bytes[i]); // add low nibble
- sum &= 0xF; //
- }
- sum &= mask;
- return sum;
-}
-
-// measuring LFSR maximum length
-static int CmdAnalyseLfsr(const char *Cmd) {
-
- uint8_t iv = param_get8ex(Cmd, 0, 0, 16);
- uint8_t find = param_get8ex(Cmd, 1, 0, 16);
-
- PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv);
- PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n", find);
-
- for (uint8_t i = 0x01; i < 0x30; i += 1) {
- legic_prng_init(iv);
- legic_prng_forward(i);
- uint16_t lfsr = legic_prng_get_bits(12); /* Any nonzero start state will work. */
- PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n", i, lfsr, 0x40 ^ lfsr, find ^ lfsr);
- }
- return 0;
-}
-static int CmdAnalyseLCR(const char *Cmd) {
- uint8_t data[50];
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_lcr();
-
- int len = 0;
- switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) {
- case 1:
- PrintAndLogEx(WARNING, "Invalid HEX value.");
- return 1;
- case 2:
- PrintAndLogEx(WARNING, "Too many bytes. Max %zu bytes", sizeof(data));
- return 1;
- case 3:
- PrintAndLogEx(WARNING, "Hex must have even number of digits.");
- return 1;
- }
- uint8_t finalXor = calculateLRC(data, len);
- PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X", data[len - 1], finalXor);
- return 0;
-}
-static int CmdAnalyseCRC(const char *Cmd) {
-
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc();
-
- int len = strlen(Cmd);
- if (len & 1) return usage_analyse_crc();
-
- // add 1 for null terminator.
- uint8_t *data = calloc(len + 1, sizeof(uint8_t));
- if (!data) return 1;
-
- if (param_gethex(Cmd, 0, data, len)) {
- free(data);
- return usage_analyse_crc();
- }
- len >>= 1;
-
- PrintAndLogEx(NORMAL, "\nTests with (%d) | %s", len, sprint_hex(data, len));
-
- // 51 f5 7a d6
- uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56
- init_table(CRC_LEGIC);
- uint8_t legic8 = CRC8Legic(uid, sizeof(uid));
- PrintAndLogEx(NORMAL, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, len, legic8), legic8);
- init_table(CRC_FELICA);
- PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len));
-
- PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code");
- PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L, 3));
- PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80));
- PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6));
-
- uint8_t b1, b2;
- // ISO14443 crc B
- compute_crc(CRC_14443_B, data, len, &b1, &b2);
- uint16_t crcBB_1 = b1 << 8 | b2;
- uint16_t bbb = Crc16ex(CRC_14443_B, data, len);
- PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb);
-
-
- // Test of CRC16, '123456789' string.
- //
-
- PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n");
- uint8_t dataStr[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
- legic8 = CRC8Legic(dataStr, sizeof(dataStr));
-
- //these below has been tested OK.
- PrintAndLogEx(NORMAL, "Confirmed CRC Implementations");
- PrintAndLogEx(NORMAL, "-------------------------------------\n");
- PrintAndLogEx(NORMAL, "CRC 8 based\n\n");
- PrintAndLogEx(NORMAL, "LEGIC: CRC8 : %X (C6 expected)", legic8);
- PrintAndLogEx(NORMAL, "MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr)));
- PrintAndLogEx(NORMAL, "-------------------------------------\n");
- PrintAndLogEx(NORMAL, "CRC16 based\n\n");
-
- // input from commandline
- PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", Crc16ex(CRC_CCITT, dataStr, sizeof(dataStr)));
-
- uint8_t poll[] = {0xb2, 0x4d, 0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
- PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", Crc16ex(CRC_FELICA, poll + 2, sizeof(poll) - 4));
- PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", Crc16ex(CRC_FELICA, poll + 2, sizeof(poll) - 2));
-
- uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01};
- PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", Crc16ex(CRC_ICLASS, sel_corr, sizeof(sel_corr) - 2));
- PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n");
-
- // ISO14443 crc A
- compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
- uint16_t crcAA = b1 << 8 | b2;
- PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, Crc16ex(CRC_14443_A, dataStr, sizeof(dataStr)));
-
- // ISO14443 crc B
- compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2);
- uint16_t crcBB = b1 << 8 | b2;
- PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, Crc16ex(CRC_14443_B, dataStr, sizeof(dataStr)));
-
- // ISO15693 crc (x.25)
- compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2);
- uint16_t crcCC = b1 << 8 | b2;
- PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, Crc16ex(CRC_15693, dataStr, sizeof(dataStr)));
-
- // ICLASS
- compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2);
- uint16_t crcDD = b1 << 8 | b2;
- PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, Crc16ex(CRC_ICLASS, dataStr, sizeof(dataStr)));
-
- // FeliCa
- compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2);
- uint16_t crcEE = b1 << 8 | b2;
- PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, Crc16ex(CRC_FELICA, dataStr, sizeof(dataStr)));
-
- free(data);
- return 0;
-}
-static int CmdAnalyseCHKSUM(const char *Cmd) {
-
- uint8_t data[50];
- uint8_t cmdp = 0;
- uint32_t mask = 0xFFFF;
- bool errors = false;
- bool useHeader = false;
- int len = 0;
- memset(data, 0x0, sizeof(data));
-
- while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
- switch (param_getchar(Cmd, cmdp)) {
- case 'b':
- case 'B':
- param_gethex_ex(Cmd, cmdp + 1, data, &len);
- if (len % 2) errors = true;
- len >>= 1;
- cmdp += 2;
- break;
- case 'm':
- case 'M':
- mask = param_get32ex(Cmd, cmdp + 1, 0, 16);
- cmdp += 2;
- break;
- case 'v':
- case 'V':
- useHeader = true;
- cmdp++;
- break;
- case 'h':
- case 'H':
- return usage_analyse_checksum();
- default:
- PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = true;
- break;
- }
- }
- //Validations
- if (errors || cmdp == 0) return usage_analyse_checksum();
-
- if (useHeader) {
- PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor");
- PrintAndLogEx(NORMAL, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |");
- PrintAndLogEx(NORMAL, "------------------+-------------+------------------+-----------------+--------------------");
- }
- PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n",
- calcSumByteAdd(data, len, mask)
- , calcSumNibbleAdd(data, len, mask)
- , calcSumCrumbAdd(data, len, mask)
- , calcSumByteSub(data, len, mask)
- , calcSumNibbleSub(data, len, mask)
- , calcSumByteAddOnes(data, len, mask)
- , calcSumNibbleAddOnes(data, len, mask)
- , calcSumCrumbAddOnes(data, len, mask)
- , calcSumByteSubOnes(data, len, mask)
- , calcSumNibbleSubOnes(data, len, mask)
- , calcSumByteXor(data, len, mask)
- , calcSumNibbleXor(data, len, mask)
- , calcSumCrumbXor(data, len, mask)
- , calcBSDchecksum8(data, len, mask)
- , calcBSDchecksum4(data, len, mask)
- );
- return 0;
-}
-
-static int CmdAnalyseDates(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- // look for datestamps in a given array of bytes
- PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!");
- return 0;
-}
-static int CmdAnalyseTEASelfTest(const char *Cmd) {
-
- uint8_t v[8], v_le[8];
- memset(v, 0x00, sizeof(v));
- memset(v_le, 0x00, sizeof(v_le));
- uint8_t *v_ptr = v_le;
-
- uint8_t cmdlen = strlen(Cmd);
- cmdlen = (sizeof(v) << 2 < cmdlen) ? sizeof(v) << 2 : cmdlen;
-
- if (param_gethex(Cmd, 0, v, cmdlen) > 0) {
- PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen);
- return 1;
- }
-
- SwapEndian64ex(v, 8, 4, v_ptr);
-
- // ENCRYPTION KEY:
- uint8_t key[16] = {0x55, 0xFE, 0xF6, 0x30, 0x62, 0xBF, 0x0B, 0xC1, 0xC9, 0xB3, 0x7C, 0x34, 0x97, 0x3E, 0x29, 0xFB };
- uint8_t keyle[16];
- uint8_t *key_ptr = keyle;
- SwapEndian64ex(key, sizeof(key), 4, key_ptr);
-
- PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8));
-
- tea_decrypt(v_ptr, key_ptr);
- PrintAndLogEx(NORMAL, "TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8));
-
- tea_encrypt(v_ptr, key_ptr);
- tea_encrypt(v_ptr, key_ptr);
- PrintAndLogEx(NORMAL, "TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8));
-
- return 0;
-}
-
-/*
-static char *pb(uint32_t b) {
- static char buf1[33] = {0};
- static char buf2[33] = {0};
- static char *s;
-
- if (s != buf1)
- s = buf1;
- else
- s = buf2;
-
- memset(s, 0, sizeof(buf1));
-
- uint32_t mask = 0x80000000;
- for (uint8_t i = 0; i < 32; i++) {
- s[i] = (mask & b) ? '1' : '0';
- mask >>= 1;
- }
- return s;
-}
-*/
-
-static int CmdAnalyseA(const char *Cmd) {
-
- return usage_analyse_a();
- /*
- PrintAndLogEx(NORMAL, "-- " _BLUE_("its my message") "\n");
- PrintAndLogEx(NORMAL, "-- " _RED_("its my message") "\n");
- PrintAndLogEx(NORMAL, "-- " _YELLOW_("its my message") "\n");
- PrintAndLogEx(NORMAL, "-- " _GREEN_("its my message") "\n");
-
- //uint8_t syncBit = 99;
- // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
- // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
- // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern
- // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
- # define SYNC_16BIT 0xB24D
- uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16);
- uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16);
- uint8_t byte_offset = 99;
- // reverse byte
- uint8_t rev = reflect8(bt);
- PrintAndLogEx(NORMAL, "input %02x | %02x \n", bt, rev);
- // add byte to shift register
- shiftReg = shiftReg << 8 | rev;
-
- PrintAndLogEx(NORMAL, "shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT);
-
- uint8_t n0 = 0, n1 = 0;
-
- n0 = (rev & (uint8_t)(~(0xFF >> (8 - 4)))) >> 4;
- n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4)));
-
- PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1));
- */
- /*
- hex(0xb24d shr 0) 0xB24D 0b1011001001001101
- hex(0xb24d shr 1) 0x5926
- hex(0xb24d shr 2) 0x2C93
- */
-
- /*
- for (int i = 0; i < 16; i++) {
- PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, ((shiftReg >> i) & 0xFFFF));
-
- // kolla om SYNC_PATTERN finns.
- if (((shiftReg >> 7) & 0xFFFF) == SYNC_16BIT) byte_offset = 7;
- else if (((shiftReg >> 6) & 0xFFFF) == SYNC_16BIT) byte_offset = 6;
- else if (((shiftReg >> 5) & 0xFFFF) == SYNC_16BIT) byte_offset = 5;
- else if (((shiftReg >> 4) & 0xFFFF) == SYNC_16BIT) byte_offset = 4;
- else if (((shiftReg >> 3) & 0xFFFF) == SYNC_16BIT) byte_offset = 3;
- else if (((shiftReg >> 2) & 0xFFFF) == SYNC_16BIT) byte_offset = 2;
- else if (((shiftReg >> 1) & 0xFFFF) == SYNC_16BIT) byte_offset = 1;
- else if (((shiftReg >> 0) & 0xFFFF) == SYNC_16BIT) byte_offset = 0;
-
- PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset);
- if (byte_offset != 99)
- break;
-
- shiftReg >>= 1;
- }
-
- uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset)));
- PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1));
-
- */
-
- /*
- pm3 --> da hex2bin 4db2 0100110110110010
- */
- //return 0;
- /*
- // split byte into two parts.
- uint8_t offset = 3, n0 = 0, n1 = 0;
- rev = 0xB2;
- for (uint8_t m=0; m<8; m++) {
- offset = m;
- n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset;
- n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset)));
-
- PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) );
- n0 = 0, n1 = 0;
- // PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) );
- //PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) );
- //PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) ));
- }
- return 0;
- // from A -- x bits into B and the rest into C.
-
- for ( uint8_t i=0; i<8; i++){
- PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) );
- b = a & (a & (0xFF >> (8-i)));
- a >>=1;
- }
-
- */
-// return 0;
-
- /*
- // 14443-A
- uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc
- uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc
- PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES" : "NO");
- PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES" : "NO");
-
- // 14443-B
- uint8_t u14b[] = {0x05, 0x00, 0x08, 0x39, 0x73};
- PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES" : "NO");
-
- // 15693 test
- uint8_t u15_c[] = {0x05, 0x00, 0x08, 0x39, 0x73}; // correct
- uint8_t u15_w[] = {0x05, 0x00, 0x08, 0x39, 0x72}; // wrong
- PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES" : "NO");
- PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES" : "NO");
-
- // iCLASS test - wrong crc , swapped bytes.
- uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43};
- uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01};
- PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES" : "NO");
- PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES" : "NO");
-
- // FeliCa test
- uint8_t felica_w[] = {0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7e};
- uint8_t felica_c[] = {0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
- PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES" : "NO");
- PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES" : "NO");
-
- PrintAndLogEx(NORMAL, "\n\n");
-
- return 0;
- */
- /*
- bool term = !isatty(STDIN_FILENO);
- if (!term) {
- char star[4];
- star[0] = '-';
- star[1] = '\\';
- star[2] = '|';
- star[3] = '/';
-
- for (uint8_t k=0; k<4; k = (k+1) % 4 ) {
- PrintAndLogEx(NORMAL, "\e[s%c\e[u", star[k]);
- fflush(stdout);
- if (kbd_enter_pressed()) {
- break;
- }
- }
- }
- */
-
-//piwi
-// uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000)
-// uid(2e086b1a) nt(230736f6) ks(0e0b0e0b090c0d02) nr(000000001)
-// uid(2e086b1a) nt(230736f6) ks(0e05060e01080b08) nr(000000002)
-//uint64_t d1[] = {0x2e086b1a, 0x230736f6, 0x0000001, 0x0e0b0e0b090c0d02};
-//uint64_t d2[] = {0x2e086b1a, 0x230736f6, 0x0000002, 0x0e05060e01080b08};
-
-// uid(17758822) nt(c0c69e59) ks(080105020705040e) nr(00000001)
-// uid(17758822) nt(c0c69e59) ks(01070a05050c0705) nr(00000002)
-//uint64_t d1[] = {0x17758822, 0xc0c69e59, 0x0000001, 0x080105020705040e};
-//uint64_t d2[] = {0x17758822, 0xc0c69e59, 0x0000002, 0x01070a05050c0705};
-
-// uid(6e442129) nt(8f699195) ks(090d0b0305020f02) nr(00000001)
-// uid(6e442129) nt(8f699195) ks(03030508030b0c0e) nr(00000002)
-// uid(6e442129) nt(8f699195) ks(02010f030c0d050d) nr(00000003)
-// uid(6e442129) nt(8f699195) ks(00040f0f0305030e) nr(00000004)
-//uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};
-//uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};
-
- /*
- uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)
- uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
- */
- /*
- uint64_t *keylistA = NULL, *keylistB = NULL;
- uint32_t keycountA = 0, keycountB = 0;
- // uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800};
- // uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f};
- uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
- uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
-
- keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4], &keylistA);
- keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB);
-
- switch (keycountA) {
- case 0:
- PrintAndLogEx(FAILED, "Key test A failed\n");
- break;
- case 1:
- PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]);
- break;
- }
- switch (keycountB) {
- case 0:
- PrintAndLogEx(FAILED, "Key test B failed\n");
- break;
- case 1:
- PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]);
- break;
- }
-
- free(keylistA);
- free(keylistB);
- */
-// qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
-// keycount = intersection(last_keylist, keylist);
-
- /*
- uint64_t keys[] = {
- 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
- 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
- 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
- 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9,
- 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
- 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
- 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
- 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
- };
-
- uint64_t keya[] = {
- 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
- 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
- 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
- 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9
- };
- uint64_t keyb[] = {
- 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
- 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
- 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
- 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
- };
-
- */
-
- /*
- uint64_t xor[] = {
- 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
- 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
- 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
- 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776,
- 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F,
- 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD,
- 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8,
- 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244
- };
-
-
- uint64_t xorA[] = {
- 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
- 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
- 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
- 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC
- };
- uint64_t xorB[] = {
- 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F,
- 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD,
- 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8,
- 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244
- };
- */
- /*
- // xor key A | xor key B
- 1 | 0DEFED88E531 | 2F87A1BDC230
- 2 | 7577AFA2E1BC | E43F502B984C
- 3 | 14D7D7BDBEC3 | 8A776AB752D9
- 4 | F5ABD3C6278B | 9A58D96A472F
- 5 | AABDFA08276F | EF3702E01916
- 6 | B77C275C10D6 | 48A03B01D007
- 7 | B6DD0B434080 | 14754B0D659E
- 8 | AAF2444499C6 | 009AD1868FDD
- 9 | 852D7F8EBF90 | 6082DB527C11
- 10 | 3108821DB92C | 4D666ADA4C0E
- 11 | B3756A1FB685 | 2D461D05F163
- 12 | DFE627C86A52 | 3596CFF0FEC8
- 13 | 5D3C093EF375 | 8CBD9258FE22
- 14 | 28C81D6FBF0E | 00D29A7B304B
- 15 | 1204DF4D3ECC | BC33DC6C9244
- */
-
- // generate xor table :)
- /*
- for (uint8_t i=0; i<31; i++){
- uint64_t a = keys[i] ^ keys[i+1];
- PrintAndLogEx(NORMAL, "%u | %012" PRIX64 " | \n", i, a);
- }
- */
-
- /*
- uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16);
- uint8_t uid[6] = {0};
- num_to_bytes(id,4,uid);
-
- uint8_t key_s0a[] = {
- uid[1] ^ uid[2] ^ uid[3] ^ 0x11,
- uid[1] ^ 0x72,
- uid[2] ^ 0x80,
- (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19,
- 0xA3,
- 0x2F
- };
-
- PrintAndLogEx(NORMAL, "UID | %s\n", sprint_hex(uid,4 ));
- PrintAndLogEx(NORMAL, "KEY A | %s\n", sprint_hex(key_s0a, 6));
-
- // arrays w all keys
- uint64_t foo[32] = {0};
-
- //A
- foo[0] = bytes_to_num(key_s0a, 6);
- //B
- //foo[16] = 0xcafe71411fbf;
- foo[16] = 0xeafe51411fbf;
-
- for (uint8_t i=0; i<15; i++){
- foo[i+1] = foo[i] ^ xorA[i];
- foo[i+16+1] = foo[i+16] ^ xorB[i];
-
- }
- for (uint8_t i=0; i<15; i++){
- uint64_t a = foo[i];
- uint64_t b = foo[i+16];
-
- PrintAndLogEx(NORMAL, "%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n",
- i,
- a,
- ( a == keya[i])?"ok":"err",
- b,
- ( b == keyb[i])?"ok":"err"
- );
- }
- */
-// return 0;
-}
-
-static void generate4bNUID(uint8_t *uid, uint8_t *nuid) {
- uint16_t crc;
- uint8_t b1, b2;
-
- compute_crc(CRC_14443_A, uid, 3, &b1, &b2);
- nuid[0] = (b2 & 0xE0) | 0xF;
- nuid[1] = b1;
- crc = b1;
- crc |= b2 << 8;
- crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true);
- nuid[2] = (crc >> 8) & 0xFF ;
- nuid[3] = crc & 0xFF;
-}
-
-static int CmdAnalyseNuid(const char *Cmd) {
- uint8_t nuid[4] = {0};
- uint8_t uid[7] = {0};
- int len = 0;
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_nuid();
-
- /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */
- /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */
- /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */
- if (cmdp == 't') {
- uint8_t uid_test1[] = {0x04, 0x0d, 0x68, 0x1a, 0xb5, 0x22, 0x81};
- uint8_t nuid_test1[] = {0x8f, 0x43, 0x0f, 0xef};
- uint8_t uid_test2[] = {0x04, 0x18, 0x3f, 0x09, 0x32, 0x1b, 0x85};
- uint8_t nuid_test2[] = {0x4f, 0x50, 0x5d, 0x7d};
- memcpy(uid, uid_test1, sizeof(uid));
- generate4bNUID(uid, nuid);
-
- bool test1 = (0 == memcmp(nuid, nuid_test1, sizeof(nuid)));
- PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_("OK") : _RED_("Fail"));
-
- memcpy(uid, uid_test2, sizeof(uid));
- generate4bNUID(uid, nuid);
- bool test2 = (0 == memcmp(nuid, nuid_test2, sizeof(nuid)));
- PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_("OK") : _RED_("Fail"));
- return 0;
- }
-
- param_gethex_ex(Cmd, 0, uid, &len);
- if (len % 2 || len != 14) return usage_analyse_nuid();
-
- generate4bNUID(uid, nuid);
-
- PrintAndLogEx(NORMAL, "UID | %s \n", sprint_hex(uid, 7));
- PrintAndLogEx(NORMAL, "NUID | %s \n", sprint_hex(nuid, 4));
- return 0;
-}
-
-static int CmdAnalyseDemodBuffer(const char *Cmd) {
-
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_demodbuffer();
-
- int bg = 0, en = 0;
- if (param_getptr(Cmd, &bg, &en, 0))
- return usage_analyse_demodbuffer();
-
- int len = MIN((en - bg + 1), MAX_DEMOD_BUF_LEN);
-
- // add 1 for null terminator.
- uint8_t *data = calloc(len + 1, sizeof(uint8_t));
- if (!data) return PM3_EMALLOC;
-
- for (int i = 0; bg <= en; bg++, i++) {
- char c = Cmd[bg];
- if (c == '1')
- DemodBuffer[i] = 1;
- if (c == '0')
- DemodBuffer[i] = 0;
-
- printf("%c", c);
- }
-
- printf("\n");
-
- DemodBufferLen = len;
- free(data);
- return PM3_SUCCESS;
-}
-
-static command_t CommandTable[] = {
- {"help", CmdHelp, AlwaysAvailable, "This help"},
- {"lcr", CmdAnalyseLCR, AlwaysAvailable, "Generate final byte for XOR LRC"},
- {"crc", CmdAnalyseCRC, AlwaysAvailable, "Stub method for CRC evaluations"},
- {"chksum", CmdAnalyseCHKSUM, AlwaysAvailable, "Checksum with adding, masking and one's complement"},
- {"dates", CmdAnalyseDates, AlwaysAvailable, "Look for datestamps in a given array of bytes"},
- {"tea", CmdAnalyseTEASelfTest, AlwaysAvailable, "Crypto TEA test"},
- {"lfsr", CmdAnalyseLfsr, AlwaysAvailable, "LFSR tests"},
- {"a", CmdAnalyseA, AlwaysAvailable, "num bits test"},
- {"nuid", CmdAnalyseNuid, AlwaysAvailable, "create NUID from 7byte UID"},
- {"demodbuff", CmdAnalyseDemodBuffer, AlwaysAvailable, "Load binary string to demodbuffer"},
- {NULL, NULL, NULL, NULL}
-};
-
-static int CmdHelp(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- CmdsHelp(CommandTable);
- return 0;
-}
-
-int CmdAnalyse(const char *Cmd) {
- clearCommandBuffer();
- return CmdsParse(CommandTable, Cmd);
-}
diff --git a/pm3rdv4rrg/src/main/cpp/client/cmdanalyse.h b/pm3rdv4rrg/src/main/cpp/client/cmdanalyse.h
deleted file mode 100644
index 4d223be1..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cmdanalyse.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2016 iceman
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Data and Graph commands
-//-----------------------------------------------------------------------------
-
-#ifndef CMDANALYSE_H__
-#define CMDANALYSE_H__
-
-#include "common.h"
-
-int CmdAnalyse(const char *Cmd);
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/cmdcrc.c b/pm3rdv4rrg/src/main/cpp/client/cmdcrc.c
deleted file mode 100644
index d51e1802..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cmdcrc.c
+++ /dev/null
@@ -1,517 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2015 iceman
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// CRC Calculations from the software reveng commands
-//-----------------------------------------------------------------------------
-#include "cmdcrc.h"
-
-#include
-#include
-#include
-#include
-
-#ifdef _WIN32
-# include
-# include
-# ifndef STDIN_FILENO
-# define STDIN_FILENO 0
-# endif /* STDIN_FILENO */
-#endif /* _WIN32 */
-
-#include "reveng/reveng.h"
-#include "ui.h"
-#include "util.h"
-
-#define MAX_ARGS 20
-
-static int split(char *str, char *arr[MAX_ARGS]) {
- int beginIndex = 0;
- int wordCnt = 0;
-
- while (1) {
- while (isspace(str[beginIndex])) {
- ++beginIndex;
- }
- if (str[beginIndex] == '\0') {
- break;
- }
- int endIndex = beginIndex;
- while (str[endIndex] && !isspace(str[endIndex])) {
- ++endIndex;
- }
- int len = endIndex - beginIndex;
- char *tmp = calloc(len + 1, sizeof(char));
- memcpy(tmp, &str[beginIndex], len);
- arr[wordCnt++] = tmp;
- beginIndex = endIndex;
- if (wordCnt == MAX_ARGS)
- break;
- }
- return wordCnt;
-}
-
-//returns array of model names and the count of models returning
-// as well as a width array for the width of each model
-int GetModels(char *Models[], int *count, uint8_t *width) {
- /* default values */
- static model_t model = MZERO;
-
- poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL;
- model_t pset = model;
-
- /* stdin must be binary */
-#ifdef _WIN32
- _setmode(STDIN_FILENO, _O_BINARY);
-#endif /* _WIN32 */
-
- SETBMP();
-
- if (width[0] == 0) { //reveng -D
- *count = mcount();
- if (!*count) {
- PrintAndLogEx(WARNING, "no preset models available");
- return 0;
- }
- for (int mode = 0; mode < *count; ++mode) {
- mbynum(&model, mode);
- mcanon(&model);
- size_t size = (model.name && *model.name) ? strlen(model.name) : 7;
- char *tmp = calloc(size + 1, sizeof(char));
- if (tmp == NULL) {
- PrintAndLogEx(WARNING, "out of memory?");
- return 0;
- }
- if (model.name != NULL) {
- memcpy(tmp, model.name, size);
- Models[mode] = tmp;
- width[mode] = plen(model.spoly);
- } else {
- free(tmp);
- }
- }
- mfree(&model);
- } else { //reveng -s
-
- int ibperhx = 8;//, obperhx = 8;
- int rflags = 0, uflags = 0; /* search and UI flags */
- if (~model.flags & P_MULXN) {
- PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models");
- return 0;
- }
- praloc(&model.spoly, (unsigned long)width[0]);
- praloc(&model.init, (unsigned long)width[0]);
- praloc(&model.xorout, (unsigned long)width[0]);
-
- if (!plen(model.spoly))
- palloc(&model.spoly, (unsigned long)width[0]);
- else
- width[0] = (uint8_t)plen(model.spoly);
-
- /* special case if qpoly is zero, search to end of range */
- if (!ptst(qpoly))
- rflags &= ~R_HAVEQ;
-
- int pass;
-
- /* if endianness not specified, try
- * little-endian then big-endian.
- * NB: crossed-endian algorithms will not be
- * searched.
- */
- /* scan against preset models */
- if (~uflags & C_NOPCK) {
- pass = 0;
- int Cnt = 0;
- do {
- int psets = mcount();
-
- while (psets) {
- mbynum(&pset, --psets);
-
- /* skip if different width, or refin or refout don't match */
- if (plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT))
- continue;
- /* skip if the preset doesn't match specified parameters */
- if (rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly))
- continue;
- if (rflags & R_HAVEI && psncmp(&model.init, &pset.init))
- continue;
- if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout))
- continue;
-
- //for additional args (not used yet, maybe future?)
- apoly = pclone(pset.xorout);
-
- if (pset.flags & P_REFOUT)
- prev(&apoly);
-
-
- for (qptr = apolys; qptr < pptr; ++qptr) {
- crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0);
- if (ptst(crc)) {
- pfree(&crc);
- break;
- }
- pfree(&crc);
- }
- pfree(&apoly);
-
- if (qptr == pptr) {
-
- /* the selected model solved all arguments */
- mcanon(&pset);
-
- size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7;
- //PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt);
- char *tmp = calloc(size + 1, sizeof(char));
- if (tmp == NULL) {
- PrintAndLogEx(WARNING, "out of memory?");
- return 0;
- }
- width[Cnt] = width[0];
- memcpy(tmp, pset.name, size);
- Models[Cnt++] = tmp;
- *count = Cnt;
- uflags |= C_RESULT;
- }
- }
- mfree(&pset);
-
- /* toggle refIn/refOut and reflect arguments */
- if (~rflags & R_HAVERI) {
- model.flags ^= P_REFIN | P_REFOUT;
- for (qptr = apolys; qptr < pptr; ++qptr) {
- prevch(qptr, ibperhx);
- }
- }
- } while (~rflags & R_HAVERI && ++pass < 2);
- }
- //got everything now free the memory...
-
- if (uflags & C_RESULT) {
- for (qptr = apolys; qptr < pptr; ++qptr) {
- pfree(qptr);
- }
- }
- if (uflags & C_NOBFS && ~rflags & R_HAVEP) {
- PrintAndLogEx(WARNING, "no models found");
- return 0;
- }
-
- if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)) {
- PrintAndLogEx(WARNING, "cannot search for crossed-endian models");
- return 0;
- }
- pass = 0;
- int args = 0;
- do {
- model_t *candmods = reveng(&model, qpoly, rflags, args, apolys);
- model_t *mptr = candmods;
- if (mptr && plen(mptr->spoly)) {
- uflags |= C_RESULT;
- }
- while (mptr && plen(mptr->spoly)) {
- mfree(mptr++);
- }
- free(candmods);
- if (~rflags & R_HAVERI) {
- model.flags ^= P_REFIN | P_REFOUT;
- for (qptr = apolys; qptr < pptr; ++qptr) {
- prevch(qptr, ibperhx);
- }
- }
- } while (~rflags & R_HAVERI && ++pass < 2);
-
- for (qptr = apolys; qptr < pptr; ++qptr) {
- pfree(qptr);
- }
- free(apolys);
- mfree(&model);
-
- if (~uflags & C_RESULT) {
- PrintAndLogEx(WARNING, "no models found");
- return 0;
- }
- }
- return 1;
-}
-
-//-c || -v
-//inModel = valid model name string - CRC-8
-//inHexStr = input hex string to calculate crc on
-//reverse = reverse calc option if true
-//endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified
-// l = little endian input and output, L = little endian output only, t = left justified}
-//result = calculated crc hex string
-int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result) {
- /* default values */
- static model_t model = MZERO;
-
- int ibperhx = 8, obperhx = 8;
-// int rflags = 0; // search flags
- int c;
- poly_t apoly, crc;
-
- char *string;
-
- // stdin must be binary
-#ifdef _WIN32
- _setmode(STDIN_FILENO, _O_BINARY);
-#endif /* _WIN32 */
-
- SETBMP();
- //set model
- c = mbynam(&model, inModel);
- if (!c) {
- PrintAndLogEx(ERR, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c);
- return 0;
- }
- if (c < 0) {
- PrintAndLogEx(WARNING, "no preset models available");
- return 0;
- }
-// rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX;
-
- //set flags
- switch (endian) {
- case 'b': /* b big-endian (RefIn = false, RefOut = false ) */
- model.flags &= ~P_REFIN;
- //rflags |= R_HAVERI;
- /* fall through: */
- case 'B': /* B big-endian output (RefOut = false) */
- model.flags &= ~P_REFOUT;
- //rflags |= R_HAVERO;
- mnovel(&model);
- /* fall through: */
- case 'r': /* r right-justified */
- model.flags |= P_RTJUST;
- break;
- case 'l': /* l little-endian input and output */
- model.flags |= P_REFIN;
- //rflags |= R_HAVERI;
- /* fall through: */
- case 'L': /* L little-endian output */
- model.flags |= P_REFOUT;
- //rflags |= R_HAVERO;
- mnovel(&model);
- /* fall through: */
- case 't': /* t left-justified */
- model.flags &= ~P_RTJUST;
- break;
- }
- /* canonicalise the model, so the one we dump is the one we
- * calculate with (not with -s, spoly may be blank which will
- * normalise to zero and clear init and xorout.)
- */
- mcanon(&model);
-
-
- if (reverse) {
- // v calculate reversed CRC
- /* Distinct from the -V switch as this causes
- * the arguments and output to be reversed as well.
- */
- // reciprocate Poly
- prcp(&model.spoly);
-
- /* mrev() does:
- * if(refout) prev(init); else prev(xorout);
- * but here the entire argument polynomial is
- * reflected, not just the characters, so RefIn
- * and RefOut are not inverted as with -V.
- * Consequently Init is the mirror image of the
- * one resulting from -V, and so we have:
- */
- if (~model.flags & P_REFOUT) {
- prev(&model.init);
- prev(&model.xorout);
- }
-
- // swap init and xorout
- apoly = model.init;
- model.init = model.xorout;
- model.xorout = apoly;
- }
- // c calculate CRC
-
- /* in the Williams model, xorout is applied after the refout stage.
- * as refout is part of ptostr(), we reverse xorout here.
- */
- if (model.flags & P_REFOUT)
- prev(&model.xorout);
-
- apoly = strtop(inHexStr, model.flags, ibperhx);
-
- if (reverse)
- prev(&apoly);
-
- crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags);
-
- if (reverse)
- prev(&crc);
-
- string = ptostr(crc, model.flags, obperhx);
- for (int i = 0; i < 50; i++) {
- result[i] = string[i];
- if (result[i] == 0) break;
- }
- free(string);
- pfree(&crc);
- pfree(&apoly);
- return 1;
-}
-/*
-//test call to RunModel
-static int CmdrevengTestC(const char *Cmd) {
- int cmdp = 0;
- char inModel[30] = {0x00};
- char inHexStr[30] = {0x00};
- char result[30];
- int dataLen;
- char endian = 0;
- dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel));
- if (dataLen < 4) return 0;
- dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr));
- if (dataLen < 4) return 0;
- bool reverse = (param_get8(Cmd, cmdp++)) ? true : false;
- endian = param_getchar(Cmd, cmdp++);
-
- //PrintAndLogEx(NORMAL, "mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse);
- int ans = RunModel(inModel, inHexStr, reverse, endian, result);
- if (!ans) return 0;
-
- PrintAndLogEx(SUCCESS, "result: %s", result);
- return 1;
-}
-*/
-//returns a calloced string (needs to be freed)
-static char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize) {
- char *tmp = calloc(len + 1, sizeof(char));
- for (uint8_t block = 0; block < (uint8_t)(len / blockSize); block++) {
- for (size_t i = 0; i < blockSize; i += 2) {
- tmp[i + (blockSize * block)] = inStr[(blockSize - 1 - i - 1) + (blockSize * block)];
- tmp[i + (blockSize * block) + 1] = inStr[(blockSize - 1 - i) + (blockSize * block)];
- }
- }
- return tmp;
-}
-
-// takes hex string in and searches for a matching result (hex string must include checksum)
-static int CmdrevengSearch(const char *Cmd) {
-
-#define NMODELS 106
-
- char inHexStr[100] = {0x00};
- int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr));
- if (dataLen < 4) return 0;
-
- // these two arrays, must match preset size.
- char *Models[NMODELS];
- uint8_t width[NMODELS] = {0};
- int count = 0;
-
- char result[30];
- char revResult[30];
- int ans = GetModels(Models, &count, width);
- bool found = false;
- if (!ans) return 0;
-
- // try each model and get result
- for (int i = 0; i < count; i++) {
- /*if (found) {
- free(Models[i]);
- continue;
- }*/
- // round up to # of characters in this model's crc
- uint8_t crcChars = ((width[i] + 7) / 8) * 2;
- // can't test a model that has more crc digits than our data
- if (crcChars >= dataLen)
- continue;
-
- PrintAndLogEx(DEBUG
- , "DEBUG: dataLen %d, crcChars %u, width[i] %u"
- , dataLen
- , crcChars
- , width[i]
- );
-
- if (crcChars == 0)
- continue;
-
- memset(result, 0, 30);
- char *inCRC = calloc(crcChars + 1, sizeof(char));
- memcpy(inCRC, inHexStr + (dataLen - crcChars), crcChars);
-
- char *outHex = calloc(dataLen - crcChars + 1, sizeof(char));
- memcpy(outHex, inHexStr, dataLen - crcChars);
-
- ans = RunModel(Models[i], outHex, false, 0, result);
- if (ans) {
- // test for match
- if (memcmp(result, inCRC, crcChars) == 0) {
- PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value: %s\n", Models[i], result);
- //optional - stop searching if found...
- found = true;
- } else {
- if (crcChars > 2) {
- char *swapEndian = SwapEndianStr(result, crcChars, crcChars);
- if (memcmp(swapEndian, inCRC, crcChars) == 0) {
- PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value endian swapped: %s\n", Models[i], swapEndian);
- // optional - stop searching if found...
- found = true;
- }
- free(swapEndian);
- }
- }
- }
- ans = RunModel(Models[i], outHex, true, 0, revResult);
- if (ans) {
- // test for match
- if (memcmp(revResult, inCRC, crcChars) == 0) {
- PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value: %s\n", Models[i], revResult);
- // optional - stop searching if found...
- found = true;
- } else {
- if (crcChars > 2) {
- char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars);
- if (memcmp(swapEndian, inCRC, crcChars) == 0) {
- PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value endian swapped: %s\n", Models[i], swapEndian);
- // optional - stop searching if found...
- found = true;
- }
- free(swapEndian);
- }
- }
- }
- free(inCRC);
- free(outHex);
- free(Models[i]);
- }
-
- if (!found) PrintAndLogEx(FAILED, "\nno matches found\n");
- return 1;
-}
-
-int CmdCrc(const char *Cmd) {
- char name[] = {"reveng "};
- char Cmd2[100 + 7];
- memcpy(Cmd2, name, 7);
- memcpy(Cmd2 + 7, Cmd, 100);
- char *argv[MAX_ARGS];
- int argc = split(Cmd2, argv);
-
- if (argc == 3 && memcmp(argv[1], "-g", 2) == 0) {
- CmdrevengSearch(argv[2]);
- } else {
- reveng_main(argc, argv);
- }
- for (int i = 0; i < argc; ++i) {
- free(argv[i]);
- }
- return 0;
-}
-
diff --git a/pm3rdv4rrg/src/main/cpp/client/cmdcrc.h b/pm3rdv4rrg/src/main/cpp/client/cmdcrc.h
deleted file mode 100644
index 957cd1ee..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cmdcrc.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2015 iceman
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// CRC Calculations from the software reveng commands
-//-----------------------------------------------------------------------------
-
-#ifndef CMDCRC_H__
-#define CMDCRC_H__
-
-#include "common.h"
-
-int CmdCrc(const char *Cmd);
-
-int GetModels(char *Models[], int *count, uint8_t *width);
-int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result);
-#endif
diff --git a/pm3rdv4rrg/src/main/cpp/client/cmddata.c b/pm3rdv4rrg/src/main/cpp/client/cmddata.c
deleted file mode 100644
index 613ce11e..00000000
--- a/pm3rdv4rrg/src/main/cpp/client/cmddata.c
+++ /dev/null
@@ -1,2344 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (C) 2010 iZsh
-//
-// iceman 2019
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Data and Graph commands
-//-----------------------------------------------------------------------------
-#include "cmddata.h"
-
-#include
-#include
-#include // for CmdNorm INT_MIN && INT_MAX
-#include // pow
-#include // tolower
-
-#include "commonutil.h" // ARRAYLEN
-#include "cmdparser.h" // for command_t
-#include "ui.h" // for show graph controls
-#include "graph.h" // for graph data
-#include "comms.h"
-#include "lfdemod.h" // for demod code
-#include "loclass/cipherutils.h" // for decimating samples in getsamples
-#include "cmdlfem4x.h" // askem410xdecode
-#include "fileutils.h" // searchFile
-
-uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
-size_t DemodBufferLen = 0;
-size_t g_DemodStartIdx = 0;
-int g_DemodClock = 0;
-
-static int CmdHelp(const char *Cmd);
-
-static int usage_data_save(void) {
- PrintAndLogEx(NORMAL, "Save trace from graph window , i.e. the GraphBuffer");
- PrintAndLogEx(NORMAL, "This is a text file with number -127 to 127. With the option `w` you can save it as wave file");
- PrintAndLogEx(NORMAL, "Filename should be without file extension");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: data save [h] [w] [f ]");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h this help");
- PrintAndLogEx(NORMAL, " w save as wave format (.wav)");
- PrintAndLogEx(NORMAL, " f save file name");
- PrintAndLogEx(NORMAL, "Samples:");
- PrintAndLogEx(NORMAL, " data save f mytrace - save graphbuffer to file");
- PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file");
- return PM3_SUCCESS;
-}
-static int usage_data_scale(void) {
- PrintAndLogEx(NORMAL, "Set cursor display scale.");
- PrintAndLogEx(NORMAL, "Setting the scale makes the differential `dt` reading between the yellow and purple markers meaningful. ");
- PrintAndLogEx(NORMAL, "once the scale is set, the differential reading between brackets is the time duration in seconds.");
- PrintAndLogEx(NORMAL, "For example, if acquiring in 125kHz, use scale 125.");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Usage: data scale [h] ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h this help");
- PrintAndLogEx(NORMAL, " sets scale of carrier frequency expressed in kHz");
- PrintAndLogEx(NORMAL, "Samples:");
- PrintAndLogEx(NORMAL, " data scale 125 - if sampled in 125kHz");
- return PM3_SUCCESS;
-}
-static int usage_data_printdemodbuf(void) {
- PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h this help");
- PrintAndLogEx(NORMAL, " i invert Demodbuffer before printing");
- PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)");
- PrintAndLogEx(NORMAL, " o enter offset in # of bits");
- PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively");
- PrintAndLogEx(NORMAL, " s strip leading zeroes, i.e. set offset to first bit equal to one");
- return PM3_SUCCESS;
-}
-static int usage_data_manrawdecode(void) {
- PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]");
- PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively");
- PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)");
- PrintAndLogEx(NORMAL, " [invert] invert output");
- PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer");
- return PM3_SUCCESS;
-}
-static int usage_data_biphaserawdecode(void) {
- PrintAndLogEx(NORMAL, "Usage: data biphaserawdecode [offset] [invert] [maxErr]");
- PrintAndLogEx(NORMAL, " Converts 10 or 01 to 1 and 11 or 00 to 0");
- PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)");
- PrintAndLogEx(NORMAL, " --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, " [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position");
- PrintAndLogEx(NORMAL, " [invert <0|1>], set to 1 to invert output");
- PrintAndLogEx(NORMAL, " [maxErr int], set max errors tolerated - default=20");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, " Example: data biphaserawdecode = decode biphase bitstream from the demodbuffer");
- PrintAndLogEx(NORMAL, " Example: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |");
- PrintAndLogEx(NORMAL, " [modulation] as 2 char,");
- PrintAndLogEx(NORMAL, " "_YELLOW_("ab")"- ask/biphase");
- PrintAndLogEx(NORMAL, " "_YELLOW_("am")"- ask/manchester");
- PrintAndLogEx(NORMAL, " "_YELLOW_("ar")"- ask/raw");
- PrintAndLogEx(NORMAL, " "_YELLOW_("fs")"- fsk");
- PrintAndLogEx(NORMAL, " "_YELLOW_("nr")"- nrz/direct");
- PrintAndLogEx(NORMAL, " "_YELLOW_("p1")"- psk1");
- PrintAndLogEx(NORMAL, " "_YELLOW_("p2")"- psk2");
- PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation");
- PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod fs h = print help specific to fsk demod");
- PrintAndLogEx(NORMAL, " data rawdemod fs = demod GraphBuffer using: fsk - autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_am(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]");
- PrintAndLogEx(NORMAL, " ['s'] optional, check for Sequence Terminator");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect");
- PrintAndLogEx(NORMAL, " , 1 to invert output");
- PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100");
- PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)");
- PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod am = demod an ask/manchester tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32");
- PrintAndLogEx(NORMAL, " data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_ab(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] ");
- PrintAndLogEx(NORMAL, " [offset], offset to begin biphase, default=0");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect");
- PrintAndLogEx(NORMAL, " , 1 to invert output");
- PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100");
- PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)");
- PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp");
- PrintAndLogEx(NORMAL, " NOTE: can be entered as second or third argument");
- PrintAndLogEx(NORMAL, " NOTE: can be entered as first, second or last argument");
- PrintAndLogEx(NORMAL, " NOTE: any other arg must have previous args set to work");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod ab = demod an ask/biph tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified");
- PrintAndLogEx(NORMAL, " data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32");
- PrintAndLogEx(NORMAL, " data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
- PrintAndLogEx(NORMAL, " data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_ar(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect");
- PrintAndLogEx(NORMAL, " , 1 to invert output");
- PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100");
- PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)");
- PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod ar = demod an ask tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod ar a = demod an ask tag from GraphBuffer, amplified");
- PrintAndLogEx(NORMAL, " data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32");
- PrintAndLogEx(NORMAL, " data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
- PrintAndLogEx(NORMAL, " data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_fs(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod fs [clock] [fchigh] [fclow]");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, omit for autodetect.");
- PrintAndLogEx(NORMAL, " , 1 for invert output, can be used even if the clock is omitted");
- PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect");
- PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect");
- PrintAndLogEx(NORMAL, " data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc");
- PrintAndLogEx(NORMAL, " data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output");
- PrintAndLogEx(NORMAL, " data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc");
- PrintAndLogEx(NORMAL, " data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_nr(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod nr [clock] <0|1> [maxError]");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect.");
- PrintAndLogEx(NORMAL, " , 1 for invert output");
- PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100.");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod nr = demod a nrz/direct tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32");
- PrintAndLogEx(NORMAL, " data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_p1(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod p1 [clock] <0|1> [maxError]");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect.");
- PrintAndLogEx(NORMAL, " , 1 for invert output");
- PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100.");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod p1 = demod a psk1 tag from GraphBuffer");
- PrintAndLogEx(NORMAL, " data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32");
- PrintAndLogEx(NORMAL, " data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data");
- PrintAndLogEx(NORMAL, " data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
- return PM3_SUCCESS;
-}
-static int usage_data_rawdemod_p2(void) {
- PrintAndLogEx(NORMAL, "Usage: data rawdemod p2 [clock] <0|1> [maxError]");
- PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect.");
- PrintAndLogEx(NORMAL, " , 1 for invert output");
- PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100.");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, "Example:");
- PrintAndLogEx(NORMAL, " data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock");
- PrintAndLogEx(NORMAL, " data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32");
- PrintAndLogEx(NORMAL, " data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output");
- PrintAndLogEx(NORMAL, " data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output");
- PrintAndLogEx(NORMAL, " data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors");
- return PM3_SUCCESS;
-}
-static int usage_data_autocorr(void) {
- PrintAndLogEx(NORMAL, "Autocorrelate is used to detect repeating sequences. We use it as detection of length in bits a message inside the signal is");
- PrintAndLogEx(NORMAL, "Usage: data autocorr w [g]");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " w window length for correlation - default = 4000");
- PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)");
- return PM3_SUCCESS;
-}
-static int usage_data_undecimate(void) {
- PrintAndLogEx(NORMAL, "Usage: data undec [factor]");
- PrintAndLogEx(NORMAL, "This function performs un-decimation, by repeating each sample N times");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " factor The number of times to repeat each sample.[default:2]");
- PrintAndLogEx(NORMAL, "Example: 'data undec 3'");
- return PM3_SUCCESS;
-}
-static int usage_data_detectclock(void) {
- PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] ");
- PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of");
- PrintAndLogEx(NORMAL, " , specify the clock (optional - to get best start position only)");
- PrintAndLogEx(NORMAL, " 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk");
- PrintAndLogEx(NORMAL, "");
- PrintAndLogEx(NORMAL, " Example: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer");
- PrintAndLogEx(NORMAL, " data detectclock f = detect the clock of an fsk modulated wave in the GraphBuffer");
- PrintAndLogEx(NORMAL, " data detectclock p = detect the clock of an psk modulated wave in the GraphBuffer");
- PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer");
- return PM3_SUCCESS;
-}
-static int usage_data_hex2bin(void) {
- PrintAndLogEx(NORMAL, "Usage: data hex2bin ");
- PrintAndLogEx(NORMAL, " This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
- return PM3_SUCCESS;
-}
-static int usage_data_bin2hex(void) {
- PrintAndLogEx(NORMAL, "Usage: data bin2hex ");
- PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)");
- return PM3_SUCCESS;
-}
-static int usage_data_buffclear(void) {
- PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside");
- PrintAndLogEx(NORMAL, "Usage: data buffclear [h]");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- return PM3_SUCCESS;
-}
-static int usage_data_fsktonrz() {
- PrintAndLogEx(NORMAL, "Usage: data fsktonrz c l f ");
- PrintAndLogEx(NORMAL, "Options:");
- PrintAndLogEx(NORMAL, " h This help");
- PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)");
- PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)");
- PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)");
- return PM3_SUCCESS;
-}
-
-//set the demod buffer with given array of binary (one bit per byte)
-//by marshmellow
-void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx) {
- if (buff == NULL) return;
-
- if (size > MAX_DEMOD_BUF_LEN - start_idx)
- size = MAX_DEMOD_BUF_LEN - start_idx;
-
- for (size_t i = 0; i < size; i++)
- DemodBuffer[i] = buff[start_idx++];
-
- DemodBufferLen = size;
-}
-
-bool getDemodBuff(uint8_t *buff, size_t *size) {
- if (buff == NULL) return false;
- if (size == NULL) return false;
- if (*size == 0) return false;
-
- *size = (*size > DemodBufferLen) ? DemodBufferLen : *size;
-
- memcpy(buff, DemodBuffer, *size);
- return true;
-}
-
-// include
-// Root mean square
-/*
-static double rms(double *v, size_t n) {
- double sum = 0.0;
- for (size_t i = 0; i < n; i++)
- sum += v[i] * v[i];
- return sqrt(sum / n);
-}
-
-static int cmp_int(const void *a, const void *b) {
- if (*(const int *)a < * (const int *)b)
- return -1;
- else
- return *(const int *)a > *(const int *)b;
-}
-static int cmp_uint8(const void *a, const void *b) {
- if (*(const uint8_t *)a < * (const uint8_t *)b)
- return -1;
- else
- return *(const uint8_t *)a > *(const uint8_t *)b;
-}
-// Median of a array of values
-
-static double median_int(int *src, size_t size) {
- qsort(src, size, sizeof(int), cmp_int);
- return 0.5 * (src[size / 2] + src[(size - 1) / 2]);
-}
-static double median_uint8(uint8_t *src, size_t size) {
- qsort(src, size, sizeof(uint8_t), cmp_uint8);
- return 0.5 * (src[size / 2] + src[(size - 1) / 2]);
-}
-*/
-// function to compute mean for a series
-static double compute_mean(const int *data, size_t n) {
- double mean = 0.0;
- for (size_t i = 0; i < n; i++)
- mean += data[i];
- mean /= n;
- return mean;
-}
-
-// function to compute variance for a series
-static double compute_variance(const int *data, size_t n) {
- double variance = 0.0;
- double mean = compute_mean(data, n);
-
- for (size_t i = 0; i < n; i++)
- variance += pow((data[i] - mean), 2.0);
-
- variance /= n;
- return variance;
-}
-
-// Function to compute autocorrelation for a series
-// Author: Kenneth J. Christensen
-// - Corrected divide by n to divide (n - lag) from Tobias Mueller
-/*
-static double compute_autoc(const int *data, size_t n, int lag) {
- double autocv = 0.0; // Autocovariance value
- double ac_value; // Computed autocorrelation value to be returned
- double variance; // Computed variance
- double mean;
-
- mean = compute_mean(data, n);
- variance = compute_variance(data, n);
-
- for (size_t i=0; i < (n - lag); i++)
- autocv += (data[i] - mean) * (data[i+lag] - mean);
-
- autocv = (1.0 / (n - lag)) * autocv;
-
- // Autocorrelation is autocovariance divided by variance
- ac_value = autocv / variance;
- return ac_value;
-}
-*/
-
-// option '1' to save DemodBuffer any other to restore
-void save_restoreDB(uint8_t saveOpt) {
- static uint8_t SavedDB[MAX_DEMOD_BUF_LEN];
- static size_t SavedDBlen;
- static bool DB_Saved = false;
- static size_t savedDemodStartIdx = 0;
- static int savedDemodClock = 0;
-
- if (saveOpt == GRAPH_SAVE) { //save
-
- memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer));
- SavedDBlen = DemodBufferLen;
- DB_Saved = true;
- savedDemodStartIdx = g_DemodStartIdx;
- savedDemodClock = g_DemodClock;
- } else if (DB_Saved) { //restore
-
- memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer));
- DemodBufferLen = SavedDBlen;
- g_DemodClock = savedDemodClock;
- g_DemodStartIdx = savedDemodStartIdx;
- }
-}
-
-static int CmdSetDebugMode(const char *Cmd) {
- int demod = 0;
- sscanf(Cmd, "%i", &demod);
- g_debugMode = (uint8_t)demod;
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-// max output to 512 bits if we have more
-// doesn't take inconsideration where the demod offset or bitlen found.
-void printDemodBuff(void) {
- int len = DemodBufferLen;
- if (len < 1) {
- PrintAndLogEx(INFO, "(printDemodBuff) no bits found in demod buffer");
- return;
- }
- if (len > 512) len = 512;
-
- PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 32));
-}
-
-int CmdPrintDemodBuff(const char *Cmd) {
- bool hexMode = false;
- bool errors = false;
- bool lstrip = false;
- bool invert = false;
- uint32_t offset = 0;
- uint32_t length = 512;
- char cmdp = 0;
- while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
- switch (tolower(param_getchar(Cmd, cmdp))) {
- case 'h':
- return usage_data_printdemodbuf();
- case 'x':
- hexMode = true;
- cmdp++;
- break;
- case 'o':
- offset = param_get32ex(Cmd, cmdp + 1, 0, 10);
- if (!offset) errors = true;
- cmdp += 2;
- break;
- case 'l':
- length = param_get32ex(Cmd, cmdp + 1, 512, 10);
- if (!length) errors = true;
- cmdp += 2;
- break;
- case 's':
- lstrip = true;
- cmdp++;
- break;
- case 'i':
- invert = true;
- cmdp++;
- break;
- default:
- PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = true;
- break;
- }
- }
- //Validations
- if (errors) return usage_data_printdemodbuf();
-
- if (DemodBufferLen == 0) {
- PrintAndLogEx(WARNING, "Demodbuffer is empty");
- return PM3_ESOFT;
- }
- if (lstrip) {
- char *buf = (char *)(DemodBuffer + offset);
- length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length;
- uint32_t i;
- for (i = 0; i < length; i++) {
- if (buf[i] == 1) break;
- }
- offset += i;
- }
- length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length;
-
- if (invert) {
- char *buf = (char *)(DemodBuffer + offset);
- for (uint32_t i = 0; i < length; i++) {
- if (buf[i] == 1)
- buf[i] = 0;
- else {
- if (buf[i] == 0)
- buf[i] = 1;
- }
- }
- }
-
- if (hexMode) {
- char *buf = (char *)(DemodBuffer + offset);
- char hex[512] = {0x00};
- int numBits = binarraytohex(hex, sizeof(hex), buf, length);
- if (numBits == 0) {
- return PM3_ESOFT;
- }
- PrintAndLogEx(SUCCESS, "DemodBuffer: %s", hex);
- } else {
- PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 32));
- }
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-//this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer
-int CmdGetBitStream(const char *Cmd) {
- CmdHpf(Cmd);
- for (uint32_t i = 0; i < GraphTraceLen; i++)
- GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0;
-
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-static int CmdConvertBitStream(const char *Cmd) {
-
- if (isGraphBitstream()) {
- convertGraphFromBitstream();
- } else {
- // get high, low
- convertGraphFromBitstreamEx(-126, -127);
- }
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-//Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
-// (amp may not be needed anymore)
-//verbose will print results and demoding messages
-//emSearch will auto search for EM410x format in bitstream
-//askType switches decode: ask/raw = 0, ask/manchester = 1
-int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
- int invert = 0;
- int clk = 0;
- int maxErr = 100;
- size_t maxLen = 0;
- uint8_t askamp = 0;
- char amp = tolower(param_getchar(Cmd, 0));
-
- sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &);
-
- if (!maxLen) maxLen = BIGBUF_SIZE;
-
- if (invert != 0 && invert != 1) {
- PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd);
- return PM3_EINVARG;
- }
-
- if (clk == 1) {
- invert = 1;
- clk = 0;
- }
- uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
- if (bits == NULL) {
- return PM3_EMALLOC;
- }
-
- size_t BitLen = getFromGraphBuf(bits);
-
- PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) #samples from graphbuff: %zu", BitLen);
-
- if (BitLen < 255) {
- free(bits);
- return PM3_ESOFT;
- }
-
- if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
-
- int foundclk = 0;
-
- //amplify signal before ST check
- if (amp == 'a') {
- askAmp(bits, BitLen);
- }
-
- size_t ststart = 0, stend = 0;
-// if (*stCheck)
- bool st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend);
-
- if (clk == 0) {
- if (foundclk == 32 || foundclk == 64) {
- clk = foundclk;
- }
- }
-
- if (st) {
- *stCheck = st;
- CursorCPos = ststart;
- CursorDPos = stend;
- if (verbose)
- PrintAndLogEx(DEBUG, "Found Sequence Terminator - First one is shown by orange / blue graph markers");
- }
-
- int startIdx = 0;
- int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx);
-
- if (errCnt < 0 || BitLen < 16) { //if fatal error (or -1)
- PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%zu, clock:%d", errCnt, (invert) ? 'Y' : 'N', BitLen, clk);
- free(bits);
- return PM3_ESOFT;
- }
-
- if (errCnt > maxErr) {
- PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%zu, clock:%d", errCnt, BitLen, clk);
- free(bits);
- return PM3_ESOFT;
- }
-
- if (verbose) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%zu, start index %d", clk, invert, BitLen, startIdx);
-
- //output
- setDemodBuff(bits, BitLen, 0);
- setClockGrid(clk, startIdx);
-
- if (verbose) {
- if (errCnt > 0)
- PrintAndLogEx(DEBUG, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt);
- if (askType)
- PrintAndLogEx(DEBUG, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk);
- else
- PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk);
-
- printDemodBuff();
- }
- uint64_t lo = 0;
- uint32_t hi = 0;
- if (emSearch)
- AskEm410xDecode(true, &hi, &lo);
-
- free(bits);
- return PM3_SUCCESS;
-}
-int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
- bool st = false;
- return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
-}
-
-//by marshmellow
-//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
-//attempts to demodulate ask while decoding manchester
-//prints binary found and saves in graphbuffer for further commands
-static int Cmdaskmandemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am();
-
- bool st = true;
- if (Cmd[0] == 's')
- return ASKDemod_ext(Cmd++, true, true, 1, &st);
- else if (Cmd[1] == 's')
- return ASKDemod_ext(Cmd += 2, true, true, 1, &st);
-
- return ASKDemod(Cmd, true, true, 1);
-}
-
-//by marshmellow
-//manchester decode
-//stricktly take 10 and 01 and convert to 0 and 1
-static int Cmdmandecoderaw(const char *Cmd) {
- size_t size = 0;
- int high = 0, low = 0;
- size_t i = 0;
- uint16_t errCnt = 0;
- int invert = 0, maxErr = 20;
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode();
-
- if (DemodBufferLen == 0) return PM3_ESOFT;
-
- uint8_t bits[MAX_DEMOD_BUF_LEN] = {0};
-
- for (; i < DemodBufferLen; ++i) {
- if (DemodBuffer[i] > high)
- high = DemodBuffer[i];
- else if (DemodBuffer[i] < low)
- low = DemodBuffer[i];
- bits[i] = DemodBuffer[i];
- }
-
- if (high > 7 || low < 0) {
- PrintAndLogEx(ERR, "Error: please raw demod the wave first then manchester raw decode");
- return PM3_ESOFT;
- }
-
- sscanf(Cmd, "%i %i", &invert, &maxErr);
- size = i;
- uint8_t alignPos = 0;
- errCnt = manrawdecode(bits, &size, invert, &alignPos);
- if (errCnt >= maxErr) {
- PrintAndLogEx(ERR, "Too many errors: %u", errCnt);
- return PM3_ESOFT;
- }
-
- PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:", errCnt);
- PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 32));
-
- if (errCnt == 0) {
- uint64_t id = 0;
- uint32_t hi = 0;
- size_t idx = 0;
- if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1) {
- //need to adjust to set bitstream back to manchester encoded data
- //setDemodBuff(bits, size, idx);
- printEM410x(hi, id);
- }
- }
- return PM3_SUCCESS;
-}
-
-/*
- * @author marshmellow
- * biphase decode
- * decodes 01 or 10 -> ZERO
- * 11 or 00 -> ONE
- * param offset adjust start position
- * param invert invert output
- * param masxErr maximum tolerated errors
- */
-static int CmdBiphaseDecodeRaw(const char *Cmd) {
- size_t size = 0;
- int offset = 0, invert = 0, maxErr = 20, errCnt = 0;
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_biphaserawdecode();
-
- sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr);
- if (DemodBufferLen == 0) {
- PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first");
- return PM3_ESOFT;
- }
-
- uint8_t bits[MAX_DEMOD_BUF_LEN] = {0};
- size = sizeof(bits);
- if (!getDemodBuff(bits, &size)) return PM3_ESOFT;
-
- errCnt = BiphaseRawDecode(bits, &size, &offset, invert);
- if (errCnt < 0) {
- PrintAndLogEx(ERR, "Error during decode:%d", errCnt);
- return PM3_ESOFT;
- }
- if (errCnt > maxErr) {
- PrintAndLogEx(ERR, "Too many errors attempting to decode: %d", errCnt);
- return PM3_ESOFT;
- }
-
- if (errCnt > 0)
- PrintAndLogEx(WARNING, "# Errors found during Demod (shown as " _YELLOW_("7")" in bit stream): %d", errCnt);
-
- PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:", offset, invert);
- PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 32));
-
- //remove first bit from raw demod
- if (offset)
- setDemodBuff(DemodBuffer, DemodBufferLen - offset, offset);
-
- setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock * offset / 2);
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-// - ASK Demod then Biphase decode GraphBuffer samples
-int ASKbiphaseDemod(const char *Cmd, bool verbose) {
- //ask raw demod GraphBuffer first
- int offset = 0, clk = 0, invert = 0, maxErr = 50;
- sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
-
- uint8_t BitStream[MAX_DEMOD_BUF_LEN];
- size_t size = getFromGraphBuf(BitStream);
- if (size == 0) {
- PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf");
- return PM3_ESOFT;
- }
- int startIdx = 0;
- //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
- int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx);
- if (errCnt < 0 || errCnt > maxErr) {
- PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk);
- return PM3_ESOFT;
- }
-
- //attempt to Biphase decode BitStream
- errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert);
- if (errCnt < 0) {
- if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt);
- return PM3_ESOFT;
- }
- if (errCnt > maxErr) {
- if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt);
- return PM3_ESOFT;
- }
-
- //success set DemodBuffer and return
- setDemodBuff(BitStream, size, 0);
- setClockGrid(clk, startIdx + clk * offset / 2);
- if (g_debugMode || verbose) {
- PrintAndLogEx(DEBUG, "Biphase Decoded using offset %d | clock %d | #errors %d | start index %d\ndata\n", offset, clk, errCnt, (startIdx + clk * offset / 2));
- printDemodBuff();
- }
- return PM3_SUCCESS;
-}
-//by marshmellow - see ASKbiphaseDemod
-static int Cmdaskbiphdemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab();
-
- return ASKbiphaseDemod(Cmd, true);
-}
-
-//by marshmellow - see ASKDemod
-static int Cmdaskrawdemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar();
-
- return ASKDemod(Cmd, true, false, 0);
-}
-
-int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveGrph, bool verbose) {
- // sanity check
- if (window > len) window = len;
-
- if (verbose) PrintAndLogEx(INFO, "performing " _YELLOW_("%zu") "correlations", GraphTraceLen - window);
-
- //test
- double autocv = 0.0; // Autocovariance value
- size_t correlation = 0;
- int lastmax = 0;
-
- // in, len, 4000
- double mean = compute_mean(in, len);
- // Computed variance
- double variance = compute_variance(in, len);
-
- int *correl_buf = calloc(MAX_GRAPH_TRACE_LEN, sizeof(int));
-
- for (size_t i = 0; i < len - window; ++i) {
-
- for (size_t j = 0; j < (len - i); j++) {
- autocv += (in[j] - mean) * (in[j + i] - mean);
- }
- autocv = (1.0 / (len - i)) * autocv;
-
- correl_buf[i] = autocv;
-
- // Computed autocorrelation value to be returned
- // Autocorrelation is autocovariance divided by variance
- double ac_value = autocv / variance;
-
- // keep track of which distance is repeating.
- if (ac_value > 1) {
- correlation = i - lastmax;
- lastmax = i;
- }
- }
-
- //
- int hi = 0, idx = 0;
- int distance = 0, hi_1 = 0, idx_1 = 0;
- for (size_t i = 0; i <= len; ++i) {
- if (correl_buf[i] > hi) {
- hi = correl_buf[i];
- idx = i;
- }
- }
-
- for (size_t i = idx + 1; i <= window; ++i) {
- if (correl_buf[i] > hi_1) {
- hi_1 = correl_buf[i];
- idx_1 = i;
- }
- }
-
- int foo = ABS(hi - hi_1);
- int bar = (int)((int)((hi + hi_1) / 2) * 0.04);
-
- if (verbose && foo < bar) {
- distance = idx_1 - idx;
- PrintAndLogEx(SUCCESS, "possible visible correlation "_YELLOW_("%4d") "samples", distance);
- } else if (verbose && (correlation > 1)) {
- PrintAndLogEx(SUCCESS, "possible correlation " _YELLOW_("%4zu") "samples", correlation);
- } else {
- PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size");
- }
-
- int retval = correlation;
- if (SaveGrph) {
- //GraphTraceLen = GraphTraceLen - window;
- memcpy(out, correl_buf, len * sizeof(int));
- if (distance > 0) {
- setClockGrid(distance, idx);
- retval = distance;
- } else
- setClockGrid(correlation, idx);
-
- CursorCPos = idx_1;
- CursorDPos = idx_1 + retval;
- DemodBufferLen = 0;
- RepaintGraphWindow();
- }
- free(correl_buf);
- return retval;
-}
-
-static int CmdAutoCorr(const char *Cmd) {
-
- uint32_t window = 4000;
- uint8_t cmdp = 0;
- bool updateGrph = false;
- bool errors = false;
-
- while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
- switch (tolower(param_getchar(Cmd, cmdp))) {
- case 'h':
- return usage_data_autocorr();
- case 'g':
- updateGrph = true;
- cmdp++;
- break;
- case 'w':
- window = param_get32ex(Cmd, cmdp + 1, 4000, 10);
- if (window >= GraphTraceLen) {
- PrintAndLogEx(WARNING, "window must be smaller than trace (%zu samples)", GraphTraceLen);
- errors = true;
- }
- cmdp += 2;
- break;
- default:
- PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = true;
- break;
- }
- }
- //Validations
- if (errors || cmdp == 0) return usage_data_autocorr();
-
- AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true);
-
- return PM3_SUCCESS;
-}
-
-static int CmdBitsamples(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- int cnt = 0;
- uint8_t got[12288];
-
- if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 0, NULL, 2500, false)) {
- PrintAndLogEx(WARNING, "command execution time out");
- return PM3_ETIMEOUT;
- }
-
- for (size_t j = 0; j < ARRAYLEN(got); j++) {
- for (uint8_t k = 0; k < 8; k++) {
- if (got[j] & (1 << (7 - k)))
- GraphBuffer[cnt++] = 1;
- else
- GraphBuffer[cnt++] = 0;
- }
- }
- GraphTraceLen = cnt;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static int CmdBuffClear(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (cmdp == 'h') return usage_data_buffclear();
-
- clearCommandBuffer();
- SendCommandNG(CMD_BUFF_CLEAR, NULL, 0);
- ClearGraph(true);
- return PM3_SUCCESS;
-}
-
-static int CmdDec(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- for (size_t i = 0; i < (GraphTraceLen / 2); ++i)
- GraphBuffer[i] = GraphBuffer[i * 2];
- GraphTraceLen /= 2;
- PrintAndLogEx(NORMAL, "decimated by 2");
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-/**
- * Undecimate - I'd call it 'interpolate', but we'll save that
- * name until someone does an actual interpolation command, not just
- * blindly repeating samples
- * @param Cmd
- * @return
- */
-static int CmdUndec(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (cmdp == 'h') return usage_data_undecimate();
-
- uint8_t factor = param_get8ex(Cmd, 0, 2, 10);
-
- //We have memory, don't we?
- int swap[MAX_GRAPH_TRACE_LEN] = {0};
- uint32_t g_index = 0, s_index = 0;
- while (g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) {
- int count = 0;
- for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
- swap[s_index + count] = GraphBuffer[g_index];
- s_index += count;
- g_index++;
- }
-
- memcpy(GraphBuffer, swap, s_index * sizeof(int));
- GraphTraceLen = s_index;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-//shift graph zero up or down based on input + or -
-static int CmdGraphShiftZero(const char *Cmd) {
- int shift = 0;
- //set options from parameters entered with the command
- sscanf(Cmd, "%i", &shift);
-
- for (size_t i = 0; i < GraphTraceLen; i++) {
- int shiftedVal = GraphBuffer[i] + shift;
-
- if (shiftedVal > 127)
- shiftedVal = 127;
- else if (shiftedVal < -127)
- shiftedVal = -127;
- GraphBuffer[i] = shiftedVal;
- }
- CmdNorm("");
- return PM3_SUCCESS;
-}
-
-int AskEdgeDetect(const int *in, int *out, int len, int threshold) {
- int last = 0;
- for (int i = 1; i < len; i++) {
- if (in[i] - in[i - 1] >= threshold) //large jump up
- last = 127;
- else if (in[i] - in[i - 1] <= -1 * threshold) //large jump down
- last = -127;
- out[i - 1] = last;
- }
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-//use large jumps in read samples to identify edges of waves and then amplify that wave to max
-//similar to dirtheshold, threshold commands
-//takes a threshold length which is the measured length between two samples then determines an edge
-static int CmdAskEdgeDetect(const char *Cmd) {
- int thresLen = 25;
- int ans = 0;
- sscanf(Cmd, "%i", &thresLen);
-
- ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen);
- RepaintGraphWindow();
- return ans;
-}
-
-/* Print our clock rate */
-// uses data from graphbuffer
-// adjusted to take char parameter for type of modulation to find the clock - by marshmellow.
-static int CmdDetectClockRate(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h')
- return usage_data_detectclock();
-
- int clock1 = 0;
- switch (cmdp) {
- case 'a' :
- clock1 = GetAskClock(Cmd + 1, true);
- break;
- case 'f' :
- clock1 = GetFskClock("", true);
- break;
- case 'n' :
- clock1 = GetNrzClock("", true);
- break;
- case 'p' :
- clock1 = GetPskClock("", true);
- break;
- default :
- PrintAndLogEx(NORMAL, "Please specify a valid modulation to detect the clock of - see option h for help");
- break;
- }
- RepaintGraphWindow();
- return clock1;
-}
-
-static char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) {
- static char fType[8];
- memset(fType, 0x00, 8);
- char *fskType = fType;
-
- if (fchigh == 10 && fclow == 8) {
-
- if (invert)
- memcpy(fskType, "FSK2a", 5);
- else
- memcpy(fskType, "FSK2", 4);
-
- } else if (fchigh == 8 && fclow == 5) {
-
- if (invert)
- memcpy(fskType, "FSK1", 4);
- else
- memcpy(fskType, "FSK1a", 5);
-
- } else {
- memcpy(fskType, "FSK??", 5);
- }
- return fskType;
-}
-
-//by marshmellow
-//fsk raw demod and print binary
-//takes 4 arguments - Clock, invert, fchigh, fclow
-//defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a))
-int FSKrawDemod(const char *Cmd, bool verbose) {
- //raw fsk demod no manchester decoding no start bit finding just get binary from wave
- uint8_t rfLen, invert, fchigh, fclow;
-
- //set defaults
- //set options from parameters entered with the command
- rfLen = param_get8(Cmd, 0);
- invert = param_get8(Cmd, 1);
- fchigh = param_get8(Cmd, 2);
- fclow = param_get8(Cmd, 3);
-
- if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) {
- if (rfLen == 1) {
- invert = 1; //if invert option only is used
- rfLen = 0;
- }
- }
-
- if (getSignalProperties()->isnoise)
- return PM3_ESOFT;
-
- uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
- if (bits == NULL) {
- return PM3_EMALLOC;
- }
-
- size_t BitLen = getFromGraphBuf(bits);
- if (BitLen == 0) {
- free(bits);
- return PM3_ESOFT;
- }
-
- //get field clock lengths
- if (!fchigh || !fclow) {
- uint16_t fcs = countFC(bits, BitLen, true);
- if (!fcs) {
- fchigh = 10;
- fclow = 8;
- } else {
- fchigh = (fcs >> 8) & 0x00FF;
- fclow = fcs & 0x00FF;
- }
- }
- //get bit clock length
- if (!rfLen) {
- int firstClockEdge = 0; //todo - align grid on graph with this...
- rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge);
- if (!rfLen) rfLen = 50;
- }
- int startIdx = 0;
- int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx);
- if (size > 0) {
- setDemodBuff(bits, size, 0);
- setClockGrid(rfLen, startIdx);
-
- // Now output the bitstream to the scrollback by line of 16 bits
- if (verbose || g_debugMode) {
- PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow);
- PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert));
- printDemodBuff();
- }
- goto out;
- } else {
- PrintAndLogEx(DEBUG, "no FSK data found");
- }
-
-out:
- free(bits);
- return PM3_SUCCESS;
-}
-
-//by marshmellow
-//fsk raw demod and print binary
-//takes 4 arguments - Clock, invert, fchigh, fclow
-//defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a))
-static int CmdFSKrawdemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs();
-
- return FSKrawDemod(Cmd, true);
-}
-
-//by marshmellow
-//attempt to psk1 demod graph buffer
-int PSKDemod(const char *Cmd, bool verbose) {
- int invert = 0, clk = 0, maxErr = 100;
-
- sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
-
- if (clk == 1) {
- invert = 1;
- clk = 0;
- }
- if (invert != 0 && invert != 1) {
- if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd);
- return PM3_EINVARG;
- }
-
- if (getSignalProperties()->isnoise)
- return PM3_ESOFT;
-
- uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
- if (bits == NULL) {
- return PM3_EMALLOC;
- }
- size_t bitlen = getFromGraphBuf(bits);
- if (bitlen == 0) {
- free(bits);
- return PM3_ESOFT;
- }
-
- int startIdx = 0;
- int errCnt = pskRawDemod_ext(bits, &bitlen, &clk, &invert, &startIdx);
- if (errCnt > maxErr) {
- if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, bitlen, errCnt);
- free(bits);
- return PM3_ESOFT;
- }
- if (errCnt < 0 || bitlen < 16) { //throw away static - allow 1 and -1 (in case of threshold command first)
- if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, bitlen, errCnt);
- free(bits);
- return PM3_ESOFT;
- }
- if (verbose || g_debugMode) {
- PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%zu", clk, invert, bitlen);
- if (errCnt > 0) {
- PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt);
- }
- }
- //prime demod buffer for output
- setDemodBuff(bits, bitlen, 0);
- setClockGrid(clk, startIdx);
- free(bits);
- return PM3_SUCCESS;
-}
-
-static int CmdIdteckDemod(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
-
- if (PSKDemod("", false) != PM3_SUCCESS) {
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
- return PM3_ESOFT;
- }
- size_t size = DemodBufferLen;
-
- //get binary from PSK1 wave
- int idx = detectIdteck(DemodBuffer, &size);
- if (idx < 0) {
-
- if (idx == -1)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples");
- else if (idx == -2)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise");
- else if (idx == -3)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found");
- else if (idx == -4)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %zu", size);
- else
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d", idx);
-
- // if didn't find preamble try again inverting
- if (PSKDemod("1", false) != PM3_SUCCESS) {
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
- return PM3_ESOFT;
- }
- idx = detectIdteck(DemodBuffer, &size);
- if (idx < 0) {
-
- if (idx == -1)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples");
- else if (idx == -2)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise");
- else if (idx == -3)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found");
- else if (idx == -4)
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %zu", size);
- else
- PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d", idx);
-
- return PM3_ESOFT;
- }
- }
- setDemodBuff(DemodBuffer, 64, idx);
-
- //got a good demod
- uint32_t id = 0;
- uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
- uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
-
- //parity check (TBD)
- //checksum check (TBD)
-
- //output
- PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2);
- return PM3_SUCCESS;
-}
-
-int demodIdteck(void) {
- return CmdIdteckDemod("");
-}
-
-
-// by marshmellow
-// takes 3 arguments - clock, invert, maxErr as integers
-// attempts to demodulate nrz only
-// prints binary found and saves in demodbuffer for further commands
-int NRZrawDemod(const char *Cmd, bool verbose) {
-
- int errCnt = 0, clkStartIdx = 0;
- int invert = 0, clk = 0, maxErr = 100;
- sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
- if (clk == 1) {
- invert = 1;
- clk = 0;
- }
-
- if (invert != 0 && invert != 1) {
- PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd);
- return PM3_EINVARG;
- }
-
- if (getSignalProperties()->isnoise)
- return PM3_ESOFT;
-
- uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
- if (bits == NULL) {
- return PM3_EMALLOC;
- }
-
- size_t BitLen = getFromGraphBuf(bits);
-
- if (BitLen == 0) {
- free(bits);
- return PM3_ESOFT;
- }
-
- errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx);
- if (errCnt > maxErr) {
- PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, BitLen, errCnt);
- free(bits);
- return PM3_ESOFT;
- }
- if (errCnt < 0 || BitLen < 16) { //throw away static - allow 1 and -1 (in case of threshold command first)
- PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, BitLen, errCnt);
- free(bits);
- return PM3_ESOFT;
- }
-
- if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %zu", clk, invert, BitLen);
- //prime demod buffer for output
- setDemodBuff(bits, BitLen, 0);
- setClockGrid(clk, clkStartIdx);
-
-
- if (errCnt > 0 && (verbose || g_debugMode)) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Errors during Demoding (shown as 7 in bit stream): %d", errCnt);
- if (verbose || g_debugMode) {
- PrintAndLogEx(NORMAL, "NRZ demoded bitstream:");
- // Now output the bitstream to the scrollback by line of 16 bits
- printDemodBuff();
- }
-
- free(bits);
- return PM3_SUCCESS;
-}
-
-static int CmdNRZrawDemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr();
-
- return NRZrawDemod(Cmd, true);
-}
-
-// by marshmellow
-// takes 3 arguments - clock, invert, maxErr as integers
-// attempts to demodulate psk only
-// prints binary found and saves in demodbuffer for further commands
-int CmdPSK1rawDemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1();
-
- int ans = PSKDemod(Cmd, true);
- //output
- if (ans != PM3_SUCCESS) {
- if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans);
- return PM3_ESOFT;
- }
- PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:");
- // Now output the bitstream to the scrollback by line of 16 bits
- printDemodBuff();
- return PM3_SUCCESS;
-}
-
-// by marshmellow
-// takes same args as cmdpsk1rawdemod
-static int CmdPSK2rawDemod(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2();
-
- int ans = PSKDemod(Cmd, true);
- if (ans != PM3_SUCCESS) {
- if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans);
- return PM3_ESOFT;
- }
- psk1TOpsk2(DemodBuffer, DemodBufferLen);
- PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:");
- // Now output the bitstream to the scrollback by line of 16 bits
- printDemodBuff();
- return PM3_SUCCESS;
-}
-
-// by marshmellow - combines all raw demod functions into one menu command
-static int CmdRawDemod(const char *Cmd) {
- int ans = 0;
-
- if (strlen(Cmd) > 35 || strlen(Cmd) < 2)
- return usage_data_rawdemod();
-
- str_lower((char *)Cmd);
-
- if (str_startswith(Cmd, "fs") || Cmd[0] == 'f') ans = CmdFSKrawdemod(Cmd + 2);
- else if (str_startswith(Cmd, "ab")) ans = Cmdaskbiphdemod(Cmd + 2);
- else if (str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd + 2);
- else if (str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd + 2);
- else if (str_startswith(Cmd, "nr") || Cmd[0] == 'n') ans = CmdNRZrawDemod(Cmd + 2);
- else if (str_startswith(Cmd, "p1") || Cmd[0] == 'p') ans = CmdPSK1rawDemod(Cmd + 2);
- else if (str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd + 2);
- else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure");
-
- return ans;
-}
-
-void setClockGrid(uint32_t clk, int offset) {
- g_DemodStartIdx = offset;
- g_DemodClock = clk;
- if (clk == 0 && offset == 0)
- PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) clear settings");
- else
- PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk);
-
- if (offset > clk) offset %= clk;
- if (offset < 0) offset += clk;
-
- if (offset > GraphTraceLen || offset < 0) return;
- if (clk < 8 || clk > GraphTraceLen) {
- GridLocked = false;
- GridOffset = 0;
- PlotGridX = 0;
- PlotGridXdefault = 0;
- RepaintGraphWindow();
- } else {
- GridLocked = true;
- GridOffset = offset;
- PlotGridX = clk;
- PlotGridXdefault = clk;
- RepaintGraphWindow();
- }
-}
-
-int CmdGrid(const char *Cmd) {
- sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
- PlotGridXdefault = PlotGridX;
- PlotGridYdefault = PlotGridY;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static int CmdSetGraphMarkers(const char *Cmd) {
- sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos);
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static int CmdHexsamples(const char *Cmd) {
- uint32_t requested = 0;
- uint32_t offset = 0;
- char string_buf[25];
- char *string_ptr = string_buf;
- uint8_t got[BIGBUF_SIZE];
-
- sscanf(Cmd, "%u %u", &requested, &offset);
-
- /* if no args send something */
- if (requested == 0)
- requested = 8;
-
- if (offset + requested > sizeof(got)) {
- PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE);
- return PM3_EINVARG;
- }
-
- if (!GetFromDevice(BIG_BUF, got, requested, offset, NULL, 0, NULL, 2500, false)) {
- PrintAndLogEx(WARNING, "command execution time out");
- return PM3_ESOFT;
- }
-
- uint8_t i = 0;
- for (uint32_t j = 0; j < requested; j++) {
- i++;
- string_ptr += sprintf(string_ptr, "%02x ", got[j]);
- if (i == 8) {
- *(string_ptr - 1) = '\0'; // remove the trailing space
- PrintAndLogEx(NORMAL, "%s", string_buf);
- string_buf[0] = '\0';
- string_ptr = string_buf;
- i = 0;
- }
- if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes
- *(string_ptr - 1) = '\0';
- PrintAndLogEx(NORMAL, "%s", string_buf);
- string_buf[0] = '\0';
- }
- }
- return PM3_SUCCESS;
-}
-
-static int CmdHide(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- HideGraphWindow();
- return PM3_SUCCESS;
-}
-
-//zero mean GraphBuffer
-int CmdHpf(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
- removeSignalOffset(bits, size);
- // push it back to graph
- setGraphBuf(bits, size);
- // set signal properties low/high/mean/amplitude and is_noise detection
- computeSignalProperties(bits, size);
-
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static bool _headBit(BitstreamOut *stream) {
- int bytepos = stream->position >> 3; // divide by 8
- int bitpos = (stream->position++) & 7; // mask out 00000111
- return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1;
-}
-
-static uint8_t getByte(uint8_t bits_per_sample, BitstreamOut *b) {
- uint8_t val = 0;
- for (int i = 0 ; i < bits_per_sample; i++)
- val |= (_headBit(b) << (7 - i));
-
- return val;
-}
-
-int getSamples(uint32_t n, bool verbose) {
- //If we get all but the last byte in bigbuf,
- // we don't have to worry about remaining trash
- // in the last byte in case the bits-per-sample
- // does not line up on byte boundaries
- uint8_t got[BIGBUF_SIZE - 1] = { 0 };
-
- if (n == 0 || n > sizeof(got))
- n = sizeof(got);
-
- if (verbose) PrintAndLogEx(INFO, "Reading " _YELLOW_("%u") "bytes from device memory", n);
-
- PacketResponseNG response;
- if (!GetFromDevice(BIG_BUF, got, n, 0, NULL, 0, &response, 10000, true)) {
- PrintAndLogEx(WARNING, "timeout while waiting for reply.");
- return PM3_ETIMEOUT;
- }
-
- if (verbose) PrintAndLogEx(SUCCESS, "Data fetched");
-
- uint8_t bits_per_sample = 8;
-
- //Old devices without this feature would send 0 at arg[0]
- if (response.oldarg[0] > 0) {
- sample_config *sc = (sample_config *) response.data.asBytes;
- if (verbose) PrintAndLogEx(INFO, "Samples @ " _YELLOW_("%d") "bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation);
- bits_per_sample = sc->bits_per_sample;
- }
-
- if (bits_per_sample < 8) {
-
- if (verbose) PrintAndLogEx(INFO, "Unpacking...");
-
- BitstreamOut bout = { got, bits_per_sample * n, 0};
- int j = 0;
- for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) {
- uint8_t sample = getByte(bits_per_sample, &bout);
- GraphBuffer[j] = ((int) sample) - 127;
- }
- GraphTraceLen = j;
-
- if (verbose) PrintAndLogEx(INFO, "Unpacked %d samples", j);
-
- } else {
- for (int j = 0; j < n; j++) {
- GraphBuffer[j] = ((int)got[j]) - 127;
- }
- GraphTraceLen = n;
- }
-
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
- // set signal properties low/high/mean/amplitude and is_noise detection
- computeSignalProperties(bits, size);
-
- setClockGrid(0, 0);
- DemodBufferLen = 0;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static int CmdSamples(const char *Cmd) {
- int n = strtol(Cmd, NULL, 0);
- return getSamples(n, false);
-}
-
-int CmdTuneSamples(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
-#define NON_VOLTAGE 1000
-#define LF_UNUSABLE_V 2000
-#define LF_MARGINAL_V 10000
-#define HF_UNUSABLE_V 3000
-#define HF_MARGINAL_V 5000
-#define ANTENNA_ERROR 1.03 // current algo has 3% error margin.
-
- // hide demod plot line
- DemodBufferLen = 0;
- setClockGrid(0, 0);
- RepaintGraphWindow();
-
-
- int timeout = 0;
- PrintAndLogEx(INFO, "\nMeasuring antenna characteristics, please wait...");
-
- clearCommandBuffer();
- SendCommandNG(CMD_MEASURE_ANTENNA_TUNING, NULL, 0);
- PacketResponseNG resp;
- while (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING, &resp, 2000)) {
- timeout++;
- printf(".");
- fflush(stdout);
- if (timeout > 7) {
- PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
- return PM3_ETIMEOUT;
- }
- }
-
- if (resp.status != PM3_SUCCESS) {
- PrintAndLogEx(WARNING, "Antenna tuning failed");
- return PM3_ESOFT;
- }
-
- PrintAndLogEx(NORMAL, "\n");
- // in mVolt
- struct p {
- uint32_t v_lf134;
- uint32_t v_lf125;
- uint32_t v_lfconf;
- uint32_t v_hf;
- uint32_t peak_v;
- uint32_t peak_f;
- int divisor;
- uint8_t results[256];
- } PACKED;
-
- struct p *package = (struct p *)resp.data.asBytes;
-
- if (package->v_lf125 > NON_VOLTAGE)
- PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf125 * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(LF_DIVISOR_125));
-
- if (package->v_lf134 > NON_VOLTAGE)
- PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf134 * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(LF_DIVISOR_134));
-
- if (package->v_lfconf > NON_VOLTAGE && package->divisor > 0 && package->divisor != LF_DIVISOR_125 && package->divisor != LF_DIVISOR_134)
- PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lfconf * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->divisor));
-
- if (package->peak_v > NON_VOLTAGE && package->peak_f > 0)
- PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->peak_f));
-
- char judgement[20];
- memset(judgement, 0, sizeof(judgement));
- // LF evaluation
- if (package->peak_v < LF_UNUSABLE_V)
- sprintf(judgement, _RED_("UNUSABLE"));
- else if (package->peak_v < LF_MARGINAL_V)
- sprintf(judgement, _YELLOW_("MARGINAL"));
- else
- sprintf(judgement, _GREEN_("OK"));
-
- PrintAndLogEx(NORMAL, "%sLF antenna is %s \n"
- , (package->peak_v < LF_UNUSABLE_V) ? _CYAN_("[!]") : _GREEN_("[+]")
- , judgement
- );
-
- // HF evaluation
- if (package->v_hf > NON_VOLTAGE)
- PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (package->v_hf * ANTENNA_ERROR) / 1000.0);
-
- memset(judgement, 0, sizeof(judgement));
-
- if (package->v_hf < HF_UNUSABLE_V)
- sprintf(judgement, _RED_("UNUSABLE"));
- else if (package->v_hf < HF_MARGINAL_V)
- sprintf(judgement, _YELLOW_("MARGINAL"));
- else
- sprintf(judgement, _GREEN_("OK"));
-
- PrintAndLogEx(NORMAL, "%sHF antenna is %s"
- , (package->v_hf < HF_UNUSABLE_V) ? _CYAN_("[!]") : _GREEN_("[+]")
- , judgement
- );
-
- // graph LF measurements
- // even here, these values has 3% error.
- uint16_t test1 = 0;
- for (int i = 0; i < 256; i++) {
- GraphBuffer[i] = package->results[i] - 128;
- test1 += package->results[i];
- }
-
- if (test1 > 0) {
- PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor %d is %.2f kHz, %d is %.2f kHz.\n\n",
- LF_DIVISOR_134, LF_DIV2FREQ(LF_DIVISOR_134), LF_DIVISOR_125, LF_DIV2FREQ(LF_DIVISOR_125));
- GraphTraceLen = 256;
- ShowGraphWindow();
- RepaintGraphWindow();
- } else {
-
- PrintAndLogEx(FAILED, "\nNot showing LF tuning graph since all values is zero.\n\n");
- }
-
- return PM3_SUCCESS;
-}
-
-static int CmdLoad(const char *Cmd) {
- char filename[FILE_PATH_SIZE] = {0x00};
- int len = 0;
-
- len = strlen(Cmd);
- if (len == 0) return PM3_EFILE;
-
- if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
- memcpy(filename, Cmd, len);
-
- char *path;
- if (searchFile(&path, TRACES_SUBDIR, filename, ".pm3", true) != PM3_SUCCESS) {
- if (searchFile(&path, TRACES_SUBDIR, filename, "", false) != PM3_SUCCESS) {
- return PM3_EFILE;
- }
- }
-
- FILE *f = fopen(path, "r");
- if (!f) {
- PrintAndLogEx(WARNING, "couldn't open '%s'", path);
- free(path);
- return PM3_EFILE;
- }
- free(path);
-
- GraphTraceLen = 0;
- char line[80];
- while (fgets(line, sizeof(line), f)) {
- GraphBuffer[GraphTraceLen] = atoi(line);
- GraphTraceLen++;
-
- if (GraphTraceLen >= MAX_GRAPH_TRACE_LEN)
- break;
- }
-
- fclose(f);
-
- PrintAndLogEx(SUCCESS, "loaded %zu samples", GraphTraceLen);
-
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
-
- removeSignalOffset(bits, size);
- setGraphBuf(bits, size);
- computeSignalProperties(bits, size);
-
- setClockGrid(0, 0);
- DemodBufferLen = 0;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-// trim graph from the end
-int CmdLtrim(const char *Cmd) {
-
- uint32_t ds = strtoul(Cmd, NULL, 10);
-
- // sanitycheck
- if (GraphTraceLen <= ds) return PM3_ESOFT;
-
- for (uint32_t i = ds; i < GraphTraceLen; ++i)
- GraphBuffer[i - ds] = GraphBuffer[i];
-
- GraphTraceLen -= ds;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-// trim graph from the beginning
-static int CmdRtrim(const char *Cmd) {
-
- uint32_t ds = strtoul(Cmd, NULL, 10);
-
- // sanitycheck
- if (GraphTraceLen <= ds) return PM3_ESOFT;
-
- GraphTraceLen = ds;
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-// trim graph (middle) piece
-static int CmdMtrim(const char *Cmd) {
- uint32_t start = 0, stop = 0;
- sscanf(Cmd, "%u %u", &start, &stop);
-
- if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return PM3_ESOFT;
-
- // leave start position sample
- start++;
-
- GraphTraceLen = stop - start;
- for (uint32_t i = 0; i < GraphTraceLen; i++)
- GraphBuffer[i] = GraphBuffer[start + i];
-
- return PM3_SUCCESS;
-}
-
-int CmdNorm(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- int max = INT_MIN, min = INT_MAX;
-
- // Find local min, max
- for (uint32_t i = 10; i < GraphTraceLen; ++i) {
- if (GraphBuffer[i] > max) max = GraphBuffer[i];
- if (GraphBuffer[i] < min) min = GraphBuffer[i];
- }
-
- if (max != min) {
- for (uint32_t i = 0; i < GraphTraceLen; ++i) {
- GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min);
- //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work
- }
- }
-
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
- // set signal properties low/high/mean/amplitude and is_noise detection
- computeSignalProperties(bits, size);
-
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-int CmdPlot(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- ShowGraphWindow();
- return PM3_SUCCESS;
-}
-
-int CmdSave(const char *Cmd) {
-
- int len = 0;
- char filename[FILE_PATH_SIZE] = {0x00};
- uint8_t cmdp = 0;
- bool errors = false, as_wave = false, has_name = false;
-
- while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
- char ctmp = tolower(param_getchar(Cmd, cmdp));
- switch (ctmp) {
- case 'h':
- return usage_data_save();
- case 'f':
- len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
- if (len < 1) {
- errors = true;
- break;
- }
- has_name = true;
- cmdp += 2;
- break;
- case 'w':
- as_wave = true;
- cmdp++;
- break;
- default:
- PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = true;
- break;
- }
- }
-
- if (!has_name) errors = true;
-
- if (errors || cmdp == 0) return usage_data_save();
-
- if (as_wave)
- return saveFileWAVE(filename, GraphBuffer, GraphTraceLen);
- else
- return saveFilePM3(filename, GraphBuffer, GraphTraceLen);
-}
-
-static int CmdScale(const char *Cmd) {
- char cmdp = tolower(param_getchar(Cmd, 0));
- if (strlen(Cmd) == 0 || cmdp == 'h') return usage_data_scale();
-
- CursorScaleFactor = atoi(Cmd);
- if (CursorScaleFactor == 0) {
- PrintAndLogEx(FAILED, "bad, can't have zero scale");
- CursorScaleFactor = 1;
- }
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down) {
-
- int lastValue = in[0];
-
- // Will be changed at the end, but init 0 as we adjust to last samples
- // value if no threshold kicks in.
- out[0] = 0;
-
- for (size_t i = 1; i < len; ++i) {
- // Apply first threshold to samples heading up
- if (in[i] >= up && in[i] > lastValue) {
- lastValue = out[i]; // Buffer last value as we overwrite it.
- out[i] = 1;
- }
- // Apply second threshold to samples heading down
- else if (in[i] <= down && in[i] < lastValue) {
- lastValue = out[i]; // Buffer last value as we overwrite it.
- out[i] = -1;
- } else {
- lastValue = out[i]; // Buffer last value as we overwrite it.
- out[i] = out[i - 1];
- }
- }
-
- // Align with first edited sample.
- out[0] = out[1];
- return PM3_SUCCESS;
-}
-
-static int CmdDirectionalThreshold(const char *Cmd) {
- int8_t up = param_get8(Cmd, 0);
- int8_t down = param_get8(Cmd, 1);
-
- PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down);
-
- directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down);
-
- // set signal properties low/high/mean/amplitude and isnoice detection
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
- // set signal properties low/high/mean/amplitude and is_noice detection
- computeSignalProperties(bits, size);
-
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static int CmdZerocrossings(const char *Cmd) {
- (void)Cmd; // Cmd is not used so far
- // Zero-crossings aren't meaningful unless the signal is zero-mean.
- CmdHpf("");
-
- int sign = 1, zc = 0, lastZc = 0;
-
- for (uint32_t i = 0; i < GraphTraceLen; ++i) {
- if (GraphBuffer[i] * sign >= 0) {
- // No change in sign, reproduce the previous sample count.
- zc++;
- GraphBuffer[i] = lastZc;
- } else {
- // Change in sign, reset the sample count.
- sign = -sign;
- GraphBuffer[i] = lastZc;
- if (sign > 0) {
- lastZc = zc;
- zc = 0;
- }
- }
- }
-
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
- // set signal properties low/high/mean/amplitude and is_noise detection
- computeSignalProperties(bits, size);
-
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-/**
- * @brief Utility for conversion via cmdline.
- * @param Cmd
- * @return
- */
-static int Cmdbin2hex(const char *Cmd) {
- int bg = 0, en = 0;
- if (param_getptr(Cmd, &bg, &en, 0))
- return usage_data_bin2hex();
-
- //Number of digits supplied as argument
- size_t length = en - bg + 1;
- size_t bytelen = (length + 7) / 8;
- uint8_t *arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t));
- memset(arr, 0, bytelen);
- BitstreamOut bout = { arr, 0, 0 };
-
- for (; bg <= en; bg++) {
- char c = Cmd[bg];
- if (c == '1')
- pushBit(&bout, 1);
- else if (c == '0')
- pushBit(&bout, 0);
- else
- PrintAndLogEx(NORMAL, "Ignoring '%c'", c);
- }
-
- if (bout.numbits % 8 != 0)
- PrintAndLogEx(NORMAL, "[padded with %d zeroes]", 8 - (bout.numbits % 8));
-
- PrintAndLogEx(NORMAL, "%s", sprint_hex(arr, bytelen));
- free(arr);
- return PM3_SUCCESS;
-}
-
-static int Cmdhex2bin(const char *Cmd) {
- int bg = 0, en = 0;
- if (param_getptr(Cmd, &bg, &en, 0)) return usage_data_hex2bin();
-
- while (bg <= en) {
- char x = Cmd[bg++];
- // capitalize
- if (x >= 'a' && x <= 'f')
- x -= 32;
- // convert to numeric value
- if (x >= '0' && x <= '9')
- x -= '0';
- else if (x >= 'A' && x <= 'F')
- x -= 'A' - 10;
- else
- continue;
-
- //Uses printf instead of PrintAndLog since the latter adds linebreaks to each printout
- for (int i = 0 ; i < 4 ; ++i)
- printf("%d", (x >> (3 - i)) & 1);
- }
- PrintAndLogEx(NORMAL, "\n");
- return PM3_SUCCESS;
-}
-
-/* // example of FSK2 RF/50 Tones
-static const int LowTone[] = {
-1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
-1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
-1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
-1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
-1, 1, 1, 1, 1, -1, -1, -1, -1, -1
-};
-static const int HighTone[] = {
-1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder)
-1, 1, 1, 1, -1, -1, -1, -1,
-1, 1, 1, 1, -1, -1, -1, -1,
-1, 1, 1, 1, -1, -1, -1, -1,
-1, 1, 1, 1, -1, -1, -1, -1,
-1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder
-};
-*/
-static void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighToneFC) {
- int i, j = 0;
- int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC) / 2);
- int Right_Modifier = (clk % LowToneFC) / 2;
- //int HighToneMod = clk mod HighToneFC;
- int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC / 2); //truncate
- int FCs_per_clk = clk / LowToneFC;
-
- // need to correctly split up the clock to field clocks.
- // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk
-
- // start with LowTone
- // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk
- for (i = 0; i < Left_Modifier; i++) {
- LowTone[i] = 1;
- }
-
- // loop # of field clocks inside the main clock
- for (i = 0; i < (FCs_per_clk); i++) {
- // loop # of samples per field clock
- for (j = 0; j < LowToneFC; j++) {
- LowTone[(i * LowToneFC) + Left_Modifier + j] = (j < LeftHalfFCCnt) ? 1 : -1;
- }
- }
-
- int k;
- // add last -1 modifiers
- for (k = 0; k < Right_Modifier; k++) {
- LowTone[((i - 1) * LowToneFC) + Left_Modifier + j + k] = -1;
- }
-
- // now do hightone
- Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC) / 2);
- Right_Modifier = (clk % HighToneFC) / 2;
- LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC / 2); //truncate
- FCs_per_clk = clk / HighToneFC;
-
- for (i = 0; i < Left_Modifier; i++) {
- HighTone[i] = 1;
- }
-
- // loop # of field clocks inside the main clock
- for (i = 0; i < (FCs_per_clk); i++) {
- // loop # of samples per field clock
- for (j = 0; j < HighToneFC; j++) {
- HighTone[(i * HighToneFC) + Left_Modifier + j] = (j < LeftHalfFCCnt) ? 1 : -1;
- }
- }
-
- // add last -1 modifiers
- for (k = 0; k < Right_Modifier; k++) {
- PrintAndLogEx(NORMAL, "(i-1)*HighToneFC+lm+j+k %i", ((i - 1) * HighToneFC) + Left_Modifier + j + k);
- HighTone[((i - 1) * HighToneFC) + Left_Modifier + j + k] = -1;
- }
- if (g_debugMode == 2) {
- for (i = 0; i < clk; i++) {
- PrintAndLogEx(NORMAL, "Low: %i, High: %i", LowTone[i], HighTone[i]);
- }
- }
-}
-
-//old CmdFSKdemod adapted by marshmellow
-//converts FSK to clear NRZ style wave. (or demodulates)
-static int FSKToNRZ(int *data, size_t *dataLen, uint8_t clk, uint8_t LowToneFC, uint8_t HighToneFC) {
- uint8_t ans = 0;
- if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) {
- int firstClockEdge = 0;
- ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, &firstClockEdge);
- if (g_debugMode > 1) {
- PrintAndLogEx(NORMAL, "DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans);
- }
- }
- // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...)
- if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) {
- if (g_debugMode > 1) {
- PrintAndLogEx(NORMAL, "DEBUG FSKtoNRZ: no fsk clocks found");
- }
- return PM3_ESOFT;
- }
-
- int LowTone[clk];
- int HighTone[clk];
- GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC);
-
- // loop through ([all samples] - clk)
- for (size_t i = 0; i < *dataLen - clk; ++i) {
- int lowSum = 0, highSum = 0;
-
- // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data)
- for (size_t j = 0; j < clk; ++j) {
- lowSum += LowTone[j] * data[i + j];
- highSum += HighTone[j] * data[i + j];
- }
- // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts)
- lowSum = abs(100 * lowSum / clk);
- highSum = abs(100 * highSum / clk);
- // save these back to buffer for later use
- data[i] = (highSum << 16) | lowSum;
- }
-
- // now we have the abs( [average sample value per clk] * 100 ) for each tone
- // loop through again [all samples] - clk - 16
- // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc
- for (size_t i = 0; i < *dataLen - clk - LowToneFC; ++i) {
- int lowTot = 0, highTot = 0;
-
- // sum a field clock width of abs( [average sample values per clk] * 100) for each tone
- for (size_t j = 0; j < LowToneFC; ++j) { //10 for fsk2
- lowTot += (data[i + j] & 0xffff);
- }
- for (size_t j = 0; j < HighToneFC; j++) { //8 for fsk2
- highTot += (data[i + j] >> 16);
- }
-
- // subtract the sum of lowTone averages by the sum of highTone averages as it
- // and write back the new graph value
- data[i] = lowTot - highTot;
- }
- // update dataLen to what we put back to the data sample buffer
- *dataLen -= (clk + LowToneFC);
- return PM3_SUCCESS;
-}
-
-static int CmdFSKToNRZ(const char *Cmd) {
- // take clk, fc_low, fc_high
- // blank = auto;
- bool errors = false;
- char cmdp = 0;
- int clk = 0, fc_low = 10, fc_high = 8;
- while (param_getchar(Cmd, cmdp) != 0x00) {
- switch (tolower(param_getchar(Cmd, cmdp))) {
- case 'h':
- return usage_data_fsktonrz();
- case 'c':
- clk = param_get32ex(Cmd, cmdp + 1, 0, 10);
- cmdp += 2;
- break;
- case 'f':
- fc_high = param_get32ex(Cmd, cmdp + 1, 0, 10);
- cmdp += 2;
- break;
- case 'l':
- fc_low = param_get32ex(Cmd, cmdp + 1, 0, 10);
- cmdp += 2;
- break;
- default:
- PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = true;
- break;
- }
- if (errors) break;
- }
- //Validations
- if (errors) return usage_data_fsktonrz();
-
- setClockGrid(0, 0);
- DemodBufferLen = 0;
- int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high);
- CmdNorm("");
- RepaintGraphWindow();
- return ans;
-}
-
-static int CmdDataIIR(const char *Cmd) {
- uint8_t k = param_get8(Cmd, 0);
- //iceIIR_Butterworth(GraphBuffer, GraphTraceLen);
- iceSimple_Filter(GraphBuffer, GraphTraceLen, k);
-
- uint8_t bits[GraphTraceLen];
- size_t size = getFromGraphBuf(bits);
- // set signal properties low/high/mean/amplitude and is_noise detection
- computeSignalProperties(bits, size);
- RepaintGraphWindow();
- return PM3_SUCCESS;
-}
-
-static command_t CommandTable[] = {
- {"help", CmdHelp, AlwaysAvailable, "This help"},
- {"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"},
- {"autocorr", CmdAutoCorr, AlwaysAvailable, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
- {"biphaserawdecode", CmdBiphaseDecodeRaw, AlwaysAvailable, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
- {"bin2hex", Cmdbin2hex, AlwaysAvailable, " -- Converts binary to hexadecimal"},
- {"bitsamples", CmdBitsamples, IfPm3Present, "Get raw samples as bitstring"},
- {"buffclear", CmdBuffClear, AlwaysAvailable, "Clears bigbuff on deviceside and graph window"},
- {"convertbitstream", CmdConvertBitStream, AlwaysAvailable, "Convert GraphBuffer's 0/1 values to 127 / -127"},
- {"dec", CmdDec, AlwaysAvailable, "Decimate samples"},
- {"detectclock", CmdDetectClockRate, AlwaysAvailable, "[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"},
- {"fsktonrz", CmdFSKToNRZ, AlwaysAvailable, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"},
- {"getbitstream", CmdGetBitStream, AlwaysAvailable, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
- {"grid", CmdGrid, AlwaysAvailable, " -- overlay grid on graph window, use zero value to turn off either"},
- {"hexsamples", CmdHexsamples, IfPm3Present, " [