MiTV 2.10 版本 Magisk ROOT 教程

淮城一只猫 奇技淫巧
阅读量 0 评论量 0

前言

我的电视系统是MiTV 2.10.3982,设备型号:L75MA-AC,Android9,这个 root 教程算是全网首发?至少我在相关论坛没有看到我这种 root 教程,理论上版本号差不多本教程差不多通用的。下面教程不涉及到 Magisk 补丁 root,第三方 recovery 刷入等教程,并且我使用的是 macOS 环境,不提供其他系统详情教学,可以根据文章实际情况来变动。
本教程配合我写的脚本通过 UART/CP2102 → U-Boot/Recovery → 部署 Magisk 启动链实现的持久 root。

1. 准备

下载我的附件,然后新建 xiaomi 文件夹将附件里面内容解压进去,不要根解压。
使用 CP2102 UART 连接电视:这边参考论坛教程:
2022新款小米电视(安卓6以上)硬核root教程(需要USB转TTL)
小米电视硬核root教程(需要USB转TTL硬件工具)

电脑设置终端环境变量:

# 小米电视ip地址
export TV=192.168.50.202:5555
# 工作目录地址
export XIAOMI=/Users/jaxson/Downloads/xiaomi
# 附件地址,放在工作目录地址里面
export ROOT_BUNDLE=$XIAOMI/final-root-bundle
# magisk 安装包
export MAGISK_APK=$ROOT_BUNDLE/apps/Magisk-v27.0.apk

CP2102:921600 baud / 8N1 / 无流控

HDMI 1 CP2102
14 +5V
15 TXD
16 RXD
20 / 屏蔽地 GND

2. 核对设备

打开终端输入:

adb connect "$TV"
adb -s "$TV" shell '
getprop ro.product.model
getprop ro.product.device
getprop ro.build.version.release
getprop ro.build.version.sdk
getenforce
'

必须得到:

MiTV-ASTP0
mulan
9
28
Enforcing

3. 进入 Recovery Root

启动 UART,注意在 window 使用 putty 的话,设置波特921600,新开一个终端A,输入:

mkdir -p "$XIAOMI/logs"
"$ROOT_BUNDLE/tools/uart921600" \
  /dev/cu.usbserial-0001 \
  921600 \
  "$XIAOMI/logs/mulan-root-install.raw.log"

另一个终端 B 重启电视:

adb -s "$TV" reboot

U-Boot 出现时按回车。看到 mulan# 后逐条执行:

factorydata read console_enable
factorydata write console_enable 1
factorydata read console_enable
setenv reboot_mode update
printenv reboot_mode
run switch_bootmode

不要执行 saveenv

Recovery 中确认:

grep -E '^(Uid|Gid|CapEff|Seccomp):' /proc/self/status
cat /sys/fs/selinux/enforce

必须是 UID 0,SELinux 输出 0

4. 完整分区备份

Recovery:

B=/sbin/busybox
$B mount /dev/block/data /data
D=/data/local/tmp/mulan-full-backup
$B mkdir -p "$D"
$B umount /cache
f(){ $B dd if=/dev/block/$1 of=$D/$1.img bs=1M; }

逐条执行:

