本文转自:My Blog https://akbwe.com/posts/an-attempt-to-replace-zte-f7607p-nand-mtdblocks/
前言
中兴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。
备份原机闪存
折腾任何机器的第一步永远是备份,对于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插件分区:CMCC_V2.0.6P1N2
联通版闪存结构分析
看一下联通版固件的分区结构
/ # 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等校验,则会从另一个kerel分区启动。rootfs分区是kernel分区内的一部分。framework和framework1是插件分区,也完全相同,互为备份。移动版固件要改为联通版,只用核心功能的话,只需要替换mtd7和mtd8就行,要完整替换的话还需要替换mtd6和mtd9、mtd10、mtd11。mtd12由于被包含在mtd7或mtd8之内,所以不需要再单独额外替换。
开始替换
准备好用于替换的几个联通版分区备份文件:UNICOM_V2.0.5P1N4,对比下hash值以防分区数据出错,kernel分区差一个字节也无法启动
preplugin.bin sha-256: 2f319e34a733ec0b4459851fe106ddd5ed352f38f163a23392a2c7494a4355d7 kernel.bin sha-256: 37bc69e02f87b87c963675b5f8a61c9ed9cd5dd16b5116fedcafcf8b6acd18e9 framework.bin sha-256: 8097258c6c38662cb93e71280cab8569d7064fac1b919419ce269dcc8b7c3363 plugin_data.bin sha-256: 9c26c23cb4533fa4b109ea8da9f872d5e92bb5c7340b8d3f435b3d683bb15b01
放入NTFS或FAT32格式的优盘,插入猫眼,进入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 kwrite /dev/mtd11 0x0 0x7900000 ./plugin_data.bin
nand kerase /dev/mtd6 0x0 0x600000
nand kwrite /dev/mtd6 0x0 0x600000 ./preplugin.bin
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的闪存分区: TELECOM_V2.0.0P1N6,解压后放入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格式的优盘,插入猫眼,进入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
的话,使用如下命令设置
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。电信版固件在网页后台可以自由切换XGPON和XEPON模式
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 |.....H..@.T.~..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