跟C++的版本 , 操作系统, 编译器关系非常大
当字符串长度>16时
第1个 int64 保存着 buf的地址
跟C++的版本 , 操作系统, 编译器关系非常大
当字符串长度>16时
第1个 int64 保存着 buf的地址
对于电信2020年后发行的普通SIM卡和物联网卡,是没有CDMA所需要的CSIM文件的。早期的EC20为了适配当时的电信UIM卡,是做了特殊处理的,启动后会搜寻SIM卡中的CSIM文件,没有这些文件就不会注册到网络。
解决方法:
(1) 读取nv 配置
发送AT命令给EC20模块
AT+QNVFR="/nv/item_files/modem/mmode/operator_name"
读出来的结果应该是 01
(2) 将该配置改为 00
AT+QNVFW="/nv/item_files/modem/mmode/operator_name",00
(3) 插入 电信4G物联网卡,断电重启EC20
说明:
operator_name = 00 表示 OPERATE_NULL, 选网时采用默认设计,无特定运营商
operator_name = 01 表示 OPERATE_CT, 中国电信,选网时是考虑CDMA兼容,SRLTE(CDMA+LTE双在网)等需求
在一款 2017年出厂的EC20上实测成功, 版本为 EC20CEFAGR06A05M4G
Phone connects to Edge Packet Data Gateway (EPDG)
over WiFi
• Voice calls over WiFi
• Phone connects on low/no signal
• Also connects in Airplane mode + WiFi
Connection to EPDG uses IPsec
• Authenticates using Internet Key Exchange Protocol (IKEv2)
Internet Protocol Security
• Confidentiality, data integrity, access control, and data source
authentication
• Recovery from transmission errors: packet loss, packet replay, and
packet forgery
• Authentication
• Authentication Header (AH) – RFC 4302
• Confidentiality
• Encapsulating Security Payload (ESP) – RFC 4303
• Key management
• Internet Key Exchange v2 (IKEv2) – RFC7296
• Two modes
• Tunnel – used for connection to Gateway (EPDG)
• Transport
Internet Key Exchange (IKEv2)
• Initiates connection in two phases
• IKE_SA_INIT
• Negotiate cryptographic algorithms, exchange nonces, and do
a Diffie-Hellman exchange
• IKE_AUTH
• Authenticate the previous messages, exchange identities (e.g.
IMSI), and certificates, and establish the child Security
Association(s) (SA)
• IKE_AUTH uses EAP-AKA
• IMSI exchange not protected by a certificate
• Open to MitM attacks on identity (IMSI)
IPsec ESP keys are not compromised
• Call content still safe
小米firmware下载的cdn 限速了。
据说是因为一帮搞 pcdn的人,为了让自己的上行流量占比 小一点, 故意刷下行流量。 其中小米firmware的下载地址是很好获取的,所以被狂刷了很多流量。
其实没什么用,现在运营商不是看占比, 而是上行流量超过多少G,就停宽带。
默认的地址是 bigota.d.miui.com, 改成
cdn-ota.azureedge.net
cdnorg.d.miui.com
bn.d.miui.com
bkt-sgp-miui-ota-update-alisgp.oss-ap-southeast-1.aliyuncs.com
有时候可以提高下载速率
https://bn.d.miui.com/V12.5.15.0.RGGEUXM/begonia_eea_global_images_V12.5.15.0.RGGEUXM_20220826.0000.00_11.0_eea_b8c6b15c15.tgz
https://cdn-ota.azureedge.net/V12.5.15.0.RGGEUXM/begonia_eea_global_images_V12.5.15.0.RGGEUXM_20220826.0000.00_11.0_eea_b8c6b15c15.tgz
https://cdn-ota.azureedge.net/V13.0.8.0.SJHCNXM/atom_images_V13.0.8.0.SJHCNXM_20230630.0000.00_12.0_cn_acca549dfc.tgz
wget -c --referer="https://miui.com/" https://hugeota.d.miui.com/V12.5.6.0.RGGCNXM/begonia_images_V12.5.6.0.RGGCNXM_20220602.0000.00_11.0_cn_fbed701a77.tgz
2017年的时候有做过这样的一个定制化需求:写入一个文件数据,恢复出厂设置后该文件数据也要恢复。
第一步:nvram lib id定义
vendor/mediatek/proprietary/custom/project/cgen/inc/Custom_NvRam_LID.h
typedef enum { AP_CFG_RDCL_FILE_AUDIO_LID=AP_CFG_CUSTOM_BEGIN_LID, //AP_CFG_CUSTOM_BEGIN_LID: this lid must not be changed, it is reserved for system. AP_CFG_RDCL_FILE_AUDIO_MAGI_CONFERENCE_LID, AP_CFG_RDCL_FILE_AUDIO_HAC_PARAM_LID, AP_CFG_CUSTOM_TEST_CUSTOM1_LID, //zrx add 定义lib id AP_CFG_CUSTOM_FILE_MAX_LID, } CUSTOM_CFG_FILE_LID; //zrx add 添加LID版本信息 #define AP_CFG_CUSTOM_TEST_CUSTOM1_LID_VERNO "000"
第二步:nvram lib id的数据结构和版本号声明
vendor/mediatek/proprietary/custom/project/cgen/inc/Custom_NvRam_data_item.h
//zrx add LID_BIT VER_LID(AP_CFG_CUSTOM_TEST_CUSTOM1_LID) Test_Custom1_Struct *CFG_TEST_CUSTOM1_REC_TOTAL { };
第三步:nvram lib数据结构定义
vendor/mediatek/proprietary/custom/project/cgen/cfgfileinc/CFG_Custom1_File.h
//zrx add start typedef struct { unsigned char Array[1024]; }Test_Custom1_Struct; //zrx add end //zrx add start #define CFG_TEST_CUSTOM1_REC_SIZE sizeof(Test_Custom1_Struct) #define CFG_TEST_CUSTOM1_REC_TOTAL 1 //zrx add end
第四步:nvram lib 默认值定义
vendor/mediatek/proprietary/custom/project/cgen/cfgdefault/CFG_Custom1_Default.h
Test_Custom1_Struct stCustom2Default = { 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
第五步:nvram lib内容加入nvram数组中
vendor/mediatek/proprietary/custom/m107/cgen/inc/CFG_file_info_custom.h
#include "../cfgfileinc/CFG_Custom1_File.h" #include "../cfgdefault/CFG_Custom1_Default.h" const TCFG_FILE g_akCFG_File_Custom[]= { { "/data/nvram/APCFG/APRDCL/Test_Custom1", VER(AP_CFG_CUSTOM_TEST_CUSTOM1_LID), CFG_TEST_CUSTOM1_REC_SIZE, CFG_TEST_CUSTOM1_REC_TOTAL, SIGNLE_DEFUALT_REC , (char *)&stCustom2Default, DataReset , NULL }, };
第六步:nvram lib id需要备份到BinRegion
vendor/mediatek/proprietary/external/nvram/libcustom_nvram/CFG_file_info.c
FileName aBackupToBinRegion[]= { {"CUSTOM_TEST",AP_CFG_CUSTOM_TEST_CUSTOM1_LID}, } pfConvertFunc aNvRamConvertFuncTable[]= { NULL,//AP_CFG_CUSTOM_TEST_CUSTOM1_LID } const TABLE_FOR_SPECIAL_LID g_new_nvram_lid[] = { { AP_CFG_CUSTOM_TEST_CUSTOM1_LID, 1024 * 1024, 1024 * 1024}, };
第七步:上层读写nvram数据接口
NvRAMAgent.java
package com.example.nvram_test; import android.os.IBinder; public interface NvRAMAgent extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements NvRAMAgent { private static final java.lang.String DESCRIPTOR = "NvRAMAgent"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an NvRAMAgent interface, * generating a proxy if needed. */ public static NvRAMAgent asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof NvRAMAgent))) { return ((NvRAMAgent) iin); } return new NvRAMAgent.Stub.Proxy(obj); } public android.os.IBinder asBinder() { return this; } public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_READFILE: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); byte[] _result = this.readFile(_arg0); reply.writeNoException(); reply.writeByteArray(_result); return true; } case TRANSACTION_WRITEFILE: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); byte[] _arg1; _arg1 = data.createByteArray(); int _result = this.writeFile(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } default: { break; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements NvRAMAgent { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } public byte[] readFile(int file_lid) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); byte[] _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(file_lid); mRemote.transact(Stub.TRANSACTION_READFILE, _data, _reply, 0); _reply.readException(); _result = _reply.createByteArray(); } finally { _reply.recycle(); _data.recycle(); } return _result; } public int writeFile(int file_lid, byte[] buff) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(file_lid); _data.writeByteArray(buff); mRemote.transact(Stub.TRANSACTION_WRITEFILE, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } public byte[] readFileByName(String filename) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); byte[] _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(filename); mRemote.transact(Stub.TRANSACTION_READFILEBYNAME, _data, _reply, 0); _reply.readException(); _result = _reply.createByteArray(); } finally { _reply.recycle(); _data.recycle(); } return _result; } public int writeFileByName(String filename, byte[] buff) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(filename); _data.writeByteArray(buff); mRemote.transact(Stub.TRANSACTION_WRITEFILEBYNAME, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_READFILE = (IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_WRITEFILE = (IBinder.FIRST_CALL_TRANSACTION + 1); static final int TRANSACTION_READFILEBYNAME = (IBinder.FIRST_CALL_TRANSACTION + 2); static final int TRANSACTION_WRITEFILEBYNAME = (IBinder.FIRST_CALL_TRANSACTION + 3); } public byte[] readFile(int file_lid) throws android.os.RemoteException; public int writeFile(int file_lid, byte[] buff) throws android.os.RemoteException; public byte[] readFileByName(String filepath) throws android.os.RemoteException; public int writeFileByName(String filepath, byte[] buff) throws android.os.RemoteException; }
第八步:读写数据帮助类
Utils.java
ackage com.example.nvram_test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.util.ArrayList; import android.content.Context; import android.os.IBinder; import android.os.ServiceManager; import android.util.Log; import android.widget.Toast; public class Utils { final String TAG = "Utis"; byte[] buff; Context mContext; public Utils(Context mContext){ this.mContext=mContext; } /** * 多个字节数组合并为一个字节数组 * @param a 字节数组 * @param b 字节数组 * @return byte[] */ public byte[] combineBytes(byte[] a, byte[] b) { byte[] bytes = new byte[a.length + b.length]; System.arraycopy(a, 0, bytes, 0, a.length); System.arraycopy(b, 0, bytes, a.length, b.length); return bytes; } /** * 写文件到app下 */ public void writeOwnFile(String fileName,String message){ try { FileOutputStream fout = mContext.openFileOutput(fileName, mContext.MODE_PRIVATE); byte[] bytes = message.getBytes(); fout.write(bytes); fout.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 从app下读文件 * @param fileName * @return */ public String readOwnFile(String fileName){ try { FileInputStream fis=mContext.openFileInput(fileName); ByteArrayOutputStream bos=new ByteArrayOutputStream(); byte[] buffer=new byte[1024]; int len=0; while((len=fis.read(buffer))!=-1){ bos.write(buff, 0, len); } byte[] content_byte = bos.toByteArray(); String content = new String(content_byte); return content; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return null; } /** * 写文件 * @param fileName 文件名 * @param bytes 字节数组 */ public void writeFile(String fileName,byte[] bytes){ try { FileOutputStream fout = new FileOutputStream(fileName); fout.write(bytes); fout.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 读文件 * @param fileName 文件名 * @return byte[] */ public byte[] readFile(String fileName){ try { FileInputStream fin = new FileInputStream(fileName); int length = fin.available(); byte [] buffer = new byte[length]; fin.read(buffer); fin.close(); return buffer; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return buff; } /** * 写值到NvRam * @param file_name NvRam路径 * @param bytes 字节数组 */ public void writeData(String file_name, byte[] bytes) { byte[] buff=new byte[1024]; if(bytes.length0) { Toast.makeText(mContext, "write Success", Toast.LENGTH_SHORT).show(); // Log.d(TAG, "zrx----write Success"); } else { Toast.makeText(mContext, "write Failure", Toast.LENGTH_SHORT).show(); Log.d(TAG, "zrx---- write Failure"); } } } /** * 从NvRam读值 * @param file_name NvRam路径 * @param offset 开始位置 * @param byteCount 字节数 * @return */ public byte[] readData(String file_name,int offset,int byteCount) { byte[] data=new byte[byteCount]; IBinder binder = ServiceManager.getService("NvRAMAgent"); NvRAMAgent agent = NvRAMAgent.Stub.asInterface(binder); if (agent != null) { try { buff = agent.readFileByName(file_name); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } if (buff != null) { try { for(int i=0;i 第九步:验证
MainActivity.javaimport android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.example.nvram_test.R; public class MainActivity extends Activity{ String TAG="MainActivity"; /** * 文件名在vendor/mediatek/proprietary/custom/m107/cgen/inc/CFG_file_info_custom.h中有定义 */ private static final String TEST_FILENAME = "/data/nvram/APCFG/APRDCL/Test_Custom1"; Button btn1; Button btn2; Button btn3; Button btn4; Utils utils; /** * 测试备份SecretKey文件的路径 */ private static final String secret_filename="/storage/emulated/0/SecretKey"; /** * 测试备份goc_database文件的路径 */ private static final String goc_database="/storage/emulated/0/goc_database"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); utils=new Utils(this); btn1=(Button)findViewById(R.id.btn1); btn2=(Button)findViewById(R.id.btn2); btn3=(Button)findViewById(R.id.btn3); btn4=(Button)findViewById(R.id.btn4); /** * 测试把SecretKey文件的字节备份到NvRam下 */ btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub byte[] a=utils.readFile(secret_filename); //读SecretKey文件 utils.writeData(TEST_FILENAME, a); //把SecretKey文件的字节备份到NvRam下 //byte[] b=utils.readData(TEST_FILENAME, 0, a.length); /* if(!Arrays.equals(a, b)){ utils.writeData(TEST_FILENAME, a); }else{ Toast.makeText(MainActivity.this, "SecretKey Data has existed, no need to backup!", Toast.LENGTH_SHORT).show(); }*/ } }); /** * 测试从NvRAM读SecretKey文件的字节 */ btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub byte[] bytes=utils.readData(TEST_FILENAME,0,27);//测试从NvRAM读SecretKey文件的字节 Toast.makeText(getApplicationContext(), "data = "+new String(bytes), Toast.LENGTH_LONG).show(); } }); /** * 测试写goc_database文件的字节到NvRAM */ btn3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub byte[] bytes=utils.readFile(goc_database); //goc_database文件的字节 byte[] a=utils.readData(TEST_FILENAME,0,27); //读NvRAM下SecretKey文件的字节 utils.writeData(TEST_FILENAME, utils.combineBytes(a, bytes)); } }); /** * 测试写到NvRAM下的goc_database文件字节是否与原文件goc_database是否一样。 */ btn4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub byte[] bytes=utils.readFile(goc_database); //读goc_database文件 byte[] b=utils.readData(TEST_FILENAME, 27, bytes.length); //读NvRAM下的goc_database字节 utils.writeFile("/storage/emulated/0/goc_database2", b); //把NvRAM下的goc_database字节写到goc_database2文件, goc_database2文件与原文件goc_database比对,发现是相同的。 } }); } }
硬件
CPU: Onyx i.MX 6SoloLite [ro.hardware]: [freescale] ro.product.manufacturer]: [Onyx] [ro.build.fingerprint]: [Onyx/JDRead/JDRead:4.4.2/2018-06-29_16-28_r3_a9ff2db/371:user/dev-keys]
开启USB调试
(0)联网
开启JDRead1,连接WiFi
(1)设置密码为0423
设置-设备名称-密码设置:密码输入0423,手机号输入自己的手机号。
为什么设置密码为 0423, 请看 https://www.senventise.com/posts/jdread1-exploit/
(2)开启开发者权限
设置-设备名称-设备信息:连续点击系统版本,直到显示“已开启开发者权限”。
https://www.cnblogs.com/arbo/p/14619813.html
用kingroot进行root
jdread1小白教程及软件v2.2.zip
提醒: 不要替换 services.jar
型号: DP75SDI
属于 Kindel的 第七代 产品
2015 年 6 月 17 日,亚马逊上架了全新 Kindle Paperwhite(KPW3)电子书阅读器。像素 300 ppi, RAM增大了一倍,也就是说运行速度也会有较大提升,但Storage依然是 4GB。 这款新机在亚马逊中国上的预订价格为 958 元,2015 年 6 月 30 日正式发货。
Jailbreak
参考资料:
https://www.mobileread.com/forums/showthread.php?t=225030
https://bookfere.com/post/892.html
https://bookfere.com/post/311.html
https://bookfere.com/post/59.html
设备信息
序列号 G090 G1
固件版本 5.8.11
硬件 Hardware : Freescale i.MX 6SoloLite based Wario Board
步骤:
1. 通过序列号 确定型号
(G090G1 Kindle PaperWhite 3 (2015) WiFi PW3 型号)
可以root / jailbreak
2. 充满电
3. 关掉密码 , 关掉家长控制
4. 开启 飞行模式,关闭3G/WiFi
更新到 5.12.3 固件 https://s3.amazonaws.com/firmwaredownloads/update_kindle_all_new_paperwhite_5.12.3.bin
固件文件名:update_kindle_all_new_paperwhite_5.12.3.bin
MD5 校验码:e4d7ff60132c58448b0c1b31d5961b12
SHA1 校验码:ff8cf3a93ce37f6adf7c12b5166f73dc0ba929fe
6. 下载 kindle-jb-kindlebreak-1.0-r18327.tar.xz
下载 jb-kindlebreak.zip 并解压,得到下列四个文件,把它们全部拷贝到 Kindle 根目录(所谓根目录,就是那个目录下有一个叫documents的子目录)
kindlebreak.jxr
kindlebreak.html
jb.sh
jb
接着点击 Kindle 右上角的菜单按钮,进入“体验版网页浏览器(Experimental Browser)”。
请务必确保“浏览器设置”中的图片设置处于启用状态,也就是显示“禁用图片(Disable Images)”字样。如显示的是“启用图片(Enable Images)”字样,你需要点击启用,以确保浏览器能够正常解析图片。
最后输入如下所示的文件地址(注意 file:/// 是一个冒号三个斜杠):
file:///mnt/us/kindlebreak.html
如果一切正常,Kindle 会在数秒至数分钟后自动重启(时长取决于不同设备)。重启完毕越狱便告成功。之前放进去的文件会被自动清理,你会在 Kindle 根目录看到一个日志文件 kindlebreak_log.txt。
7. 安装热修复补丁 JailBreak-1.16.N-FW-5.x-hotfix.zip
Jailbreak Hotfix 的具体安装步骤如下:
(1)用 USB 数据线把 Kindle 连接到电脑,直到出现 Kindle 盘符;
(2)解压缩下载到的 ZIP 压缩包 JailBreak-x.xx.N-FW-5.x-hotfix.zip,得到一个名为 Update_jailbreak_hotfix_x.xx.N_install.bin 的文件;
(3)将此 bin 文件拷贝到 Kindle 磁盘根目录,然后从电脑弹出 Kindle;
(4) 依次在 Kindle 中点击【菜单 → 设置 → 菜单 → 更新您的 Kindle】,等待重启;
8. 安装 MobileRead Package Installer (MRPI)
(1)用 USB 数据线将 Kindle 连接到电脑上,直到出现 Kindle 磁盘;
(2) 解压缩下载到的 kual-mrinstaller-1.7.N-xxx.tar.xz 得到一个文件夹;
(3)把文件夹内的 extensions 和 mrpackages 拷贝到 Kindle 的根目录。
(4)从电脑上断开 Kindle磁盘,重启Kindel
注意,如果根目录已有 extensions 这个文件夹,可以只把解压得到的 extensions 文件夹中的内容拷贝到 Kindle 根目录原有的 extensions 文件夹内,以避免原文件夹内的其它文件被删除。
9. 安装 KUAL ( Kindle Unified Application Launcher)
(1) 用 USB 数据线将 Kindle 连接到电脑上,直到出现 Kindle 磁盘;
(2) 如果没有安装MRPI, 先按照第8步的方法安装 MobileRead Package Installer (MRPI);
(3) 然后解压缩下载到的 KUAL-v2.x.xx-xxxxxxxx-20xxxxxx.tar.xz 得到一个文件夹;
在文件夹中找到 Update_KUALBooklet_v2.x.xx_install.bin 文件,拷贝到 Kindle 根目录下的 mrpackages 文件夹,然后在 Kindle 搜索框中输入 ;log mrpi 点击回车;
这时会调用 mrpi 安装 KUAL,安装完成并等待 Kindle 重启完毕后即可使用 KUAL。
10. 安装 Koreader
首先确保安装了 MRPI 和 KUAL;
用 USB 数据线将 Kindle 连接到电脑上,直到出现 Kindle 磁盘;
解压缩下载到的 Koreader 压缩包,可得到 extensions 和 koreader 两个文件夹;
先把文件夹 extensions 中的内容拷贝到 Kindle 根目录下的 extensions 文件夹中;
然后把文件夹内的 koreader 文件夹拷贝到 kindle 根目录下;
通过 KUAL 菜单中启动 Koreader 并用它的文件浏览器打开并阅读电子书。
11. 安装 USBNetwork
(1)首先确保安装了 MRPI 和 KUAL;
(2)用 USB 数据线将 Kindle 连接到电脑上,直到出现 Kindle 磁盘;
(3) 解压缩下载到的 kindle-usbnet-0.xx.N-rxxxxx.tar.xz 压缩包,得到一个文件夹;
(4) 把文件夹内的 Update_usbnet_0.xx.N_install_pw2_and_up.bin 拷贝到 Kindle 里 mrpackages 文件夹中;
(5)弹出 Kindle 磁盘,进入 Kindle 界面,打开 KUAL,依次点击菜单【Helper → Install MR Packages】(或在搜索栏输入 ;log mrpi 并回车);
耐心等待 USBNetwork 安装,直到安装完成后 Kindle 重启完毕;
配置 USBNetwork
修改配置文件
重启完成后,可以在 Kindle 根目录可以看到 usbnet 文件夹。首先将此文件夹中的文件 DISABLED_auto 重命名为 auto。然后在此文件夹里的 etc 文件夹中找到配置文件 config,并用代码编辑器(如 Sublime Text)将其打开。找到 USE_WIFI 和 USE_WIFI_SSHD_ONLY 两个配置项,将两者的值从默认的 false 修改为 true(注意,两者都要改成 true),保存并关闭。
USE_WIFI="true" USE_WIFI_SSHD_ONLY="true"
如果不将USE_WIFI_SSHD_ONLY 改为true, 会导致 将kindel通过usb插入电脑时, 不识别 Kindle 磁盘
创建密钥
ssh-keygen -t rsa -f ~/Desktop/KindleKey
会在你的桌面上会出现 KindleKey 和 KindleKey.pub 两个文件,把其中的 KindleKey.pub 重命名为 authorized_keys,并拷贝到 usbnet 插件目录中的 etc 文件夹中。
ssh登陆到kindle
ssh -i KindleKey root@192.168.xxx.xxx
在 Kindle 搜索框中输入 ;711 可以看到 Kindel分配到IP地址
Redmi Note 10 Pro
天玑1100
CPU型号为 MT6891Z/CZA
( MT6885,天玑1000L, 联发科的首款5G芯片)
sysfs
/sys/kernel/ccci /sys/class/ccci_node/ccci_ccb_meta /sys/class/ccci_node/ccci_ccb_md_monitor /sys/class/ccci_node/ccci_raw_mdm /sys/class/ccci_node/ccci_mdl_monitor /sys/class/ccci_md_sta/ccci_md1_sta /sys/firmware/devicetree/base/mddriver/ccci,modem_info_v2
代码
drivers/misc/mediatek/ccci_util/ccci_util_lib_load_img.c drivers/misc/mediatek/ccci_util/ccci_util_lib_sys.c drivers/misc/mediatek/eccci/ccci_core.c ccci_init(void) drivers/misc/mediatek/eccci/mt6885/ccci_platform.c ccci_plat_common_init 配置地址 drivers/misc/mediatek/eccci/ccci_modem.c void ccci_md_config(struct ccci_modem *md) { phys_addr_t md_resv_mem_addr = 0, md_resv_smem_addr = 0, md1_md3_smem_phy = 0; unsigned int md_resv_mem_size = 0, md_resv_smem_size = 0, md1_md3_smem_size = 0; int amms_pos_size = 0; phys_addr_t bank4_phy_addr; ...... ...... /* Get memory info */ get_md_resv_mem_info(md->index, &md_resv_mem_addr, &md_resv_mem_size, &md_resv_smem_addr, &md_resv_smem_size); get_md1_md3_resv_smem_info(md->index, &md1_md3_smem_phy, &md1_md3_smem_size); /* setup memory layout */ /* MD image */ md->mem_layout.md_bank0.base_ap_view_phy = md_resv_mem_addr; md->mem_layout.md_bank0.size = md_resv_mem_size; /* do not remap whole region, consume too much vmalloc space */ md->mem_layout.md_bank0.base_ap_view_vir = ccci_map_phy_addr( md->mem_layout.md_bank0.base_ap_view_phy, MD_IMG_DUMP_SIZE); /* Share memory */ /* * MD bank4 is remap to nearest 32M aligned address * assume share memoy layout is: * |---AP/MD1--| <--MD1 bank4 0x0 (non-cacheable) * |--MD1/MD3--| <--MD3 bank4 0x0 (non-cacheable) * |---AP/MD3--| * |--non-used_-| * |--cacheable--| <-- MD1 bank4 0x8000000 (for 6292) * this should align with LK's remap setting */ eccci/modem_sys1.c ccci_set_mem_access_protection_1st_stage(md); eccci/fsm/ccci_fsm.c ccci_set_mem_access_protection_second_stage
modem firmware的结构
代码位于 drivers/misc/mediatek/ccci_util/ccci_util_lib_load_img.c
#define IMG_MAGIC 0x58881688 #define EXT_MAGIC 0x58891689 #define IMG_NAME_SIZE 32 #define IMG_HDR_SIZE 512 union prt_img_hdr { struct { /* always IMG_MAGIC */ unsigned int magic; /* image size, image header and padding are not included */ unsigned int dsize; char name[IMG_NAME_SIZE]; /* image load address in RAM */ unsigned int maddr; /* maddr is counted from the beginning or end of RAM */ unsigned int mode; /* extension */ /* always EXT_MAGIC */ unsigned int ext_magic; /* header size is 512 bytes currently, * but may extend in the future */ unsigned int hdr_size; /* see HDR_VERSION */ unsigned int hdr_version; /* please refer to #define beginning with SEC_IMG_TYPE_ */ unsigned int img_type; /* end of image list? * 0: this image is followed by another image * 1: end */ unsigned int img_list_end; /* image size alignment setting in bytes, * 16 by default for AES encryption */ unsigned int align_size; /* high word of image size for 64 bit address support */ unsigned int dsize_extend; /* high word of image load address in RAM * for 64 bit address support */ unsigned int maddr_extend; } info; unsigned char data[IMG_HDR_SIZE]; };
OAI 5G NR SA tutorial with COTS UE
https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md
SMA天线接口 有3个输入信号:
1. 外部 PPS 参考
2. 10 MHz 时钟 参考
3. GPS信号
都是所谓 Timing Reference Input (定时基准输入)
1 PPS
秒脉冲 (Pulse Per Second)
PPS 时间参考 和 10MHz 时钟参考,主要用于多个 B210之间进行同步。
B210接受外部PPS信号进行时间校准,以及10 MHz参考频率校准—这允许外部时间和频率源用于更精确的同步
GPS则可实现 在物理位置上相距非常大的 多个B210之间 的时间同步。
GPS时钟主要分为两类,
一类是GPS授时仪,主要输出时标信息,包括1 PPS及TOD信息;
另外一类是GPS同步时钟,后者输出利用卫星信号驯服OCXO或者铷钟得到的高稳定频率信息,以及本地恢复的更平稳的时标信号。
高精度1 PPS信号,精度优于50ns,占空比为50%,1 PPS信号 上升沿为时间同步点,上升沿时间小于5ns。
两个接收前端共享RX LO(本振),而两个发射前端共享TX LO。每个本振可在50mhz和6ghz之间独立调谐,可用于1或2个信道;所有使用相同本振的信道必须使用相同的采样参数,包括采样率和射频中心频率。
附带的USB 3.0电缆为USRP总线系列提供电源和数据连接。
我的板子带了GPSDO,必须连接外部直流电源(12V 3A)
所有GPSDO都有一些共同的特性。每个GPSDO包括一个10 MHz振荡器,可以是TCXO或OCXO。10MHz振荡器可以独立工作,也就是说,
即使GPSDO没有锁定到卫星星座,它也可以提供时钟。
根据GPSDO型号,解锁振荡器将提供20~75 ppb之间的系统频率精度。
GPSDO模块还将产生1-pps信号,用于定时同步。如果连接了GPS天线,GPSDO将锁定到GPS卫星星座,并且10 MHz振荡器可以按照全球GPS标准进行调节。在这种情况下,1-pps信号也将在50ns内与全球标准对齐。
共享一个时钟总是比尝试通过GPS同步要好。gpsdo将代替共享时钟,提供下一个最佳的同步级别,这对于大多数应用程序来说已经足够了。
但前面也说了,GPS也更加灵活,因为设备可以在地理上相隔十万八千里,但依然保持同步。
板载OCXO和板载TCXO的结构和工作原理是相同的。然而,TCXO消耗较少的功率,在其整个温度范围内提供较少的精度,并且具有不同的相位噪声特性。
我的是 OCXO, 需要外接电源。
输入/输出阻抗
所有射频端口通常匹配50欧姆,回波损耗为-10dB或更好
LED600 电源指示
灭 = 无供电 或者 外部供电,但初始化 未完成
蓝 = USB供电
红 = 外部供电成功(初始化完成)
LED800 通道2 接收2
灭 = 无供电
绿色 = 正在接收
LED801 通道2 发送/接收
灭 = 无供电
绿色 = 正在接收
红色 = 正在发送
橙色 = 正在切换(发送或接收)
LED802 通道1 发送/接收
灭 = 无供电
绿色 = 正在接收
红色 = 正在发送
橙色 = 正在切换(发送或接
LED803 通道1 接收2
灭 = 无供电
绿色 = 正在接收
LED100 GPS锁定指示
灭 = 没有锁定
绿色 = 已经锁定
J601 外部供电接口 6V 3A
J701 USB3 接口
J104 外部PPS 输入 (1.8 V – 5 V )
J101 GPS天线 (GPSDO will supply nominal voltage to antenna)
J100 外部10 MHz输入 (最大 +15 dBm )
J800 射频天线B TX/RX (发射功率 最大+20 dBm, 接收 -15 dBm)
J802 射频天线B 接收2 ( 接收 -15 dBm)
J803 射频天线A 接收2 ( 接收最大 -15 dBm)
当使用 GPSDO 时, 不能使用 外部10MHz 输入, 除非将 GPSDO从板子上拿走