f bootloader
f reserved
f cache
f env
f logo
f recovery
f misc
f dtbo
f cri_data
f param
f boot
f rsv
f metadata
f vbmeta
f tee
f secure_recovery
f factorydata
f vendor
f odm
f system
f product
$B dd if=/dev/block/mmcblk0boot0 of=$D/mmcblk0boot0.img bs=1M
$B dd if=/dev/block/mmcblk0boot1 of=$D/mmcblk0boot1.img bs=1M
$B dd if=/dev/block/mtdblock0 of=$D/mtdblock0.img bs=1M
$B dd if=/dev/block/mmcblk0 of=$D/emmc-before-data.img bs=1M count=3184
$B chown -R 2000:2000 "$D"
$B chmod 700 "$D"
$B chmod 600 "$D"/*
$B sync
$B reboot

Android 启动后重新开启 ADB,把备份拉到 Mac,并复制一份到其他存储:

mkdir -p "$XIAOMI/backups/mulan-full-backup"
adb connect "$TV"
adb -s "$TV" pull \
  /data/local/tmp/mulan-full-backup/. \
  "$XIAOMI/backups/mulan-full-backup/"

5. 安装 Stage-B

确认远端安装目录不存在,然后推送:

adb -s "$TV" shell 'test ! -e /data/local/tmp/mulan-stage-b-install-20260719'
adb -s "$TV" push \
  "$ROOT_BUNDLE/stage-b" \
  /data/local/tmp/mulan-stage-b-install-20260719

adb -s "$TV" shell '
cd /data/local/tmp/mulan-stage-b-install-20260719
chmod 0700 install-recovery.sh rollback-recovery.sh payload/busybox
'

adb -s "$TV" reboot recovery

Recovery:

B=/sbin/busybox
$B mount /dev/block/data /data
/sbin/sh /data/local/tmp/mulan-stage-b-install-20260719/install-recovery.sh

必须看到:

[mulan-stage-b-install] INSTALL_SUCCESS

成功后:

$B sync
$B reboot

等待 Android 和 ADB 恢复:

adb connect "$TV"
adb -s "$TV" shell '
/sbin/magisk -v
/sbin/magisk su -c "id"
/sbin/magisk su -c "cat /data/adb/magisk/bootstrap.rc"
cat /data/local/tmp/mulan-adb-persist.log
'

必须是 Magisk 27.0、uid=0bootstrap.rc=0,ADB 日志包含 SERVICE_SUCCESS

6. 启用内置 Zygisk

Stage-C Final 安装前,先写入 Magisk 的内置 Zygisk 设置:

adb -s "$TV" shell
/sbin/magisk su
/sbin/magisk --sqlite "INSERT OR REPLACE INTO settings (key,value) VALUES ('zygisk',1);"
/sbin/magisk --sqlite 'SELECT key,value FROM settings WHERE key="zygisk";'
exit
exit

输出必须包含:

key=zygisk|value=1

7. 安装 Stage-C Final

正常 Android:

adb -s "$TV" shell 'test ! -e /data/local/tmp/mulan-stage-c-final'
adb -s "$TV" push \
  "$ROOT_BUNDLE/stage-c-final" \
  /data/local/tmp/mulan-stage-c-final

adb -s "$TV" shell '
cd /data/local/tmp/mulan-stage-c-final
chmod 0700 *.sh payload/busybox
/sbin/magisk su -c "./prepare-android.sh"
'

必须看到:

[mulan-stage-c-final-prepare] PREPARE_SUCCESS

进入 Recovery:

adb -s "$TV" reboot recovery

Recovery:

B=/sbin/busybox
$B mount /dev/block/data /data
/sbin/sh /data/local/tmp/mulan-stage-c-final/install-recovery.sh

必须看到:

[mulan-stage-c-final-install] INSTALL_SUCCESS

出现 FAILED 时不要重启。成功后:

$B sync
$B reboot

8. 最终验证

等待约 90 秒,不要手动重新开启电视设置中的 ADB:

adb connect "$TV"
adb -s "$TV" shell '
getprop sys.boot_completed
getenforce
/sbin/magisk -v
/sbin/magisk su -c "id"
/sbin/magisk su -c "cat /data/adb/magisk/stage-c-early.rc"
/sbin/magisk su -c "cat /data/adb/magisk/stage-c-service.rc"
/sbin/magisk su -c "grep STAGE_C_LATE_SUCCESS /data/adb/magisk/bootstrap.log"
/sbin/magisk su -c "cat /data/adb/magisk/stage-c-zygisk-mode"
cat /data/local/tmp/mulan-adb-persist.log
'

必须满足:

sys.boot_completed=1
SELinux=Enforcing
uid=0
stage-c-early.rc=0
stage-c-service.rc=0
STAGE_C_LATE_SUCCESS
Zygisk mode=builtin
ADB 日志包含 STABILIZATION_SUCCESS 和 SERVICE_SUCCESS

检查 Zygisk:

adb -s "$TV" shell "/sbin/magisk su -c '
P=\$(pidof zygote | awk \"{print \\$1}\")
grep libzygisk.so /proc/\$P/maps
'"

必须看到 /system/lib/libzygisk.so。再正常重启一次并重复本节。

9. Magisk App 和模块

adb -s "$TV" install -r "$MAGISK_APK"

不要点击“修复运行环境”、Direct Install、核心更新或卸载。

模块必须兼容 Android 9、Magisk 27 和 32 位 zygote。安装模块后正常重启。

LSPosed 1.9.2 (7024) - Zygisk 已验证。

10. 给应用授予 Root 权限

目前 magisk app 在小米电视系统无法正常弹窗授权,直到超时提示拒绝授权,这时候可以用下面 UID 授权:

1. 查应用 UID

把包名替换成目标应用:

export TV=192.168.50.202:5555
adb -s "$TV" shell
pm list packages -U | grep 'package:com.example.app '

示例输出:

package:com.example.app uid:10075

记下 UID。不要直接给 uid:1000 等共享系统 UID 授权,否则同一 UID 下的其他系统组件也会获得 Root。

2. 永久允许

先确认 Magisk daemon 正常:

pidof magiskd
/sbin/magisk su -c id

然后进入 Root shell,把 10075 换成实际 UID:

/sbin/magisk su
APP_UID=10075
/sbin/magisk --sqlite "INSERT OR REPLACE INTO policies (uid,policy,until,logging,notification) VALUES ($APP_UID,2,0,1,0);"
/sbin/magisk --sqlite "SELECT uid,policy,until,logging,notification FROM policies WHERE uid=$APP_UID;"
exit
exit

正确结果包含:

uid=10075
policy=2
until=0

含义:

policy=2       允许
until=0        永不过期
logging=1      记录新的 su 请求
notification=0 不显示授权通知

这会覆盖该 UID 原有的拒绝记录,不再依赖电视上无法操作的 Magisk 弹窗。

3. 重新启动应用

adb -s "$TV" shell 'am force-stop com.example.app'

重新打开应用,再执行它的 Root 功能。

Magisk 日志中的旧“拒绝”不会自动消失,应以新的请求时间和 policies 查询结果为准。

4. 查看全部授权

/sbin/magisk su -c '/sbin/magisk --sqlite "SELECT uid,policy,until,logging,notification FROM policies ORDER BY uid;"'

5. 撤销授权

/sbin/magisk su
APP_UID=10075
/sbin/magisk --sqlite "DELETE FROM policies WHERE uid=$APP_UID;"
/sbin/magisk --sqlite "SELECT uid,policy FROM policies WHERE uid=$APP_UID;"
exit
exit

查询无结果表示已撤销。

6. 常见问题

No daemon is currently running!

这不是 App 授权问题,而是 magiskd 没有运行。先正常重启电视,确认以下命令成功后再授权:

pidof magiskd
/sbin/magisk su -c id

已写入 policy=2,应用仍提示没有 Root

依次检查:

  1. 包名对应的 UID 是否正确;
  2. 应用是否在授权后被完全停止并重新打开;
  3. 应用是否使用了其他进程或不同 UID;
  4. pidof magiskd 是否有输出;
  5. /sbin/magisk su -c id 是否仍返回 uid=0

不要通过 Magisk App 的“修复运行环境”或 Direct Install 处理授权弹窗问题。


11. 细节讨论

1. 结论

TvService 和 Magisk 是两条独立的 Root 链路:

  • TvService 是小米厂商诊断服务提供的一次性 Root 脚本执行入口;
  • Magisk 是开机自动建立、支持 su 授权、Zygisk 和模块的持久 Root 框架;
  • 当前 Stage-B → Stage-C Final 方案使用 UART/Recovery Root 安装 Magisk,不依赖 TvService
  • Magisk 正常启动后,日常获取 Root 不需要再次调用 TvService

2. TvService 临时 Root

小米电视里面的服务名 TvService 作为突破口,这个服务名把一个脚本路径交给高权限服务,由 uid=0 的 misysdiagnose SELinux 域执行:

service call TvService 4400 s16 s s16 /sdcard/Download/script.sh

执行链:

ADB shell
uid=2000(shell)
SELinux=u:r:shell:s0
        │
        │ Binder transaction 4400
        ▼
Xiaomi TvService
        │
        │ 将脚本路径交给厂商诊断执行组件
        ▼
misysdiagnose 执行脚本
uid=0(root)
SELinux=u:r:misysdiagnose:s0

提权发生在 Binder 服务端,不是把当前 ADB shell 进程改成 UID 0。脚本结束后,这次 Root 执行也随之结束。

u:r:misysdiagnose:s0 仍受 SELinux Enforcing 限制。UID 0 不代表一定可以 remount 分区、写入 /vendor/odmbootvbmeta

3. Magisk 持久 Root

Magisk 的执行链是:

Android init
  → 执行植入的启动 Hook
  → bootstrap.sh 建立 /sbin Magisk runtime
  → 启动 magiskd
  → magiskd 进入 u:r:magisk:s0
  → shell 或 App 通过 su 请求 Root

日常验证命令:

pidof magiskd
/sbin/magisk su -c id

正常结果应包含:

uid=0(root)
context=u:r:magisk:s0

Magisk App 只是管理界面。真正提供 Root 的是启动 Hook、/sbin/magiskmagiskd、SELinux 策略和 /data/adb/magisk.db

4. 当前方案如何安装 Magisk

当前生产流程是:

UART
  → U-Boot
  → Recovery UID 0 + SELinux Permissive
  → 完整分区备份
  → 安装 Stage-B
  → 启动并验证 Magisk Root
  → 安装 Stage-C Final
  → 启用内置 Zygisk 和模块生命周期

Stage-B 在 Recovery 中完成:

  1. 将 Magisk 27 核心文件部署到 /data/adb/magisk
  2. 修改 /vendor/bin/init.post-fs-data.sh,让系统启动时执行 bootstrap.sh
  3. 修改 /odm/etc/selinux/precompiled_sepolicy,允许启动 Hook 建立 Magisk 域;
  4. 启动时建立 /sbin runtime,执行 magisk --daemon
  5. 为 ADB shell UID 2000 写入 Magisk 允许策略。

Stage-C Final 再补齐:

  • post-fs-dataserviceboot-complete 生命周期;
  • Magisk 27 内置 Zygisk;
  • Magisk 模块和模块 sepolicy.rule
  • 32 位 magisk32stub.apk 和重启后 TCP ADB 5555。

因此,当前持久 Root 的来源是 Recovery 中安装的启动链,不是 TvService

5. 两者的关系

项目 TvService Magisk
入口 Binder transaction 4400 启动 Hook 和 magiskd
Root 上下文 u:r:misysdiagnose:s0 u:r:magisk:s0
ADB shell 是否直接变成 Root 通过 su 获取
重启后是否自动恢复
App 授权 不支持 支持
Zygisk/模块 不支持 支持
当前生产安装是否依赖

理论上可以尝试利用 TvService 临时 Root 部署持久化文件,但其 SELinux 域未验证具备完整的分区挂载和启动链写入权限,因此不能替代已经验证的 Recovery 安装流程。

6. Magisk 丢失时 TvService 能做什么

如果 magiskd 没有运行,TvService 仍可能独立提供临时 Root,因为它不依赖 Magisk。它适合读取以下诊断信息:

/data/adb/magisk/bootstrap.log
/data/adb/magisk/bootstrap.rc
/data/adb/magisk/stage-c-early.log
/data/adb/magisk/stage-c-early.rc
/data/adb/magisk/stage-c-service.log
/data/adb/magisk/stage-c-service.rc

不要直接用 TvService 执行 bootstrap.sh:脚本要求 u:r:run_post_fs_data:s0,而 TvService 脚本运行在 u:r:misysdiagnose:s0,上下文不匹配。

涉及 /init.rc/vendor/odm 或 SELinux 策略的恢复,应使用 Recovery 中保存的回滚脚本。

7. 不要混淆

安装 Magisk APK ≠ 获得 Root
TvService UID 0 ≠ Magisk su
TvService 临时 Root ≠ adb root
UID 0 ≠ 绕过 SELinux
Magisk Root 丢失 ≠ TvService 一定失效

本方案不是 Magisk 官方 boot.img patch 流程。不要在 Magisk App 中执行“修复运行环境”、Direct Install、核心更新或卸载,否则可能破坏当前自定义启动链。

喵~