2026/7/25
一、背景与目标
手里有一台 ZTE B860AV1.1-T2 机顶盒,芯片是中兴微 ZX296716(四核 Cortex-A53),1GB 内存、8GB eMMC,原厂系统是 Android 4.4.2。
目标是把这台盒子改造成一台低功耗 Linux 服务器,跑一些轻量服务。需要解决的问题:
-
WiFi 能连上
-
SSH 能远程登录
-
把 Android 框架干掉,释放内存
-
修改 DTB 把被 GPU/解码器占用的 CMA 内存收回来
-
开机自动启动 WiFi + SSH
二、硬件摸底
分区表
text
mmcblk0p1 bootloader 4MB u-boot
mmcblk0p2 (unknown) 64MB
mmcblk0p3 conf 4MB 配置分区
mmcblk0p4 cache 768MB
mmcblk0p5 env 8MB u-boot 环境变量
mmcblk0p6 logo 32MB
mmcblk0p7 (unknown) 32MB
mmcblk0p8 misc 8MB 启动模式标志
mmcblk0p9 (unknown) 8MB
mmcblk0p10 boot 32MB 内核+ramdisk+DTB
mmcblk0p11 (unknown) 32MB
mmcblk0p12 (unknown) 32MB
mmcblk0p13 system 1GB Android 系统
mmcblk0p14 data 5.2GB 用户数据
关键分区:boot(内核+ramdisk+DTB)、system(系统文件)、data(用户数据)。
内存状态
text
MemTotal: 1014156 kB (990 MB)
CmaTotal: 282624 kB (276 MB) ← GPU/视频解码器预留
CmaFree: 265780 kB (259 MB) ← 259MB 空闲但被锁死
系统总内存约 990MB,其中 276MB 被 CMA 预留给多媒体,但实际只用了 17MB,剩下的 259MB 完全浪费。这是改造的关键切入点。
三、WiFi 调试
硬件与驱动
WiFi 芯片是 Realtek 8189FS(SDIO 接口),驱动模块是 /system/lib/modules/8189fs.ko。
bash
insmod /system/lib/modules/8189fs.ko
加载后出现 wlan0 和 wlan1 两个接口,MAC 地址只差一位。
踩坑:ifconfig wlan0 up 显示 "link is not ready"
这不是错误。WiFi 的 "link is not ready" 表示还没连上 AP,和以太网没插网线一样。需要先配置 wpa_supplicant 连接。
连接 WiFi
bash
# 扫描
iwlist wlan0 scan | grep ESSID
# 配置 wpa_supplicant
cat > /data/wpa.conf << EOF
network={
ssid="WiFi名"
psk="密码"
}
EOF
# 连接
wpa_supplicant -B -i wlan0 -c /data/wpa.conf
dhcpcd wlan0
踩坑:dhcpcd 锁文件冲突
报错 flock /data/misc/dhcp/dhcpcd-wlan0.pid: Try again。解决:
bash
rm -f /data/misc/dhcp/dhcpcd-wlan0.pid
killall dhcpcd
dhcpcd wlan0
四、SSH 配置
系统自带 Dropbear v0.52(2012 年版本),路径 /system/xbin/dropbear。
bash
mkdir -p /data/ssh
dropbearkey -t rsa -f /data/ssh/dropbear_rsa_host_key
dropbear -p 22
踩坑:新版 OpenSSH 连不上旧版 Dropbear
Dropbear v0.52 只支持旧版密钥交换算法 diffie-hellman-group1-sha1,新版 OpenSSH 默认禁用。
客户端连接需要加参数:
bash
ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 \
-oHostKeyAlgorithms=+ssh-rsa root@192.168.31.208
或写入 ~/.ssh/config:
text
Host 192.168.31.208
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms +ssh-rsa
五、内存优化(运行时方案)
问题:直接 kill -9 没用
Android init 会自动重启被杀的服务。必须用 stop 命令告诉 init 不再拉起。
bash
stop zygote
stop surfaceflinger
stop servicemanager
stop mediaserver
stop drm
stop installd
stop keystore
stop bootanim
stop netd
然后再杀残留进程:
bash
killall -9 com.zte. com.ztestb. com.stbmc. com.mcsp. com.dangbei. com.android.
killall -9 MainCenter hgAgent zte_probe zteKlog netaccess wirelesskey
效果对比
| 项目 | 优化前 | 优化后 |
|---|---|---|
| 内存占用 | 733 MB | 300 MB |
| 空闲内存 | 280 MB | 714 MB |
| 用户进程数 | 60+ | 15 |
释放了约 430MB 内存,系统只剩内核 + 基础 Linux 服务。
六、永久性改造:修改 DTB 回收 CMA
运行时 kill 方案每次重启都要执行,不够彻底。永久方案是修改 DTB 中的 CMA 预留大小。
Boot.img 结构
ZTE 的 boot.img 是自定义头 + Android 标准格式:
text
0x0000-0x005F ZTE 头 (magic: 55667788)
0x0060-0x085F Android 头 (magic: ANDROID!)
0x0860-0xB0BFEF 内核 (11.3MB)
0xB0BFF0-0xC4399F Ramdisk (1.2MB)
0xC439A0-0xC5399F DTB × 3
踩坑:改 DTB 导致 u-boot 卡死
第一次尝试改了 ramdisk,导致 DTB 偏移改变,u-boot 找不到 DTB 卡死。
原因: u-boot 用固定偏移读取 DTB,ramdisk 大小变了,DTB 位置就变了。
教训: boot.img 的任何改动必须保持文件大小不变,否则 DTB 偏移会错位。
踩坑:DTB 没有 CRC32
DTB offset 4-7 是 totalsize(总大小),不是 CRC32。第一次误认为是 CRC,写错了值导致 DTB 损坏。
正确格式:
text
0x00-0x03: magic (0xd00dfeed)
0x04-0x07: totalsize
0x08-0x0B: off_struct
0x0C-0x0F: off_strings
踩坑:CMA=0 导致内核 panic
把 multimedia_region size 设为 0 后启动 panic:
text
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
某些驱动初始化需要 CMA 内存,分配失败导致 init 段错误。CMA 不能设为 0,最小可用值约 16MB。
最终修改
DTB 中 reserved-memory 节点的 CMA 大小:
dts
reserved-memory {
multimedia_region {
compatible = "shared-dma-pool";
reusable;
size = <0x11000000>; // 272 MB → 改为 16 MB
};
};
修改后 CmaTotal 从 336MB 降到 36MB,多释放了约 256MB 内存。
刷入方法
bash
# 改好的 boot.img 放 /data/local/
dd if=/data/local/boot_patched.img of=/dev/block/mmcblk0p10 bs=4096
sync
reboot
七、Init.rc 改造(未完成)
计划方案:
-
注释
class_start main--- 阻止 zygote/surfaceflinger 启动 -
注释 Android 服务定义 --- servicemanager、zygote、drm、media、bootanim、installd、keystore
-
添加 Linux 服务:
text
service linux_init /system/bin/sh /system/bin/linux_init.sh
class core
oneshot
linux_init.sh放在 system 分区,负责加载 WiFi、启动 SSH
未完成原因: 改 ramdisk 需要重建 boot.img,涉及 ramdisk 大小变化带来的 DTB 偏移问题。最终采用 DTB-only 方案(只改 CMA),配合 install-recovery.sh 钩子实现开机自启。
八、TFTP 刷机尝试
尝试通过 u-boot 的 tftpboot 命令刷 boot.img,持续超时:
text
Loading: T #T #T ##T ##########T
Retry count exceeded; starting again
TFTP 协议在 u-boot 下不稳定,未解决。最终改用 recovery + dd 方案:
-
safe命令进入 recovery -
dd从/data/local/写入 boot 分区
九、开机自启
使用 /system/etc/install-recovery.sh 钩子(系统自带,开机自动执行):
bash
#!/system/bin/sh
sleep 10
insmod /system/lib/modules/8189fs.ko
ifconfig wlan0 up
wpa_supplicant -B -i wlan0 -c /data/wpa.conf
dhcpcd wlan0
dropbear -p 22
十、踩坑总结
| 问题 | 原因 | 解决方案 |
|---|---|---|
| WiFi "link is not ready" | 还没连 AP,正常现象 | 配置 wpa_supplicant 连接 |
| dhcpcd 锁文件冲突 | 残留 pid 文件 | rm -f 后重启 dhcpcd |
| OpenSSH 连不上 Dropbear | 旧版算法被新版禁用 | 加 -o 参数启用旧算法 |
| kill -9 杀不死 Android 服务 | init 自动重启 | 用 stop 命令 |
| 改 ramdisk 后 u-boot 卡死 | DTB 偏移变了 | 保持文件大小不变 |
| CMA=0 后内核 panic | 驱动需要 CMA 内存 | 最小 16MB |
u-boot tftpboot 超时 |
协议或驱动问题 | 改用 recovery + dd |
十一、最终状态
| 项目 | 结果 |
|---|---|
| WiFi | ✅ 开机自动连接 |
| SSH | ✅ 端口 22,可用密钥登录 |
| 空闲内存 | 从 280MB 提升到 714MB |
| CMA 回收 | 从 276MB 降到 36MB,释放 240MB |
| 开机自启 | ✅ install-recovery.sh 钩子 |
| 持久化改造 | ✅ DTB 修改永久生效 |
十二、关键经验
-
boot.img 改动必须保持文件大小一致,否则 DTB 偏移错位,u-boot 卡死
-
CMA 不能设为 0,驱动初始化需要最低内存
-
Android init 会自动重启服务 ,必须用
stop而非kill -
u-boot 的 bootsys 不展开环境变量 ,
${othbootargs}是死字符串 -
TFTP 在 u-boot 下可能不稳定,recovery + dd 更可靠