重要提示:此文仅为个人折腾之记录,放自己博客以防健忘。刷机有风险,他人勿模仿,禁止转载
另声明:本人没建立任何QQ群,也没在任何群里面
前言
中兴F7607P是个好猫,之前已实现登陆Telnet后修改wantype
值来切换上行口光模式为XGPON或10G EPON,改为5后型号会自动变为F4607P。联通定制版机器在执行以下命令后可以正常稳定工作在10G EPON模式下
setmac 1 40960 5
setmac 1 32769 MAC地址
而移动定制版切换后PON状态为未注册未认证,此前的解决的办法是开盖接TTL适配器进入uboot,在uboot下写入联通版的分区备份。由于开盖属于破坏性折腾,所以一直在寻找不开盖不关机在线替换mtd分区的办法,最终在网友@longdike
的无私帮助下找到解决办法,记录一下以访自己忘记
开启Telnet
- 在线自助开启中兴Telnet
- zte_factroymode.py实力网友@douniwan逆向固件后的开源python工具。十分感谢!
备份原机闪存
折腾任何机器的第一步永远是备份,对于F7607P来说犹如此。从目前已知的信息看,此机器CPU为ZX279132s,属于高安芯片,带secure boot,闪存内的uboot被加密和签名过,且其中绑定了CPU id或NAND id,具体哪个还未知,已知的就是自己的uboot只能在自己的机器上用,别人的uboot分区备份在自己的机器上启动不了,所以一定要备份好自己的uboot分区,万一挂了又没有备份的话就会彻底变砖,编程器也救不了。
以上分析只针对uboot版本V2.0.5P1N1,编译时间为20211203,其他版本的uboot是否有相同验证机制未知
插入NTFS或FAT32格式的优盘,Telnet登陆后可以使用如下命令备份完整闪存:
dd if=/dev/mtd0 of=/mnt/usb1_1/f7607p_dd.bin
或
cat /dev/mtd0 > /mnt/usb1_1/f7607p_cat.bin
或
nand kread /dev/mtd0 0x0 0x10000000 /mnt/usb1_1/f7607p_nand.bin
保险起见可以三种方式都备份一次。优盘目录名测试移动版默认为usb1_1,联通版默认为USB1_disc1,电信版默认为USB_disc1。可以使用df
命令查看挂载的目录名。另知联通和电信版busybox阉割了dd
命令
我备份的移动版kernel和osgi插件分区:Part1, Part2, Part3
联通版闪存结构分析
看一下联通版固件的分区结构
/ # cat /proc/mtd
dev: size erasesize name
mtd0: 10000000 00020000 "whole flash"
mtd1: 00200000 00020000 "u-boot"
mtd2: 00200000 00020000 "others"
mtd3: 00200000 00020000 "parameter tags"
mtd4: 00200000 00020000 "wlan"
mtd5: 00800000 00020000 "usercfg"
mtd6: 00600000 00020000 "preplugin"
mtd7: 02800000 00020000 "kernel1"
mtd8: 02800000 00020000 "kernel2"
mtd9: 01000000 00020000 "framework"
mtd10: 01000000 00020000 "framework1"
mtd11: 07900000 00020000 "plugin_data"
mtd12: 024c0000 00020000 "rootfs"
其中kernel1和kernel2完全一样,uboot启动时会读取mtd2中的BootImageNum
值,其为0的话就从kernel1启动,1的话从kernel2启动,如果被选择的分区无法通过crc和rsa等校验,则会从另一个kernel分区启动。rootfs分区是kernel分区内的一部分。framework和framework1是插件分区,也完全相同,互为备份。移动版固件要改为联通版,只用核心功能的话,只需要替换mtd7和mtd8就行,要完整替换的话还需要替换mtd9和mtd10插件分区,mtd12由于被包含在mtd7或mtd8之内,所以不需要再单独额外替换。
开始替换
准备好用于替换的几个联通版分区备份文件:Part1,Part2,对比下hash值以防分区数据出错,kernel分区差一个字节也无法启动
kernel.bin sha-256: 37bc69e02f87b87c963675b5f8a61c9ed9cd5dd16b5116fedcafcf8b6acd18e9
framework.bin sha-256: 8097258c6c38662cb93e71280cab8569d7064fac1b919419ce269dcc8b7c3363
放入NTFS或FAT32格式的优盘,插入光猫USB接口,进入Telnet,运行fw_flashing
,会报错并给出当前启动的内核分区,如:
baseaddr:1600000, curpdev=/dev/mtd7, offset=0
如果上面fw_flashing
的结果和示例一样是mtd7
的话,执行命令upgradetest switchver 1
;如果是mtd8
的话,则执行upgradetest switchver 0
。作用是下一次启动时切换到另一个分区。(credit: @longdike)
根据上面fw_flashing
的结果更改{待定1}
的值:
如果 (fw_flashing
== mtd7
) 那么 { {待定1}
== mtd8
};
如果 (fw_flashing
== mtd8
) 那么 { {待定1}
== mtd7
}
这里插播一条重要提醒:上面和后面相似的判断逻辑,目的是为了判断系统当前启动的kernel分区,然后把固件写入另一个当前没有被使用的分区,避免直接对正在运行中的Kernel分区做覆盖,很可能会写入失败并且产生大量坏块,这是血的教训,一定判断仔细
严格按顺序执行以下命令,一次一行
cd /mnt/usb1_1
echo 2 > /proc/zteinfo/factory/factorymode
touch /userconfig/nanddebug
nand kerase /dev/{待定1} 0x0 0x2800000
nand kwrite /dev/{待定1} 0x0 0x2800000 ./kernel.bin
完成后reboot
重启,开机后应该就进入联通系统了,进入Telnet继续按顺序执行以下命令
再次运行fw_flashing
,并根据结果更改{待定2}
的值:
如果 (fw_flashing
== mtd7
) 那么 { {待定2}
== mtd8
};
如果 (fw_flashing
== mtd8
) 那么 { {待定2}
== mtd7
}
cd /mnt/USB1_disc1
echo 2 > /proc/zteinfo/factory/factorymode
nand kerase /dev/{待定2} 0x0 0x2800000
nand kwrite /dev/{待定2} 0x0 0x2800000 ./kernel.bin
nand kerase /dev/mtd9 0x0 0x1000000
nand kwrite /dev/mtd9 0x0 0x1000000 ./framework.bin
nand kerase /dev/mtd10 0x0 0x1000000
nand kwrite /dev/mtd10 0x0 0x1000000 ./framework.bin
nand kerase /dev/mtd11 0x0 0x7900000
nand kerase /dev/mtd6 0x0 0x600000
rm /userconfig/nanddebug
移动和联通版的区域代码不一样,改后可能需要重新设置一下,使用cat /etc/init.d/regioncode
查看区域码对照表,找到想要的区域代码,例如上海为305,然后用命令upgradetest sdefconf 305
切换区域为上海。切换后猫会自动重启,加载上海地区的默认配置,当然telnet又被关闭了。
cat regioncode
300:Jiangsu
301:Xinjiang
302:Hainan
303:Tianjin
304:Anhui
305:Shanghai
306:Chongqing
307:Beijing
308:Sichuan
309:Shandong
310:Guangdong
311:Hubei
312:Fujian
313:Suzhou
314:Zhejiang
315:Shanxi
316:Hunan
317:Yunnan
318:Xizang
319:Heilongjiang
320:Guizhou
321:Shanxi2
322:Hebei
323:Ningxia
324:Guangxi
325:Jiangxi
326:Gansu
327:Qinghai
328:Xian
329:Liaoning
330:Jilin
331:Neimeng
332:Henan
不需要设置区域代码的话直接重启,至此已完整替换移动版固件为联通版,/cu.html登陆,MAC地址/SN等信息也还是机身标签上的。要改参数的话可以使用setmac show2
查看对应的ID,然后setmac 1
更改。
另须注意:
- 北京联通没有超级管理员账户,不建议将区域设置为北京
想象中的骚操作:双固件共存与切换(已验证可行)
既然可以使用命令手动切换下一次启动的kernel分区,那是否可以保持kernel1为移动版固件,kernel2刷成联通版固件?缺点就是切换后插件和容器功能无法正常使用,核心上网功能应该不受影响。本人未实际尝试,但理论上完全可行且无风险。如果需要尝试的话,以上步骤进行到第一个reboot
处就可以结束了,之后使用命令upgradetest switchver 1
或upgradetest switchver 0
切换不同固件。0为mtd7,即移动固件,1为mtd8,即联通版固件。
/userconfig/cfg
这个目录用于存放用户的配置文件,可以把不同固件下正常使用时的配置文件都另拷贝一份,运行上面切换分区的命令前,先用对应版本的配置文件覆盖cfg文件夹,这样不用重复配置区域代码重置设置
改电信版的尝试
改电信版固件理论上应该是一样的,只要有对应的闪存分区备份就行。正好从网友处得到了电信版的闪存备份,但由于本人的粗心操作,在开机状态下直接覆写了正在使用的分区,导致该分区产生大量坏块,已无法使用。两个kernel分区只剩下一个活命。怯于光猫亡命,不敢再继续折腾剩下的这个独苗分区,只能期待其他人的继续验证
Update: 已成功消除坏块标记并写入电信固件和移动固件共存,详见:清除中兴F7607P/F4607P的NAND闪存坏块标记
继续尝试远程改电信版F4607P
吸取上面的教训后,成功远程在网友的猫上将联通版改为电信版,记录如下,感谢网友@song
首先看电信版的分区结构:
/ # cat /proc/mtd
dev: size erasesize name
mtd0: 10000000 00020000 "whole flash"
mtd1: 00200000 00020000 "u-boot"
mtd2: 00200000 00020000 "others"
mtd3: 00200000 00020000 "parameter tags"
mtd4: 00200000 00020000 "wlan"
mtd5: 00800000 00020000 "usercfg"
mtd6: 01000000 00020000 "framework"
mtd7: 01000000 00020000 "framework1"
mtd8: 00600000 00020000 "dbus"
mtd9: 02800000 00020000 "kernel1"
mtd10: 02800000 00020000 "kernel2"
mtd11: 07900000 00020000 "plugin_data"
mtd12: 024c0000 00020000 "rootfs"
和移动与联通版不同,电信版的kernel分区改为了mtd9和mtd10,但实际在闪存中的地址不变,还是0x1600000-0x3e00000和0x3e00000-0x6600000,大小也还是0x2800000,rootfs的结构也一样,所以可以继续使用上面的方法替换,只需稍加改动
准备电信版F4607P的固件
感谢不记名网友分享的电信版F4607P的闪存分区: Part1,Part2,解压后放入NTFS或FAT32格式的优盘,对比下hash值:
kernel_CT.bin sha-256: d6b98566985a7e812d7d7fa50a6e442592050dcc5923794bcdd506993f8868f8
framework_CT.bin sha-256: 28afbbb861102763ac0c84f16c38958abbd1c8448946aa692b5d5430dcb2dd54
该网友机器的两个kernel分区固件版本不同,mtd9为V2.0.0P1N6,编译时间20220422;mtd10为V2.0.0P1N7,编译时间20220521。经测试mtd10的备份写入后无法启动,应该是没通过校验,可能网友在备份的过程中出现差错,也可能是固件本身就有问题,于是只用mtd9的备份作为替换用的固件。
另说明,F4607P和F7607P其实无论硬件还是固件都是同一个,固件名都叫做ZXHN F7607P XXX
,型号的区分只通过wantype的取值来确定
开始替换
替换步骤和改联通版本时一样,再赘述下,以访自己健忘,需注意细微的区别
放入NTFS或FAT32格式的优盘,插入光猫USB接口,进入Telnet,运行fw_flashing
,会报错并给出当前启动的内核分区,如:
baseaddr:1600000, curpdev=/dev/mtd7, offset=0
如果上面fw_flashing
的结果和示例一样是mtd7
的话,执行命令upgradetest switchver 1
;如果是mtd8
的话,则执行upgradetest switchver 0
。作用是下一次启动时切换到另一个分区。(credit: @longdike)
运行fw_flashing
,并根据结果更改{待定1}
的值:
如果 (fw_flashing
== mtd7
) 那么 { {待定1}
== mtd8
};
如果 (fw_flashing
== mtd8
) 那么 { {待定1}
== mtd7
}
cd /mnt/usb1_1
echo 2 > /proc/zteinfo/factory/factorymode
touch /userconfig/nanddebug
nand kerase /dev/{待定1} 0x0 0x2800000
nand kwrite /dev/{待定1} 0x0 0x2800000 ./kernel_CT.bin
完成后reboot
重启,开机后应该就进入电信系统了,进入Telnet继续按顺序执行以下命令。
再次运行fw_flashing
,并根据结果更改{待定2}
的值:
如果 (fw_flashing
== mtd9
) 那么 { {待定2}
== mtd10
};
如果 (fw_flashing
== mtd10
) 那么 { {待定2}
== mtd9
}
cd /mnt/USB_disc1
echo 2 > /proc/zteinfo/factory/factorymode
nand kerase /dev/{待定2} 0x0 0x2800000
nand kwrite /dev/{待定2} 0x0 0x2800000 ./kernel_CT.bin
umount /opt/upt/apps/mnt1(移动版刷电信固件不用这一步)
umount /opt/upt/apps/mnt2(移动版刷电信固件不用这一步)
nand kerase /dev/mtd6 0x0 0x1000000
nand kwrite /dev/mtd6 0x0 0x1000000 ./framework_CT.bin
nand kerase /dev/mtd7 0x0 0x1000000
nand kwrite /dev/mtd7 0x0 0x1000000 ./framework_CT.bin
nand kerase /dev/mtd8 0x0 0x600000
nand kerase /dev/mtd11 0x0 0x7900000
rm /userconfig/nanddebug
然后根据需要选择一个区域码配置,不然还是用的之前联通版的配置文件,会产生莫名其妙的问题。使用cat /etc/init.d/regioncode
查看区域码对照表,找到想要的区域代码,例如上海为205,然后用命令upgradetest sdefconf 205
切换区域为上海。切换后猫会自动重启,加载上海地区的默认配置,当然telnet又被关闭了。
/ # cat regioncode
200:Jiangsu
201:Xinjiang
202:Hainan
203:Tianjin
204:Anhui
205:Shanghai
206:Chongqing
207:Beijing
208:Sichuan
209:Shandong
210:Guangdong
211:Hubei
212:Fujian
214:Zhejiang
215:Shanxi
216:Hunan
217:Yunnan
218:Xizang
219:Heilongjiang
220:Guizhou
221:Shanxi2
222:Hebei
223:Ningxia
224:Guangxi
225:Jiangxi
226:Gansu
227:Qinghai
229:Liaoning
230:Jilin
231:Neimeng
232:Henan
234:TelecomInstitute
电信原版F4607P出厂时已配置好了ponmac,值为MAC8的值加1,也就是MAC1即机身标签上的MAC值加8(16进制)。其他原厂为XGPON的版本改为10G EPON后都需要手动使用setmac 1 32769 MAC地址
设置ponmac。如果提示setmac failed
的话,使用如下命令设置。此处仅表明中兴原厂的ponmac设置规则,不代表必须如此设置。ponmac可以是任意合法的MAC值,只要同一个OLT下没有重复就行。如果运营商有绑定光猫ponmac,则需将其设置为老猫的ponmac值,或直接Call小哥解除绑定
echo 2 > /proc/zteinfo/factory/factorymode
setmac 1 32769 MAC地址
echo 0 > /proc/zteinfo/factory/factorymode
电信固件和联通固件部分省份没注册ITMS服务器的话会劫持所有DNS请求的结果到192.168.1.1,使用如下命令手动欺骗ITMS注册结果
sendcmd 1 DB set PDTCTUSERINFO 0 Status 0
sendcmd 1 DB set PDTCTUSERINFO 0 Result 1
sendcmd 1 DB save
另已知:
- 电信版中兴系统的登陆入口不是80端口,而是8080。80端口为插件内的系统,直接访问8080端口会自动跳转到80端口登陆,所以电信版没有插件分区无法进入网页后台。
- 跳转不影响frp或端口转发,照常开Telnet,无需理会跳转,但最好把frp服务器直接改为IP地址,避免frp服务器域名同样被劫持。打开Tenet后再使用上述命令欺骗ITMS注册结果,重启光猫,刷新电脑DNS缓存
- 电信版固件在网页后台可以自由切换XGPON和XEPON模式
- 电信版某些省份的默认配置限制较多,需要特别注意的是陕西直接屏蔽了WiFi,建议使用区域代码
234
电信研究院
U-boot下写入固件
如果两个kernel分区都已经损坏无法启动的话,只能接TTL在uboot下写入分区备份
写这段的时候正看到U-boot之父Wolfgang Denk去世的消息,RIP,感谢
安装OpenTFTP或tftpd64等tftp服务端软件,将分区备份放入tftp的工作目录内,给光猫通电,然后迅速按任意键中断启动,进入U-boot控制台
先设置本机和TFTP服务器IP:
setenv ipaddr 192.168.2.2
setenv serverip 192.168.2.3
saveenv
然后开始下载分区备份到内存并写入到NAND中对应的位置,三家运营商的版本kernel分区的位置大小一样,写入命令一样,但移动版的osgi分区与联通电信版的framework分区位置和大小不同,需注意
- 移动/联通/电信版写入kernel分区:
tftp 0x88000000 kernel.bin
nand erase 0x1600000 0x2800000
nand erase 0x3e00000 0x2800000
nand write 0x88000000 0x1600000 0x2800000
nand write 0x88000000 0x3e00000 0x2800000
- 移动版写入osgi分区:
tftp 0x88000000 osgi.bin
nand erase 0x6600000 0x3200000
nand erase 0x9800000 0x3200000
nand write 0x88000000 0x6600000 0x3200000
nand write 0x88000000 0x9800000 0x3200000
- 联通/电信版写入framework分区:
tftp 0x88000000 framework.bin
nand erase 0x6600000 0x1000000
nand erase 0x7600000 0x1000000
nand write 0x88000000 0x6600000 0x1000000
nand write 0x88000000 0x7600000 0x1000000
reset
重启
一些折腾中发现的其他东西,记录一下
/ # cat /proc/csp/versionstates
baseaddress : 0x1600000
current : 0
version1states : 0x8f
version2states : 0x0
____________________________________________________
Index Running Latest CRC Integrality Type
----------------------------------------------------
0 Y Y Y Y Upg
1 N N N N Upg
----------------------------------------------------
查看两个kernel分区的情况,baseaddress是当前运行的分区在闪存中的起始位置,current为当前运行的分区代号,下面还有CRC和完整性校验的结果,但这里的CRC校验结果并代表实际情况,好的也会显示N
upgradetest getver
获取两个kernel分区中固件的版本号
hexdump -C -s 0x180 -n 128 /dev/mtd7
输出kernel分区的固件版本号和编译日期部分,移动联通为mtd7和mtd8,电信为mtd9和mtd10
00000180 5a 58 48 4e 20 46 37 36 30 37 50 20 55 4e 49 20 |ZXHN F7607P UNI |
00000190 56 32 2e 30 2e 36 50 31 4e 32 00 00 00 00 00 00 |V2.0.6P1N2......|
000001a0 01 00 00 00 00 48 08 00 40 00 54 04 7e f2 f6 49 |[email protected].~..I|
000001b0 00 00 7e 02 00 00 d6 01 17 07 c4 96 00 00 00 00 |..~.............|
000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................|
000001e0 8d a4 a1 c0 32 30 32 32 30 35 31 36 32 32 35 32 |....202205162252|
000001f0 34 33 00 00 00 00 00 00 ff ff ff ff ff ff ff ff |43..............|
00000200
/ # cat /proc/capability/boardinfo
system:LINUX
cpufac:ZXIC
cpumod:ZX279132
2gwlmod:INTEL
5gwlmod:INTEL
cpufre:1100MHZ
cpunum:4
flshcap:256MB
ddrcap:512MB
查看硬件配置信息,可以看到WiFi芯片是英特尔的,有传言新版会用MTK的
删除定制版WiFi名字的强制CMCC_和ChinaNet_前缀
sendcmd 1 DB set WLANCfg 0 ESSIDPrefix
sendcmd 1 DB set WLANCfg 4 ESSIDPrefix
sendcmd 1 DB save
ip link set mini-olt down
rmmod optical
rmmod mtlk
rmmod mtlkroot
关闭下行GPON光口和WiFi,功率从12.5W降低到9.7W,一年能省25度电,10元钱。再次开启:重启或者
insmod /kmodule/optical.ko
insmod /kmodule/mtlkroot.ko
insmod /kmodule/mtlk.ko
加密配置文件的密钥每台机器都不一样,根据出厂时内置在tagparam文件中的INDIVKEY
值生成,一段32位的随机值,每台机器都不一样,独立生成,和MAC/SN值都无关。所以想要导出配置文件再解密是不可能的
分割mtd0
备份的mtdblock0是整个闪存256MB的完整备份,如需要单独恢复某个分区的话,使用16进制编辑器按照下面的地址分割
0x000000000000-0x000000200000 : "u-boot" size: 0x200000
0x000000200000-0x000000400000 : "others" size: 0x200000
0x000000400000-0x000000600000 : "parameter tags" size: 0x200000
0x000000600000-0x000000800000 : "wlan" size: 0x200000
0x000000800000-0x000001000000 : "usercfg" size: 0x800000
0x000001000000-0x000001600000 : "middle" size: 0x600000
0x000001600000-0x000003e00000 : "kernel1" size: 0x2800000
0x000003e00000-0x000006600000 : "kernel2" size: 0x2800000
0x000006600000-0x000009800000 : "osgi1" size: 0x3200000
0x000009800000-0x00000ca00000 : "osgi2" size: 0x3200000
0x00000ca00000-0x000010000000 : "plugin_data" size: 0x3600000
0x000001920000-0x000003e00000 : "rootfs" size: 0x024e0000
再次重要提示:此文仅为个人折腾之记录,放自己博客以防健忘。刷机有风险,他人勿模仿,禁止转载
另声明:本人没建立任何QQ群,也没在任何群里面
Last modified: