引言

家里的宽带最近升级了200M上行, 装维说200M上行必须得用XGPON光猫, 买了一个二手xgpon猫, 注册的时候卡在了29%, 过程是O3, 证明我的线路支持XGPON, 但是可能被ONU拦下了.

参考itu的说明: ITU-T G.987.3 明确规定: ONU取得下行同步以后才进入 O2-3 Serial Number 状态; 在这个状态, ONU响应 OLT 的 Serial Number grant, 把自己的 SN 发给 OLT. 只有 OLT 随后发送一个与这个 SN 匹配的 Assign_ONU-ID, ONU才会进入 O4.

image-20260926220853167

于是想着是不是ONU侧认光猫的SN, 就TELNET上去修改了一下新光猫的SN为老光猫SN, 结果输入的时候忘了输入Vender ID, 本来12位的SN只输入了8位, reboot之后power灯一直闪烁, 插到电脑甚至显示网络线缆未连接.

于是乎就有了这篇救砖博客.

获取超级密码和开启Telnet

博通方案的天邑TEWA-1108V在未成功注册前的超级密码为nE7jA%5m.

账号一般是useradmin.

使用超密登录后, 进入http://192.168.1.1:8080/enableTelnet.html

根据恩山帖子 https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=8402465 开启入口也可能是http://192.168.1.1/enableTelnet.html

即可进入开启界面

image-20260926221713208

开启TELNET后, 连接TELNET

telnet可以不用su密码卡BUG获得root权限, 先按照常规方式登录Telnet, 打一个;回车, 这时会报错: sh: syntax error: unexpected “;”, 再输入命令echo $USER, 就是root权限

或者可以通过光猫的MAC地址计算出来, 计算器网址

Telnet可用命令如下, 来源恩山

常用网页入口

地址用途
http://192.168.2.1:8080/enableTelnet.html开启 Telnet
http://192.168.2.1:8080/backupsettings.conf下载配置
http://192.168.2.1:8080/updatesettings.html上传配置
http://192.168.1.1:8080/NN_WAN1.html删除 TR069

NVRAM / 地区相关

命令用途
ls /etc/default_configs查询地区配置
cat /proc/nvram/LocationCode查看当前地区
cat /proc/nvram/BaseMacAddr查询 MAC
echo XX:XX:XX:XX:XX:XX > /proc/nvram/BaseMacAddr修改 MAC
echo 0x0B00 > /proc/nvram/LocationCode切换地区,以北京为例

地区代码

地区代码地区代码地区代码地区代码
北京0x0B00内蒙古0x0F00黑龙江0x1700福建0x2300
天津0x0C00辽宁0x1500安徽0x2200江西0x2400
河北0x0D00吉林0x1600浙江0x2100重庆0x32005
山西0x0E00上海0x1F00江苏0x2000四川0x3300
山东0x2500河南0x2900湖北0x2A00湖南0x2B00
广东0x2C00广西0x2D00海南0x2E00贵州0x3400
云南0x3500陕西0x3D00甘肃0x3E00青海0x3F00
西藏0x3600宁夏0x4000新疆0x4100

qoecmd / MDM 常用命令

命令用途
sh进入 Shell
qoecmd help查看命令
qoecmd mdm -h查看 MDM 命令用法
qoecmd dumpmdm查看配置信息
qoecmd dumpcfg查看可配置信息
qoecmd gponSN get查看 GPON SN
qoecmd gponSN set XXXXXXXXXXXX修改 GPON SN
qoecmd telecomadmin get获取超级管理员密码
qoecmd restoredefault恢复出厂设置
qoecmd Register set status 0 result 1ITMS 注册
qoecmd bobdata dump查看光模块型号
ct_getITMSRegistStat查看 ITMS 注册状态
cqct_itms查看 LOID
mdm dumpobj 2查看配置
mdm setpv修改配置
mdm getpv InternetGatewayDevice.DeviceInfo.X_CT-COM_MACAddress查看 MAC
mdm getpv InternetGatewayDevice.DeviceInfo.Manufacturer查看制造商
mdm getpv InternetGatewayDevice.DeviceInfo.SerialNumber查看设备标识后十七位
mdm getpv InternetGatewayDevice.DeviceInfo.ManufacturerOUI查看设备标识前六位
mdm getpv InternetGatewayDevice.DeviceInfo.ProductClass查看设备型号
mdm getpv InternetGatewayDevice.DeviceInfo.X_CT-COM_CheckKey查看 X_CT-COM_CheckKey
mdm getpv InternetGatewayDevice.DeviceInfo.X_CT-COM_ServiceManage查看 X_CT-COM_ServiceManage

