r2 评审 p2-6items 六条全部处理;**产物字节未变**(5 件 md5 与31d4c22完全一致)。 P2-1/P2-4 归因纠正(31d4c22 提交说明里那两行是错的,以本条为准): - bootmenu 的 +1728 **不是**工具链代差,是 M23 源码(m2.29→m2.30)。证据:旧件 `readelf -p .comment` 已是 clang 22.1.8(与新件同代);旧件版本串 `0.1.0-m2.29-takeover`, 而钉值 commit884d4c4的源码已是 m2.30;用 6364498(m2.29 树)+ 今天的工具链重编得 157108/0507739d,与旧钉值件逐字节相同。 - launcherd 的 −512 也不是编译器:新旧 .comment 集合一致(那道 21.1.8 来自 meow_ui.a 里的 meow_font.o),真实原因是 SDK 静态库从 86800633 换成 cc0ed49b——用58cdb73源码 + 86800633 的 .a 重编得 894940/cea0a735,与旧钉值件逐字节相同。 - 因此**只有 meow_audiod 真有工具链代差**(旧 clang/LLD 21.1.8 → 新 22.1.8)。 P2-2 主 checkout 定位:`git rev-parse --git-common-dir` 给的是主仓库 .git 的**绝对**路径, 父目录才是主 checkout;旧版把绝对路径当相对路径拼到 $ROOT 下,`cd` 失败被 `set -e` 直接终止 → 干净 worktree 里静默 exit 1。现为 `cd "$_gcd/.."` + 全部 `|| true`, 找不到 meow_ui.a 时**先**打印诊断(缺什么、试过哪些路径、怎么覆盖)再退出。 P2-3 .tools 兜底层级:旧版把 $COMPAT_HOME/Project/R3ProII 指向 ROOT,脚本里的 `$HOME/Project/R3ProII/.tools` 就落到 `<checkout>/.tools`(干净 worktree 不存在 → 127)。 现在造一个真目录,只放 `.tools -> ~/.tools` 与 `patch_v2 -> $ROOT/patch_v2`; 零手工准备即可开箱重编。README 措辞同步改准。 P2-5 门禁假绿:test_time32_abi.sh 的退出码现计入 FAIL,脚本缺失也记 FAIL。 失败桩自证:`PASS=33 FAIL=1`、exit 1(原为 PASS=33 FAIL=0 / exit 0)。 P2-6 desc:meow_audio 的 `volume` → 真实子命令 `status / tone / route / vol / output / monitor` (并避开 `|`,否则破坏清单 4 字段格式);bootmenu 的读取键改为 display.brightness (display.brightness_min 只是下限 clamp);netmgrd 去掉「以太网连接」的夸大说法。
127 lines
5.9 KiB
Bash
Executable File
127 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
||
# verify_fingerprints.sh — 语义指纹自证(M51 批次产物)。
|
||
#
|
||
# 背景:仓内钉值的 md5 来自不同时期的工具链/源码,重编后**必然全变**,md5 不再是
|
||
# 「产物含哪些源码改动」的证据。能证明产物语义的只有两样东西:二进制里的字符串/动态段
|
||
# (功能存在),以及反汇编里的 time32 系统调用形态(4263 + 16 字节布局写回,见
|
||
# patch_v2/sdk/test_time32_abi.sh)。本脚本把这些判据固化下来,重编后跑一遍即可。
|
||
#
|
||
# 用法:
|
||
# bash scripts/build/verify_fingerprints.sh # 全量判据
|
||
# bash scripts/build/verify_fingerprints.sh --self-test # 自检:判据必须能 FAIL 也要能 PASS
|
||
# 退出码:全部命中 0;任一条不命中 1。
|
||
#
|
||
# 注意:中文串用 `grep -a -o -F` 直接数二进制里的字节序列,**不能**用 strings ——
|
||
# strings 只输出可打印 ASCII 串,UTF-8 中文(每字节 ≥0x80)整段被跳过,会假阴。
|
||
set -u
|
||
|
||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||
BM="$ROOT/patch_v2/bootmenu/meow_bootmenu"
|
||
NM="$ROOT/patch_v2/meow_netmgrd/meow_netmgrd"
|
||
AD="$ROOT/patch_v2/meow_audiod/meow_audiod"
|
||
AU="$ROOT/patch_v2/meow_audiod/meow_audio"
|
||
LC="$ROOT/patch_v2/meow_launcherd/meow_launcherd"
|
||
|
||
PASS=0; FAIL=0
|
||
ok() { PASS=$((PASS+1)); printf ' PASS %s\n' "$1"; return 0; }
|
||
bad() { FAIL=$((FAIL+1)); printf ' FAIL %s\n' "$1"; return 1; }
|
||
|
||
# cnt <file> <literal>:二进制里该字面量的出现次数(按字节,含 UTF-8)
|
||
cnt() { grep -a -o -F -- "$2" "$1" 2>/dev/null | wc -l; }
|
||
|
||
# eq <name> <file> <literal> <期望次数>
|
||
eq() {
|
||
local got; got=$(cnt "$2" "$3")
|
||
if [ "$got" -eq "$4" ]; then ok "$1: '$3' = $got"; else bad "$1: '$3' = $got(期望 $4)"; fi
|
||
}
|
||
# ge <name> <file> <literal> <最少次数>
|
||
ge() {
|
||
local got; got=$(cnt "$2" "$3")
|
||
if [ "$got" -ge "$4" ]; then ok "$1: '$3' = $got (>= $4)"; else bad "$1: '$3' = $got(期望 >= $4)"; fi
|
||
}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 自检:判据必须是「有内容」的 —— 对不存在的串要 FAIL,对存在的中文串要 PASS,
|
||
# 对改一个字的中文串要 FAIL。任何一条不成立说明判据本身坏了(例如退回用 strings)。
|
||
# ---------------------------------------------------------------------------
|
||
self_test() {
|
||
local rc=0 n
|
||
echo "==> 自检:判据可 FAIL(不存在的 ASCII 串)"
|
||
if ( eq SELFTEST "$LC" '__m51_no_such_string__' 1 >/dev/null 2>&1 ); then
|
||
echo " FAIL 不存在的串竟判 PASS —— 判据恒真"; rc=1
|
||
else
|
||
echo " PASS 不存在的串判 FAIL(判据不是恒真)"
|
||
fi
|
||
echo "==> 自检:判据可 PASS(存在的中文串,证明 -a -F 对 UTF-8 有效)"
|
||
n=$(cnt "$LC" '蓝牙状态未知')
|
||
if [ "$n" -ge 1 ]; then echo " PASS '蓝牙状态未知' 命中 $n 次"; else echo " FAIL 存在的中文串反而 0 命中"; rc=1; fi
|
||
echo "==> 自检:中文串改一个字必须 0 命中(不是子串误匹配)"
|
||
if ( eq SELFTEST "$LC" '蓝牙状态未如' 1 >/dev/null 2>&1 ); then
|
||
echo " FAIL 改字后竟判 PASS"; rc=1
|
||
else
|
||
echo " PASS 改字后判 FAIL"
|
||
fi
|
||
return $rc
|
||
}
|
||
|
||
if [ "${1:-}" = "--self-test" ]; then
|
||
self_test || { echo "!! 自检失败"; exit 1; }
|
||
echo "==> 自检全部通过"; exit 0
|
||
fi
|
||
|
||
echo "==> meow_bootmenu(亮度单一权威源 + time32)"
|
||
eq bootmenu "$BM" 'display.brightness_min' 1
|
||
eq bootmenu "$BM" '0.1.0-m2.30-bri-src' 1
|
||
|
||
echo "==> meow_netmgrd(蓝牙控制面 / WiFi 连接修复 + time32)"
|
||
ge netmgrd "$NM" 'paired-devices' 1
|
||
ge netmgrd "$NM" 'hcitool con' 1
|
||
ge netmgrd "$NM" 'list-pcms' 1
|
||
ge netmgrd "$NM" 'A2DP none' 1
|
||
ge netmgrd "$NM" 'bt scan on' 1
|
||
eq netmgrd "$NM" 'connected=%d' 4
|
||
eq netmgrd "$NM" 'bt cmd:' 0 # 旧「一条命令行」形态已删
|
||
eq netmgrd "$NM" 'a2dp list' 0 # 旧的整段 dump 形态已删
|
||
|
||
echo "==> meow_audiod(蓝牙 A2DP 输出端到端;glibc-dynamic 链 libasound)"
|
||
ge audiod "$AD" 'audio.output_bt' 1
|
||
ge audiod "$AD" 'bluealsa:DEV=%s,PROFILE=a2dp,CODEC=%s' 1
|
||
ge audiod "$AD" 'btdev=' 1
|
||
ge audiod "$AD" 'btcodec=' 1
|
||
ge audiod "$AD" 'btacodec=' 1
|
||
eq audiod "$AD" 'pcm.bluealsa' 0 # 打开名改走 bluealsa:DEV=... 内联参数
|
||
eq audiod "$AD" '/usr/data/alsa.conf' 0 # 不再读写 HiBy 播放器的非法 alsa.conf
|
||
if readelf -d "$AD" 2>/dev/null | grep -q 'libasound.so.2'; then ok "audiod: readelf -d NEEDED libasound.so.2"
|
||
else bad "audiod: readelf -d 缺 libasound.so.2"; fi
|
||
if readelf -l "$AD" 2>/dev/null | grep -q 'interpreter: /lib/ld.so.1'; then ok "audiod: interpreter = /lib/ld.so.1"
|
||
else bad "audiod: interpreter 不是 /lib/ld.so.1"; fi
|
||
|
||
echo "==> meow_audio(CLI,musl 静态 + time32)"
|
||
ge audio "$AU" 'S24' 1
|
||
ge audio "$AU" 'S32' 1
|
||
|
||
echo "==> meow_launcherd(装包委托 nyai + 开关三态)"
|
||
ge launcherd "$LC" 'pkg_install: nyai unavailable at %s' 1
|
||
ge launcherd "$LC" 'pkg_install: rejected path: %s' 1
|
||
ge launcherd "$LC" 'pkg_install: ok' 1
|
||
ge launcherd "$LC" '--pkg-install' 1
|
||
ge launcherd "$LC" '/usr/bin/nyai' 1
|
||
for s in '正在%s…(等待设备确认)' '无法确认当前状态(上次已知:%s)' '切换未生效:当前仍为%s' \
|
||
'蓝牙状态未知' 'WiFi 开关状态未知' '无法读取开关状态(服务/控制器无响应)' \
|
||
'无法读取射频状态(rfkill/网卡无响应)'; do
|
||
ge launcherd "$LC" "$s" 1
|
||
done
|
||
|
||
echo "==> time32 二进制判据(4263 + 16B 布局写回;audiod 守护例外见 build_audiod.sh)"
|
||
# 门禁的退出码必须进 FAIL —— 否则「门禁失败但脚本宣布 ALL PASS」比没有门禁更危险。
|
||
GATE="$ROOT/patch_v2/sdk/test_time32_abi.sh"
|
||
if [ ! -f "$GATE" ]; then
|
||
bad "time32 门禁脚本缺失:$GATE"
|
||
elif ! bash "$GATE" --no-builds "$BM" "$NM" "$AU" "$LC"; then
|
||
bad "time32 二进制门禁 FAIL(4263 / 16B 布局写回)"
|
||
fi
|
||
|
||
echo "==> 汇总:fingerprints PASS=$PASS FAIL=$FAIL"
|
||
[ "$FAIL" -eq 0 ] || exit 1
|
||
echo " ALL PASS"
|