Files
MeowOS-For-R3P2/scripts/build/repack_repro.sh
T
tower d34406ac22 chore(fw): M56 重编 5 件受源码变动影响的产物 + 钉值回写 + 可复现打包器(0.8.51)
- 重编 netmgrd(M54 ACL)/audiod(M55 BT 增益 + M52 bind 失败即退)/launcherd(M52 multi_font 收口)/
  watchdog(M52 资源告警);meow_audio 源码未变,重编逐字节相同(md5 不变)
- fw_content.conf:5 条 md5 回写 + meow_power desc 去掉「policy 期3桩」(已实装)
- 新增 scripts/build/repack_repro.sh:mksquashfs -repro-time + genisoimage -creation-date
  + mtime 归一化 + 半成品防护(先写暂存再 mv、体积下限自检)
- build_fw_apps.sh:优先走可复现打包器、XIMAGE/TMPDIR 可在干净 checkout/worktree 覆盖
- rebuild_binaries.sh:新增 watchdog 目标(build_watchdog.sh 的 ROOT/.tools 在 worktree 不存在)
2026-11-12 08:25:04 +08:00

181 lines
7.3 KiB
Bash
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
# ============================================================================
# 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>),
# 只是把「墙钟时间」从产物里拿掉,使同一输入**连续打包两次逐字节相同**:
#
# 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:genisoimage 的卷创建时间用 `-creation-date <YYYYMMDDhhmmsscc>` 固定,
# 并把暂存目录里所有文件/目录的 mtime touch 到同一 epoch(ISO 目录记录取文件 mtime)。
#
# 用法:
# 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"