变砖过程

在光猫正常运行时, 通过 Telnet 查询 GPON SN:

qoecmd gponSN get

返回值是 12 个文本字符, 形式类似:

gponsn:SCTY12345678

随后把它改成了只有 8 个十六进制字符的值, 并重启:

qoecmd gponSN set A1B2C3D4 # 不要执行!!!!!

重启后的表现是:

  • POWER 灯持续闪烁.
  • 电脑直连时获取不到 DHCP 地址.
  • Web 管理页面无法访问.
  • 手动指定地址后也无法 ping 通.

reset之后依旧如此, 光猫的reset只能重置用户配置, 不会将所有设置重置.

后来的串口日志表明, 设备能够启动 U-Boot 和 Linux, 但在 PON 初始化期间出现 SN 校验错误, 随后 kernel panic, 等待 5 秒后再次启动.

修复过程

本来以为80块钱打水漂变成电子垃圾了, 结果在冲浪时发现光猫可以通过ttl拯救, 但我手头没有usb-ttl设备, 但有一个Arduino Uno(Uno 兼容板, ATmega328P / 16 MHz, CH340 USB 串口). 接下来的操作都是通过Uno和光猫的ttl口连接操作的. 其中执行命令连接SIN的时候需要用1个2k欧姆的电阻和一个1k欧姆电阻分压实现3.3V输入.

光猫拆解

光猫背面有两颗螺丝, 其中一颗

image-20260926223210580

另一颗需要撕开标签

image-20260926223246811

都拧下之后, 就可以硬撬外壳了, 外壳的卡扣很紧, 很难做到无损拆除请注意.

拆机后如下

image-20260926223424466

其中右下角有四个触点, 名字分别是

SIN SOUT GND 3.3V

其中SIN是写入, SOUT是对外输出, GND是接地.

连接光猫TTL

我使用Arduino与其共地, 然后D2号口接受SOUT的信息转发给PC. 关键错误日志如下

[ERROR ploamFsm] parseSNPW ,138:
Invalid SN Number (1) ([A-Z]4[0-9a-fA-F]8). Given: BRCM12345678

[ERROR ploamFsm] bcm_ploamCreate,443: parseSNPW failed.

Kernel panic - not syncing: Fatal exception
Rebooting in 5 seconds..

这里有一个容易误解的地方, BRCM12345678并不是我实际写入的那个SN, 应该只是个例子.

不过还能启动证明系统本身没坏, 只要想办法把SN改回来就能拯救.

修复过程

根据博通官方的文档可以得知这款光猫的启动流程为

Boot ROM → SPL → TPL → U-Boot proper → Linux → PON 初始化

在出现以下标记时也就是SPL阶段立即发送小写 a, 无需回车:

$SPL: 5.04L.02@348603 $

实际返回:

Use enter to confirm input menu selection
go - continue
ddr - mcb override(hex) or DDR safe mode.
r - Boot Fallback; 1 - recovery
bid - Ignore boardid while booting
mcb - List all the mcb selectors
wdt - Disable spl wdt
h - halt

发送 h 加回车后返回 Halted, 可以暂时停住启动. 后续菜单命令需要回车.

