Merge branch 'feat/m56-post-merge-rebuild-batch-0-8-51-pack'
This commit is contained in:
commit
f7921ba799
10 files changed
+238
-23
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,7 +7,10 @@
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
ROOT=../..
|
||||
CC="$ROOT/.tools/zig-mipsel-cc"
|
||||
# 交叉编译器:ZIGCC env 优先(与 build_netmgrd.sh 同口径;干净 worktree 里 <root>/.tools
|
||||
# 这个符号链接通常不存在,重编驱动会直接传 ZIGCC 进来),其次 <root>/.tools/,最后 $HOME/.tools/
|
||||
CC="${ZIGCC:-$ROOT/.tools/zig-mipsel-cc}"
|
||||
[ -x "$CC" ] || CC="$HOME/.tools/zig-mipsel-cc"
|
||||
INC="$ROOT/patch_v2/meow_launcherd" # meow_ipc.h(音量收编 v2:MSG_AUDIO_VOLUME/MSG_ACK)
|
||||
|
||||
if [ "$1" = "host" ]; then
|
||||
|
||||
Binary file not shown.
@@ -20,7 +20,7 @@
|
||||
# 缺陷版(4263 的 a1 直接指向调用方 8 字节缓冲、无宽度转换)两条都不成立。
|
||||
#
|
||||
# 用法(任意目录):
|
||||
# bash patch_v2/sdk/test_time32_abi.sh # 只跑构建门禁(10 个组件)
|
||||
# bash patch_v2/sdk/test_time32_abi.sh # 只跑构建门禁(11 个组件)
|
||||
# bash patch_v2/sdk/test_time32_abi.sh <mipsel-bin> ... # 构建门禁 + 二进制检查
|
||||
# bash patch_v2/sdk/test_time32_abi.sh --no-builds <bin> ... # 只跑二进制检查(旧用法)
|
||||
# 可用 OBJDUMP=<path> 指定 objdump(默认 llvm-objdump)。
|
||||
@@ -34,7 +34,7 @@ OD="${OBJDUMP:-llvm-objdump}"
|
||||
|
||||
usage() {
|
||||
echo "用法: $0 [--builds|--no-builds] [mipsel-binary ...]" >&2
|
||||
echo " 无参数 / --builds 只跑构建门禁(10 个 M43 组件)" >&2
|
||||
echo " 无参数 / --builds 只跑构建门禁(11 个 M43 组件 + meow_watchdog)" >&2
|
||||
echo " <binary> ... 构建门禁 + 二进制检查" >&2
|
||||
echo " --no-builds <binary> 只跑二进制检查" >&2
|
||||
}
|
||||
@@ -52,6 +52,7 @@ meow_svc_perf|patch_v2/meow_svc_perf/build_svc_perf.sh
|
||||
meow_powermgr|patch_v2/meow_powermgr/build_powermgr.sh
|
||||
meowpanel|patch_v2/meowpanel/build_meowpanel.sh
|
||||
meow_audio|patch_v2/meow_audiod/build_audiod.sh
|
||||
meow_watchdog|patch_v2/meow_watchdog/build_watchdog.sh
|
||||
'
|
||||
|
||||
# 语义断言:要求 16 字节写回与「被调函数填的 8 字节 ts32 缓冲」存在数据依赖。
|
||||
|
||||
@@ -171,18 +171,35 @@ else
|
||||
echo " (基线无 S99ssh,跳过 S99→S84 改名)"
|
||||
fi
|
||||
|
||||
# ---- 9) repack ----
|
||||
# 用 bash 显式执行:repack.sh 的 #!/usr/bin/env bash 在 Android 上无 /usr/bin/env,
|
||||
# 且经 su 跑时 termux-exec 的 LD_PRELOAD 被丢弃 → bad interpreter(M13 实测)。
|
||||
echo "==> repack"
|
||||
bash "$ROOT/hiby_os_crack/scripts/repack.sh" \
|
||||
# 优先用可复现打包器(scripts/build/repack_repro.sh:mksquashfs -repro-time +
|
||||
# genisoimage -creation-date + mtime 归一化)。可复现口径**到 squashfs/元数据为止**:
|
||||
# rootfs.squashfs / 分片 / ota_update.in 两次打包逐字节相同;`.upt` 本身仍差约 93 字节
|
||||
# (genisoimage 写的 Rock Ridge TF backup date,无覆盖开关),故 .upt 验收仍是
|
||||
# 「体积 + unpack 0 diff + 进包 md5」。
|
||||
# 未设 REPACK 时才回退历史 repack.sh(产物布局相同,时间戳全随墙钟);
|
||||
# **显式指定了却不存在 → 直接失败**,免得「以为用了可复现打包器、其实悄悄退回旧路径」。
|
||||
# 两者都按 bash 显式执行:repack.sh 的 #!/usr/bin/env bash 在 Android 上无 /usr/bin/env,
|
||||
# 且经 su 跑时 termux-exec 的 LD_PRELOAD 被丢弃 → bad interpreter(M13 实测)。
|
||||
if [ -n "${REPACK:-}" ]; then
|
||||
[ -f "$REPACK" ] || { echo "!!! REPACK 显式指定但不存在: $REPACK"; exit 1; }
|
||||
else
|
||||
REPACK="$ROOT/scripts/build/repack_repro.sh"
|
||||
[ -f "$REPACK" ] || REPACK="$ROOT/hiby_os_crack/scripts/repack.sh"
|
||||
fi
|
||||
echo " repack = $REPACK"
|
||||
# 内核镜像(unpacked_v14/xImage)未入库:干净 checkout / git worktree 里没有它,
|
||||
# 用 XIMAGE 指到主 checkout 的那份(普通 checkout 下默认值即可)。
|
||||
XIMAGE="${XIMAGE:-$ROOT/unpacked_v14/xImage}"
|
||||
[ -f "$XIMAGE" ] || { echo "!!! 内核镜像不存在: $XIMAGE(可用 XIMAGE=/path/to/xImage 覆盖)"; exit 1; }
|
||||
bash "$REPACK" \
|
||||
-i "$DST" \
|
||||
-k "$ROOT/unpacked_v14/xImage" \
|
||||
-k "$XIMAGE" \
|
||||
-o "$OUT" < /dev/null
|
||||
|
||||
# ---- 10) 体积核对(rootfs 分区, 上限 45,088,768) ----
|
||||
echo "==> 体积核对(rootfs 分区, 上限 45,088,768)"
|
||||
mkdir -p /tmp/fw_apps_chk && cd /tmp/fw_apps_chk
|
||||
mkdir -p "${TMPDIR:-/tmp}/fw_apps_chk" && cd "${TMPDIR:-/tmp}/fw_apps_chk"
|
||||
rm -rf ota_v0 ota_update.in rootfs.squashfs
|
||||
7z x -y "$OUT" ota_v0/ota_update.in > /dev/null 2>&1
|
||||
RFSZ=$(grep -A1 'img_name=rootfs' ota_v0/ota_update.in | grep img_size | cut -d= -f2)
|
||||
@@ -193,15 +210,15 @@ echo "==> rootfs.img md5"
|
||||
grep -A3 'img_name=rootfs' ota_v0/ota_update.in | grep img_md5 | cut -d= -f2
|
||||
|
||||
echo "==> unpack 回验(0 diff)"
|
||||
mkdir -p /tmp/fw_apps_rt && cd /tmp/fw_apps_rt
|
||||
mkdir -p "${TMPDIR:-/tmp}/fw_apps_rt" && cd "${TMPDIR:-/tmp}/fw_apps_rt"
|
||||
rm -rf ota_v0 ota_config.in squashfs-root rootfs.squashfs rootfs.squashfs.*
|
||||
7z x -y "$OUT" > /dev/null 2>&1
|
||||
find . -name "rootfs.squashfs.*" | sort -V | xargs cat > rootfs.squashfs 2>/dev/null
|
||||
unsquashfs -no-progress -d squashfs-root rootfs.squashfs > /dev/null 2>&1 || true
|
||||
if diff -rq --no-dereference "$DST" squashfs-root > /tmp/fw_apps_rt_diff.log 2>&1; then
|
||||
if diff -rq --no-dereference "$DST" squashfs-root > ${TMPDIR:-/tmp}/fw_apps_rt_diff.log 2>&1; then
|
||||
echo "0 diff ✓"
|
||||
else
|
||||
echo "!!! diff found:"; head -20 /tmp/fw_apps_rt_diff.log
|
||||
echo "!!! diff found:"; head -20 ${TMPDIR:-/tmp}/fw_apps_rt_diff.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
# ---- 用户态/服务守护二进制(usr/bin,全部 chmod 755 静态 MIPS)----
|
||||
patch_v2/bootmenu/meow_bootmenu|/usr/bin/meow_bootmenu|8bce6558cbc25faa8fbc105078003ef5|开机引导选单(MIPS32 musl 静态二进制):显示前按 settings.conf 的 display.brightness 设定面板亮度(下限取 display.brightness_min);菜单超时/按键长按时序
|
||||
patch_v2/meow_launcherd/meow_launcherd|/usr/bin/meow_launcherd|e21450ff6621a67fd854165413c58be1|桌面/启动器主程序(MIPS32 musl 静态,链 SDK meow_ui.a):桌面与状态栏渲染、设置页(亮度/蓝牙/WiFi)、App 启动;包安装委托 /usr/bin/nyai
|
||||
patch_v2/meow_watchdog/meow_watchdog|/usr/bin/meow_watchdog|37c57e0feb9cd220978bfd5deff75a1f|应用看门狗 M40:o32 time32 取时/睡眠(修 held 天文数字→单击误判长按)、电源阈值读 power.longpress_menu_ms/forceoff_ms(缺省 3000/8000,与 launcher 主屏统一);继承 M20 亮屏亮度按 settings 恢复(四支决策不再回退固定 60)
|
||||
patch_v2/meow_launcherd/meow_launcherd|/usr/bin/meow_launcherd|7562907822a4cf50783ab52570d452f1|桌面/启动器主程序(MIPS32 musl 静态,链 SDK meow_ui.a):桌面与状态栏渲染、设置页(亮度/蓝牙/WiFi)、App 启动;包安装委托 /usr/bin/nyai
|
||||
patch_v2/meow_watchdog/meow_watchdog|/usr/bin/meow_watchdog|25f769509a43d0f66287efd456c64281|应用看门狗 M40:o32 time32 取时/睡眠(修 held 天文数字→单击误判长按)、电源阈值读 power.longpress_menu_ms/forceoff_ms(缺省 3000/8000,与 launcher 主屏统一);继承 M20 亮屏亮度按 settings 恢复(四支决策不再回退固定 60)
|
||||
patch_v2/meow_svcd/meow_svcd|/usr/bin/meow_svcd|d2111094e458336b52f9e8d524e35a91|服务管理器 M2.77(+崩溃上报 meow_crash agent-187);M43 链 meow_time32(o32 time32 取时/睡眠,修 time64 ABI;重启退避/停止宽限恢复真实毫秒)
|
||||
mips-repo/bins/meow_mdns/bin/meow_mdns|/usr/bin/meow_mdns|d6b0151bda26768f19952dae1342610d|mDNS 应答器 M2.78(启动竞态+换IP重检 agent-194)
|
||||
patch_v2/meow_sysui/meow_sysui|/usr/bin/meow_sysui|d33fa6bd71541875de7e373721d8c9d8|系统 UI(sysui);M43 链 meow_time32(o32 time32 取时/睡眠,修 time64 ABI;监督重启退避恢复真实毫秒)
|
||||
@@ -38,12 +38,12 @@ patch_v2/meow_svc_power/meow_svc_power|/usr/bin/meow_svc_power|39ae3aa255695a97f
|
||||
patch_v2/meow_verify/meow_verify|/usr/bin/meow_verify|6c2e8ed24aebe5caf41e7aed391312d5|II期验签 2B(多公钥+v2签名块 agent-221)
|
||||
patch_v2/meow_crash/meow_crash|/usr/bin/meow_crash|ce8aa8bede960844b4d50dfa9171a13b|系统级崩溃捕获 (agent-187) + log升级: 清理前缀扩 perf_/hang_ 承接1GB纪律 (337);M43 链 meow_time32(o32 time32 取时/睡眠,修 time64 ABI)
|
||||
patch_v2/meow_svc_perf/meow_svc_perf|/usr/bin/meow_svc_perf|44e2ff6f5666ef6509e63ab3e606bb33|性能专项服务 M2.75 + log升级(337:卡死快照+perf基线) + OOM治理C(348:Cached/Dirty监控降载, /tmp/meow_cachegov_c.state单点);M43 链 meow_time32(o32 time32 取时/睡眠,修 time64 ABI)
|
||||
patch_v2/meow_audiod/meow_audiod|/usr/bin/meow_audiod|9f58b2197ed91d24951918d41a78cf29|独占音频守护(MIPS32 glibc-2.22 动态链接:interpreter /lib/ld.so.1,NEEDED libasound.so.2 / libc.so.6 / libpthread.so.0):DAC 与蓝牙 A2DP 输出路由、硬件音量、电平监控
|
||||
patch_v2/meow_audiod/meow_audiod|/usr/bin/meow_audiod|4a6ab894adccce6c86ddbff64ce4099c|独占音频守护(MIPS32 glibc-2.22 动态链接:interpreter /lib/ld.so.1,NEEDED libasound.so.2 / libc.so.6 / libpthread.so.0):DAC 与蓝牙 A2DP 输出路由、硬件音量、电平监控
|
||||
patch_v2/meow_audiod/meow_audio|/usr/bin/meow_audio|3909c8d226d9da5afba4563056d105a5|audiod 用户侧 CLI(MIPS32 musl 静态):status / tone / route(端口 0、2、3)/ vol 0-100 / output(dac 或 bt)/ monitor 子命令
|
||||
patch_v2/meow_powermgr/meow_powermgr|/usr/bin/meow_powermgr|40217b5dc91da5c08d094c403eeb5fb2|功耗管理专项服务期2 M6.1(期1+history/top/events+mp2731 current_now 实测充电功率+WiFi 未关联档/BT rfkill 细化+系数路径 /data/meow/powermgr/;IPC 0xD0-D7);M43 链 meow_time32(o32 time32 取时/睡眠,修 time64 ABI)
|
||||
patch_v2/meow_powermgr/meow_powermgr|/usr/bin/meow_power|40217b5dc91da5c08d094c403eeb5fb2|meow_powermgr 的 CLI 形态(同二进制双形态,argv[0]=meow_power 即 CLI:status/estimate/model/history/top/events,policy 期3桩);M43 链 meow_time32
|
||||
patch_v2/meow_netmgrd/meow_netmgrd|/usr/bin/meow_netmgrd|e62e7512d8a71a83bbba6d7c0d5e4fee|网络管理守护(MIPS32 musl 静态):WiFi 扫描/连接(含隐藏网)、接口流量观测、DNS/路由/策略、蓝牙控制面(开关/扫描/配对/连接/已配对/A2DP);/usr/bin/meow_net 为同一二进制的 CLI 形态
|
||||
patch_v2/meow_netmgrd/meow_netmgrd|/usr/bin/meow_net|e62e7512d8a71a83bbba6d7c0d5e4fee|meow_netmgrd 同一二进制的 CLI 形态(argv[0]=meow_net):status/iface/wifi/bt/rfkill/apps/conns/top/dns/policy 等子命令
|
||||
patch_v2/meow_powermgr/meow_powermgr|/usr/bin/meow_power|40217b5dc91da5c08d094c403eeb5fb2|meow_powermgr 的 CLI 形态(同二进制双形态,argv[0]=meow_power 即 CLI:status/estimate/model/history/top/events,policy show / set profile 与 calibrate start / stop / list(power 子命令已在 meow_powermgr 实装,非桩));M43 链 meow_time32
|
||||
patch_v2/meow_netmgrd/meow_netmgrd|/usr/bin/meow_netmgrd|025772103ffc2ecd3c962a845cb584f4|网络管理守护(MIPS32 musl 静态):WiFi 扫描/连接(含隐藏网)、接口流量观测、DNS/路由/策略、蓝牙控制面(开关/扫描/配对/连接/已配对/A2DP);/usr/bin/meow_net 为同一二进制的 CLI 形态
|
||||
patch_v2/meow_netmgrd/meow_netmgrd|/usr/bin/meow_net|025772103ffc2ecd3c962a845cb584f4|meow_netmgrd 同一二进制的 CLI 形态(argv[0]=meow_net):status/iface/wifi/bt/rfkill/apps/conns/top/dns/policy 等子命令
|
||||
patch_v2/ntpsync/meow_ntpsync|/usr/bin/meow_ntpsync|f3c3abe4a960560f59f4101e6c444722|网络校时 M22(复用固件自带 ntp-4.2.8p14 一次性 -q 校时 + hwclock -w -u 回写 RTC;自带看门狗/总超时/默认路由轮询/进程锁,不自常驻、不阻塞调用方;r1 修:trap 收尸 ntpd 子进程+孤儿收尸、日志不可写不再吞掉 hwclock、锁用 <pid> 子目录自证且只删自己的锁)
|
||||
|
||||
# ---- 开机 init 脚本(etc/init.d,数字决定启动顺序,按文件名自然序)----
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
# COMPAT_HOME 兼容 HOME 目录(默认 ${TMPDIR:-$HOME/tmp}/meow-build-home)
|
||||
#
|
||||
# 用法:
|
||||
# bash scripts/build/rebuild_binaries.sh # 全部 5 组
|
||||
# bash scripts/build/rebuild_binaries.sh # 全部 6 组
|
||||
# bash scripts/build/rebuild_binaries.sh bootmenu # 只编指定的(可多个)
|
||||
# 组件名:bootmenu netmgrd audiod audio launcherd
|
||||
# 组件名:bootmenu netmgrd audiod audio launcherd watchdog
|
||||
set -u
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
@@ -118,8 +118,8 @@ report() {
|
||||
printf ' %-44s %8s B %s\n' "$1" "$(stat -c%s "$f")" "$(md5sum "$f" | cut -d' ' -f1)"
|
||||
}
|
||||
|
||||
do_bootmenu=0; do_netmgrd=0; do_audiod=0; do_audio=0; do_launcherd=0
|
||||
if [ $# -eq 0 ]; then do_bootmenu=1; do_netmgrd=1; do_audiod=1; do_audio=1; do_launcherd=1; fi
|
||||
do_bootmenu=0; do_netmgrd=0; do_audiod=0; do_audio=0; do_launcherd=0; do_watchdog=0
|
||||
if [ $# -eq 0 ]; then do_bootmenu=1; do_netmgrd=1; do_audiod=1; do_audio=1; do_launcherd=1; do_watchdog=1; fi
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
bootmenu) do_bootmenu=1 ;;
|
||||
@@ -127,7 +127,8 @@ for a in "$@"; do
|
||||
audiod) do_audiod=1 ;;
|
||||
audio) do_audio=1 ;;
|
||||
launcherd) do_launcherd=1 ;;
|
||||
*) die "未知组件: $a(bootmenu netmgrd audiod audio launcherd)" ;;
|
||||
watchdog) do_watchdog=1 ;;
|
||||
*) die "未知组件: $a(bootmenu netmgrd audiod audio launcherd watchdog)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -143,5 +144,10 @@ echo " ZIG=$ZIG ($("$ZIG" version 2>/dev/null || echo '?'))"
|
||||
[ "$do_audiod" = 1 ] && { run audiod patch_v2/meow_audiod bash build_audiod.sh; report patch_v2/meow_audiod/meow_audiod; }
|
||||
[ "$do_audio" = 1 ] && { run audio patch_v2/meow_audiod bash build_audiod.sh cli; report patch_v2/meow_audiod/meow_audio; }
|
||||
[ "$do_launcherd" = 1 ] && { ensure_ui_a; run launcherd patch_v2/meow_launcherd bash build_launcher.sh; report patch_v2/meow_launcherd/meow_launcherd; }
|
||||
# watchdog:走它自己的 build_watchdog.sh(编译参数只有一份,改脚本即改批次)。
|
||||
# 该脚本的 CC 认 ZIGCC env(M56 r1 起的口径),所以 worktree 里 <root>/.tools 不存在也能编;
|
||||
# 这里显式传 ZIGCC=,与其余组件同一个编译器,不再内联复制参数。
|
||||
[ "$do_watchdog" = 1 ] && { run watchdog patch_v2/meow_watchdog env ZIGCC="$ZIGCC" bash build_watchdog.sh
|
||||
report patch_v2/meow_watchdog/meow_watchdog; }
|
||||
|
||||
echo "==> 完成。产物自证:bash scripts/build/verify_fingerprints.sh"
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
#!/bin/bash
|
||||
# ============================================================================
|
||||
# repack_repro.sh — .upt 打包(mksquashfs + 分片 md5 链 + ISO),时间戳尽量可复现
|
||||
#
|
||||
# 与 hiby_os_crack/scripts/repack.sh 的产物布局逐字节等价(ota_update.in / ota_v0.ok /
|
||||
# ota_config.in / rootfs.squashfs.NNNN.<prev-md5> / ota_md5_rootfs.squashfs.<md5>),
|
||||
# 只把墙钟时间从「squashfs + 元数据」里拿掉。**可复现到什么程度(实测口径,别夸大)**:
|
||||
# ✅ bytes-reproducible:rootfs.squashfs、ota_md5_rootfs.squashfs.*、ota_update.in、
|
||||
# 分片文件名与内容、xImage 侧 —— 同一输入连续两次打包全部相同。
|
||||
# ❌ not bytes-reproducible:`.upt`(ISO)本身。genisoimage 会给 Rock Ridge `TF`
|
||||
# 记录写 **backup date**(TF flag=0x1a,第三个 7 字节字段),该字段取墙钟且**没有
|
||||
# 覆盖开关**(`-creation-date` 只定卷的创建/修改时间)。M56 实测两次打包 `cmp -l`
|
||||
# 恰好 93 字节不同,全在该字段(分钟字节),载荷 0 差异。
|
||||
# 因此 `.upt` 的验收口径仍是:**体积 + unpack 0 diff + 进包 md5**。
|
||||
#
|
||||
# 时间戳处理:
|
||||
# 1) squashfs:`-repro-time <epoch>`(= -mkfs-time + -inode-time;mksquashfs 4.7 起)。
|
||||
# 只加 -all-time 不够 —— 超级块的 mkfs_time 仍是墙钟(M60 实测)。本脚本按
|
||||
# `mksquashfs -help-all` 能力探测,依次尝试:
|
||||
# -repro-time <t> (4.7+)
|
||||
# -mkfs-time <t> -inode-time <t> (4.6)
|
||||
# -mkfs-time <t> -all-time <t> (老版本)
|
||||
# 都没有 → 告警并按旧口径(体积 + unpack 0 diff + 进包 md5)出货。
|
||||
# 2) ISO:卷创建时间用 `-creation-date <秒数>` 固定,并把暂存目录里所有文件/目录的
|
||||
# mtime touch 到同一 epoch(ISO 目录记录取文件 mtime)。backup date 无解,见上。
|
||||
#
|
||||
# 用法:
|
||||
# repack_repro.sh -i <squashfs-root> -k <xImage> -o <out.upt>
|
||||
# SOURCE_DATE_EPOCH=1735689600 覆盖固定时间(默认见 REPRO_EPOCH)。
|
||||
# ============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
REPRO_EPOCH="${SOURCE_DATE_EPOCH:-1735689600}" # 2025-01-01T00:00:00Z
|
||||
TEMP_DIR="${TMPDIR:-/tmp}/meow-repack-repro"
|
||||
|
||||
# 本机(Termux)没有 /usr/bin/mksquashfs:fw 工具集放在 ~/.cache/fwtools/shims
|
||||
# (glibc 版 mksquashfs/unsquashfs/genisoimage 经 grun 运行)。
|
||||
if ! command -v mksquashfs >/dev/null 2>&1 && [ -d "$HOME/.cache/fwtools/shims" ]; then
|
||||
PATH="$HOME/.cache/fwtools/shims:$PATH"
|
||||
fi
|
||||
|
||||
show_help() {
|
||||
sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//'
|
||||
}
|
||||
|
||||
input_root=""
|
||||
input_ximage=""
|
||||
output_file=""
|
||||
|
||||
while getopts ":i:k:o:h" opt; do
|
||||
case "$opt" in
|
||||
i) input_root="$OPTARG" ;;
|
||||
k) input_ximage="$OPTARG" ;;
|
||||
o) output_file="$OPTARG" ;;
|
||||
h) show_help; exit 0 ;;
|
||||
:) echo "Error: -$OPTARG 需要参数" >&2; exit 1 ;;
|
||||
\?) echo "Error: 未知参数 -$OPTARG" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$input_root" ] || { echo "Error: -i 必填" >&2; exit 1; }
|
||||
[ -n "$input_ximage" ] || { echo "Error: -k 必填" >&2; exit 1; }
|
||||
[ -n "$output_file" ] || { echo "Error: -o 必填" >&2; exit 1; }
|
||||
[ -d "$input_root" ] || { echo "Error: '$input_root' 不存在" >&2; exit 1; }
|
||||
[ -f "$input_ximage" ] || { echo "Error: '$input_ximage' 不存在" >&2; exit 1; }
|
||||
command -v mksquashfs >/dev/null 2>&1 || { echo "Error: 缺 mksquashfs" >&2; exit 1; }
|
||||
command -v genisoimage >/dev/null 2>&1 || echo "WARN: 无 genisoimage,将尝试 mkisofs" >&2
|
||||
|
||||
input_root=$(realpath "$input_root")
|
||||
input_ximage=$(realpath "$input_ximage")
|
||||
output_file=$(realpath -m "$output_file")
|
||||
[ -e "$output_file" ] && rm -f "$output_file"
|
||||
|
||||
ISO_TOOL=genisoimage
|
||||
command -v genisoimage >/dev/null 2>&1 || ISO_TOOL=mkisofs
|
||||
|
||||
# ---- squashfs 时间戳参数:按能力探测 ----------------------------------------
|
||||
sq_help="$(mksquashfs -help-all 2>/dev/null || mksquashfs -help 2>/dev/null || true)"
|
||||
sq_time=()
|
||||
# 直接用 case 匹配字符串,**不要**写成 `printf ... | grep -q`:脚本是 set -o pipefail,
|
||||
# grep -q 命中后立刻退出 → printf 收 SIGPIPE(141) → 整条管道判失败 → 参数被静默丢掉
|
||||
# (M56 踩过一次:ISO 卷时间因此回落成墙钟,两次打包不一致)。
|
||||
case "$sq_help" in
|
||||
*-repro-time*) sq_time=(-repro-time "$REPRO_EPOCH") ;;
|
||||
*-mkfs-time*)
|
||||
case "$sq_help" in
|
||||
*-inode-time*) sq_time=(-mkfs-time "$REPRO_EPOCH" -inode-time "$REPRO_EPOCH") ;;
|
||||
*-all-time*) sq_time=(-mkfs-time "$REPRO_EPOCH" -all-time "$REPRO_EPOCH") ;;
|
||||
esac ;;
|
||||
esac
|
||||
if [ "${#sq_time[@]}" -eq 0 ]; then
|
||||
echo "WARN: 本机 mksquashfs 不支持 -mkfs-time/-repro-time —— squashfs 内不含可复现时间戳," >&2
|
||||
echo " 只能按旧口径(体积 + unpack 0 diff + 进包 md5)验收。" >&2
|
||||
fi
|
||||
|
||||
# genisoimage 1.1.11 的 -creation-date 只吃得下「秒数」形式:传 YYYYMMDDhhmmsscc
|
||||
# (本工具 man 里推荐的 16 位串)会直接 *** buffer overflow detected *** 崩掉。
|
||||
# 传秒数时 PVD 的 Creation/Modif. Time 都被写成同一时刻(xorriso -pvd_info 可核),
|
||||
# 正是可复现需要的样子。
|
||||
iso_date="$REPRO_EPOCH"
|
||||
iso_time=()
|
||||
iso_help="$("$ISO_TOOL" -help 2>&1 || true)"
|
||||
case "$iso_help" in
|
||||
*-creation-date*) iso_time=(-creation-date "$iso_date") ;;
|
||||
esac
|
||||
|
||||
rm -rf "$TEMP_DIR"
|
||||
mkdir -p "$TEMP_DIR/ota_v0"
|
||||
pushd "$TEMP_DIR/ota_v0" >/dev/null
|
||||
|
||||
echo "### GENERATING NEW SQUASHFS FILES ###"
|
||||
echo " mksquashfs 时间参数: ${sq_time[*]:-(无)} epoch=$REPRO_EPOCH"
|
||||
mksquashfs "$input_root" rootfs.squashfs -comp lzo -all-root "${sq_time[@]}"
|
||||
|
||||
rootfs_size=$(stat -c%s rootfs.squashfs)
|
||||
rootfs_md5=$(md5sum rootfs.squashfs | awk '{print $1}')
|
||||
|
||||
split rootfs.squashfs -d -a 4 -b 512k rootfs.squashfs.
|
||||
rm rootfs.squashfs
|
||||
|
||||
md5=$rootfs_md5
|
||||
ota_md5_rootfs="ota_md5_rootfs.squashfs.${rootfs_md5}"
|
||||
> "$ota_md5_rootfs"
|
||||
for part in $(ls rootfs.squashfs.[0-9]* | sort); do
|
||||
md5next=$(md5sum "$part" | awk '{print $1}')
|
||||
echo "$md5next" >> "$ota_md5_rootfs"
|
||||
mv "$part" "$part.$md5"
|
||||
md5="$md5next"
|
||||
done
|
||||
|
||||
echo "### GENERATING NEW xImage FILES ###"
|
||||
cp "$input_ximage" xImage
|
||||
ximage_size=$(stat -c%s xImage)
|
||||
ximage_md5=$(md5sum xImage | awk '{print $1}')
|
||||
split xImage -d -a 4 -b 512k xImage.
|
||||
rm xImage
|
||||
|
||||
md5=$ximage_md5
|
||||
ota_md5_ximage="ota_md5_xImage.${ximage_md5}"
|
||||
> "$ota_md5_ximage"
|
||||
for part in $(ls xImage.[0-9]* | sort); do
|
||||
md5next=$(md5sum "$part" | awk '{print $1}')
|
||||
echo "$md5next" >> "$ota_md5_ximage"
|
||||
mv "$part" "$part.$md5"
|
||||
md5="$md5next"
|
||||
done
|
||||
|
||||
echo "### GENERATING METADATA FILES ###"
|
||||
cat > ota_update.in <<-EOM
|
||||
ota_version=0
|
||||
|
||||
img_type=kernel
|
||||
img_name=xImage
|
||||
img_size=${ximage_size}
|
||||
img_md5=${ximage_md5}
|
||||
|
||||
img_type=rootfs
|
||||
img_name=rootfs.squashfs
|
||||
img_size=${rootfs_size}
|
||||
img_md5=${rootfs_md5}
|
||||
EOM
|
||||
|
||||
echo > ota_v0.ok
|
||||
echo "current_version=0" > ../ota_config.in
|
||||
|
||||
echo "### GENERATING FIRMWARE FILE ###"
|
||||
# ISO 的目录记录取文件 mtime → 全树归一化到 REPRO_EPOCH(含目录自身;-h 跟随符号链接元数据)。
|
||||
find "$TEMP_DIR" -exec touch -h -d "@$REPRO_EPOCH" {} +
|
||||
# 先写暂存路径,成功后再 mv 到交付路径:genisoimage 中途 abort(本机 1.1.11 有已知崩溃)
|
||||
# 时,交付路径上不会留下「看起来像成品」的残缺 ISO(M56 踩过:28,672 B 半成品)。
|
||||
iso_tmp="${TEMP_DIR}.iso" # 暂存在打包树之外(否则 ISO 会把自己读进去)
|
||||
"$ISO_TOOL" -o "$iso_tmp" -J -r "${iso_time[@]}" "$TEMP_DIR"
|
||||
[ -s "$iso_tmp" ] || { echo "!!! ISO 为空: $iso_tmp" >&2; exit 1; }
|
||||
mv -f "$iso_tmp" "$output_file"
|
||||
iso_size=$(stat -c%s "$output_file")
|
||||
# 反「静默半成品」:ISO 至少要装得下 rootfs 本体(+xImage + 元数据),小了就是没写完。
|
||||
[ "$iso_size" -ge "$rootfs_size" ] || {
|
||||
echo "!!! ISO 体积 $iso_size B < rootfs $rootfs_size B —— 打包不完整" >&2
|
||||
rm -f "$output_file"; exit 1; }
|
||||
|
||||
popd >/dev/null
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
echo
|
||||
echo "Repacking complete!"
|
||||
echo " rootfs.squashfs = ${rootfs_size} B md5=${rootfs_md5}"
|
||||
echo " xImage = ${ximage_size} B md5=${ximage_md5}"
|
||||
echo " firmware: $output_file"
|
||||
Reference in new issue
Block a user