Files
MeowOS-For-R3P2/scripts/build/verify_fingerprints.sh
T
AskaEth 0d1b2d4c19 fix(fw): M51 r2 — 重编脚本开箱可用、自证门禁不再假绿、归因与 desc 纠正
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`,
    而钉值 commit 884d4c4 的源码已是 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 去掉「以太网连接」的夸大说法。
2026-11-11 21:02:09 +08:00

127 lines
5.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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"