这里参考了 Broadcom 的 early_abort.c.

Broadcom 参考 early_abort.c

SPL 的 Recovery 和 Fallback 没解决问题

实际测试结果:

操作设备响应后续结果
r 1, 随后 goBoot Image: Recovery仍加载 Image 2, 发生相同 SN 错误和 panic
r, 随后 goBoot Image: Fallback选择 Image 1, 但 FIT 头认证失败

备用镜像的报错:

SELECTED Image 1 FIT_VOL_ID is 3
padding_pss_verify: invalid pss padding (0xbc is missing)
FAILED to authenticate FIT header!!!
resetting board...

此后热重启仍选择 Image 1; 断电约 5 秒再上电后, 重新回到可加载的正常镜像. 没有查明备用镜像认证失败的根因, 也没修改它.

小写 ty: 进入 U-Boot 命令行

以为没救了, 但翻输出日志看到这么一行

Enter specific characters to stop autoboot in  1s

尝试发送Ctrl+C, 26个字母10个数字都无效 .

Codex帮我在恩山的一篇帖子中的日志找到了 Enter 'ty' to stop autoboot, 因此试了试 ty , 成功看到 => 提示符. 天邑 TEWA-7100A 启动日志

具体就是按下ty, 不需要回车.

看到 => 后, 执行 help、printenv 均可正常返回.

临时启动 Linux 应急 shell

进入 U-Boot 后, 先查询:

=> printenv bootcmd bootargs bootargs_append
bootcmd=run once;sdk boot_img
## Error: "bootargs" not defined
## Error: "bootargs_append" not defined

参考代码支持通过 bootargs_append 追加 Linux 启动参数. Broadcom 参考启动参数处理

本机正常可加载的是 Image 2, 因此执行:

setenv bootargs_append init=/bin/sh
printenv bootargs_append
sdk boot_img 2

这里不执行 saveenv. 参数只用于这一次启动, 重启后消失.

Linux 返回:

VFS: Mounted root (squashfs filesystem) readonly on device 254:0.
Run /bin/sh as init process
#

这时已进入 root shell, 通常的初始化服务没有运行, 因此尚未触发 PON 崩溃路径.

处理看门狗

第一次应急 shell 在约 80 秒后被看门狗重启. 重新进入后, 挂载必要的虚拟文件系统和内存目录, 再启动原厂喂狗程序:

mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t tmpfs tmpfs /var
mkdir -p /var/run /var/tmp
/bin/sh /etc/init.d/wdtd.sh start

这一顺序为守护进程提供可写的运行目录.

实际排查时, 在创建 /var/run 前启动 wdtd, 报了 PID 文件错误, 但进程仍持有 /dev/watchdog; 再次启动便提示 EBUSY.

不能看到 PID 文件错误就认为喂狗进程已经退出, 要检查实际进程.

查询真正保存的 SN

cat /proc/environment/gponsn

输出为误写的 8 位值. 本例该节点权限是只读:

-r-------- ... /proc/environment/gponsn

直接运行 qoecmd gponSN get 返回:

could not initialize msg, ret=9002

因为应急 shell 没有qoecmd所依赖的服务.

最终没通过 qoecmd 执行修复, 而是用 U-Boot 修改保存 SN 的环境变量.

修改前, 备份两个环境所在的 Flash 块

其实这里不备份也没啥, 但是想着阴性结果也是结果, 就备份了一下.

U-Boot 查询环境位置:

=> printenv env_boot_magic
env_boot_magic=16384@0x40000,0xaf000

本机存在两个环境副本. Linux 的 /proc/mtd 显示:

dev:    size     erasesize  name
mtd0: 10000000 00020000 "brcmnand.0"
mtd1: 00200000 00020000 "loader"
mtd2: 0fd00000 00020000 "image"

环境副本分别落在以下 128 KiB 擦除块中:

