重要提示:此文仅为个人折腾之记录,放自己博客以防健忘。刷机有风险,他人勿模仿,禁止转载

另声明:本人没建立任何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

备份原机闪存

折腾任何机器的第一步永远是备份,对于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之内,所以不需要再单独额外替换。

开始替换

准备好用于替换的几个联通版分区备份文件:Part1Part2,对比下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 1upgradetest 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的闪存分区: Part1Part2,解压后放入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,感谢

安装OpenTFTPtftpd64等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群,也没在任何群里面