环境地址所在块起点对 /dev/mtd1 的读取参数
0x400000x40000bs=131072 skip=2 count=1
0xaf0000xa0000bs=131072 skip=5 count=1

loader 分区从物理偏移 0 开始, 所以这里的分区内偏移与物理偏移相同. 其他分区布局不能直接套用.

只读 Flash, 写入内存中的 /var/tmp:

dd if=/dev/mtd1 of=/var/tmp/env-block-before.bin bs=131072 skip=2 count=1
sha256sum /var/tmp/env-block-before.bin

dd if=/dev/mtd1 of=/var/tmp/env-block2-before.bin bs=131072 skip=5 count=1
sha256sum /var/tmp/env-block2-before.bin

经串口把备份传回电脑

由于软件串口连续输出时会丢字节, 使用 OpenSSL Base64 编码, 并在每行之后短暂停顿:

echo ENV_BACKUP_BEGIN
openssl base64 -in /var/tmp/env-block-before.bin | while IFS= read -r L; do echo "$L"; usleep 5000; done
echo ENV_BACKUP_END

第二份使用不同标记:

echo ENV_SECOND_BEGIN
openssl base64 -in /var/tmp/env-block2-before.bin | while IFS= read -r L; do echo "$L"; usleep 5000; done
echo ENV_SECOND_END

电脑端把 RX 原始字节保存成 .bin, 截取开始、结束标记之间的 Base64, 再解码为 131072 字节的二进制文件. 两份文件的 SHA-256 都与光猫端计算值一致, 另外检查了环境内部 CRC.

这台精简系统里没有可用的 printf 命令, sleep 0.05 也不接受小数, 最后使用 echo 和 BusyBox 的 usleep.

备份的是故障时的环境块, 其中仍包含误写的 SN; 作用是保留修改前现场.

在 U-Boot 中恢复原始 SN

备份完成后, 从应急 shell 执行 reboot -f, 重新在 U-Boot 倒计时处输入 ty.

先核对三项:

printenv gponsn env_boot_magic bootargs_append

本次确认:

  • gponsn 仍是误写值.
  • 环境副本位置与备份时一致.
  • 临时的 bootargs_append 已经不存在.

然后恢复自己设备记录过的原始 SN:

# 以下 SN 是例子, 执行前必须换成自己设备的原值. 
setenv gponsn SCTY12345678
printenv gponsn

读回正确后, 保存:

=> saveenv
Saving Environment to BOOT_MAGIC... save to 40000
save to af000
OK

这里的 saveenv 会真正写入 Flash. 它保存当前环境, 因此在执行前确认临时启动参数没有混入非常重要. 参考实现会读入对应擦除块, 更新环境区域, 再写回整块; 前面的备份覆盖了两个实际涉及的块. Broadcom 参考 BOOT_MAGIC 保存实现

执行 reset, 再次输入 ty, 再读一次:

=> printenv gponsn bootargs_append
gponsn=SCTY12345678
## Error: "bootargs_append" not defined

这次读值发生在重新启动、重新加载环境之后, 因此验证了保存结果, 不只是修改后的 RAM 值.

最后执行:

boot

恢复正常启动流程.

修复结果与验证边界

正常启动后, 看串口日志

[NTC ploamFsm] bcm_ploamCreate: ploam driver created.
:::::Broadcom OMCI Stack v4.2 ...

并且POWER灯常亮, 光纤灯闪红(因为没插光纤).

吐槽

谁家好人写光猫系统保存sn不校验, bootloader校验SN不通过导致kernel panic啊??

参考资料

  1. Broadcom源码
  2. https://www.right.com.cn/forum/thread-8412122-1-1.html
  3. https://www.right.com.cn/forum/thread-8426017-1-1.html
  4. https://www.right.com.cn/forum/thread-8455169-1-1.html
  5. https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=8402465
  6. https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=8470716
  7. https://www.right.com.cn/forum/thread-8428331-1-1.html