Files

209 lines
9.3 KiB
Bash
Executable File
Raw Permalink 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
# ============================================================================
# build_fw_apps.sh — 通用固件打包脚本(配置驱动)
#
# 用法:
# build_fw_apps.sh -c <manifest> -v <version> -o <out.upt> [-b <base dir>]
#
# 参数:
# -c|--config 固件内容清单路径。默认 scripts/build/fw_content.conf。
# 传别的路径即可并存多套调试/场景配置(互不覆盖)。
# -v|--version 版本号,写入目标 /etc/meowos_version(如 0.7.62)。【必传】
# -o|--out 输出 .upt 路径(如 r3proii_m2_67.upt)。【必传】
# 若指向仓库内 fw_apps/ 下(非 out/),自动并入 fw_apps/out/ 归档。
# -b|--base fw_ssh 基线目录。默认 fw_ssh/squashfs-root。
#
# 通用步骤(读清单之外的固定逻辑):
# 1) 解析参数
# 2) 建树:rm -rf fw_apps/build && mkdir -p && cp -a $BASE fw_apps/build/squashfs-root
# (组装区 fw_apps/build/ 每次清理重建;产物 fw_apps/out/ 不受影响)
# 3) 校验基线:usr/bin/hiby_player 必须为 stock(a73f2c49…)
# 4) 解析清单:逐条 md5 校验(若填) + cp -f + chmod 755,目录自动建
# 5) 写版本:echo $VERSION > $DST/etc/meowos_version
# 6) 外围 CLI 瘦身:从 $DST/usr/bin 按白名单移除(已迁 TF 卡 MeowOS/opt/bin)
# 7) 启动图/背包/关机 logo:从 bootlogos/ 拷 logo_new→logo.jpeg、logo1_new→logo1、
# logo2_new→logo2、boot_anim_0.png→etc/boot_animation/0.png、shutdown_logo.jpeg→etc/
# 8) S99ssh → S84ssh:改名(内容不变),校验一致后删除 S99ssh(清单不含 S84)
# 9) repack:hiby_os_crack/scripts/repack.sh -i $DST -k unpacked_v14/xImage -o $OUT
# 10) 体积核对(rootfs ≤ 45,088,768)+ unpack 回验 0 diff
#
# 约定:改固件内容只改 fw_content.conf(每行 <src>|<dst>|<md5>|<desc>),不改本脚本。
# ============================================================================
set -e
# 项目根:由本脚本位置向上推(scripts/build/ → 根),可迁移
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# 默认值
CONFIG="$ROOT/scripts/build/fw_content.conf"
BASE="$ROOT/fw_ssh/squashfs-root"
VERSION=""
OUT=""
OUT_DIR="$ROOT/fw_apps/out" # 产物归档目录(不受构建清理影响)
usage() {
echo "用法: $0 -c <manifest.conf> -v <version> -o <out.upt> [-b <fw_ssh/squashfs-root>]"
echo " -c|--config <manifest> 固件内容清单路径 (默认 scripts/build/fw_content.conf)"
echo " -v|--version <version> 版本号,写入 etc/meowos_version (必传)"
echo " -o|--out <file> 输出 .upt 路径 (必传)"
echo " -b|--base <dir> fw_ssh 基线目录 (默认 fw_ssh/squashfs-root)"
}
# ---- 1) 解析参数 ----
while [ $# -gt 0 ]; do
case "$1" in
-c|--config) CONFIG="$2"; shift 2 ;;
-v|--version) VERSION="$2"; shift 2 ;;
-o|--out) OUT="$2"; shift 2 ;;
-b|--base) BASE="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) echo "!!! 未知参数: $1"; usage; exit 1 ;;
esac
done
[ -n "$VERSION" ] || { echo "!!! 缺少 -v/--version"; usage; exit 1; }
[ -n "$OUT" ] || { echo "!!! 缺少 -o/--out"; usage; exit 1; }
# 一律转绝对路径,避免后续 cd /tmp 后相对路径失效
case "$CONFIG" in /*) ;; *) CONFIG="$ROOT/$CONFIG" ;; esac
case "$BASE" in /*) ;; *) BASE="$ROOT/$BASE" ;; esac
case "$OUT" in /*) ;; *) OUT="$ROOT/$OUT" ;; esac
[ -f "$CONFIG" ] || { echo "!!! 清单不存在: $CONFIG"; exit 1; }
[ -d "$BASE" ] || { echo "!!! 基线不存在: $BASE"; exit 1; }
# 产物统一归档到 $ROOT/fw_apps/out/(避免某次构建清理误删;仅当 -o 指向仓库内非 out/ 路径时并入)
case "$OUT" in
"$OUT_DIR/"*) ;; # 已在 out/ 下,保持
"$ROOT/fw_apps/"*) OUT="$OUT_DIR/$(basename "$OUT")" ;; # 仓库内 fw_apps/ 下 → 并入 out/
esac
mkdir -p "$(dirname "$OUT")"
SRC="$BASE" # 基线(拷贝源)
DST="$ROOT/fw_apps/build/squashfs-root" # 组装目标(工作区,每次构建清理重建;产物不受影响)
LOGO_DIR="$ROOT/bootlogos"
# 外围 CLI(自 rootfs /usr/bin 移除;已迁 TF 卡 MeowOS/opt/bin/)
MIGRATE_TOOLS="curl socat tmux jq rsync nano htop ncdu file xxd"
# 基线 player 校验值(stock v1.4)
STOCK_PLAYER_MD5="a73f2c49a655659ef14db3bf6acecd78"
echo "==> 参数"
echo " ROOT=$ROOT"
echo " CONFIG=$CONFIG"
echo " BASE=$BASE"
echo " VERSION=$VERSION"
echo " OUT=$OUT"
# ---- 2) 建树(复制基线) ----
echo "==> 建树(复制基线)"
rm -rf "$ROOT/fw_apps/build"
mkdir -p "$ROOT/fw_apps/build" "$OUT_DIR"
cp -a "$SRC" "$DST"
# ---- 3) 校验基线 player 为 stock ----
echo "==> 校验基线 player 为 stock"
BASE_MD5=$(md5sum "$DST/usr/bin/hiby_player" | cut -d' ' -f1)
[ "$BASE_MD5" = "$STOCK_PLAYER_MD5" ] || {
echo "!!! hiby_player 不是 stock(a73f2c49): $BASE_MD5"; exit 1; }
# ---- 4) 解析清单,逐条 校验(md5 若填) + cp + chmod 755 ----
echo "==> 解析清单: $CONFIG"
CNT=0
while IFS='|' read -r src dst md5 desc; do
# 去首尾空白
src=$(echo "$src" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
dst=$(echo "$dst" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
# 注释 / 空行 / 无有效字段跳过
[ -z "$src" ] && continue
case "$src" in \#*) continue ;; esac
[ -z "$dst" ] && { echo " !!! 行缺 dst(跳过): $src"; continue; }
md5=$(echo "$md5" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
srcpath="$ROOT/$src"
[ -f "$srcpath" ] || { echo "!!! 源不存在: $srcpath"; exit 1; }
# 强校验 md5(若填)
if [ -n "$md5" ]; then
got=$(md5sum "$srcpath" | cut -d' ' -f1)
[ "$got" = "$md5" ] || {
echo "!!! 源 md5 不匹配: $src (期望 $md5, 实际 $got)"; exit 1; }
fi
# 目标绝对路径 $dst 的宿主目录
dstdir=$(dirname "$DST$dst")
mkdir -p "$dstdir"
cp -f "$srcpath" "$DST$dst"
chmod 755 "$DST$dst"
CNT=$((CNT+1))
[ -n "$desc" ] && echo " ${dst} <- ${src} (${desc})" || echo " ${dst} <- ${src}"
done < "$CONFIG"
echo " 已安装 $CNT 条"
# ---- 5) 写版本号 ----
echo "==> 写版本: $VERSION"
echo "$VERSION" > "$DST/etc/meowos_version"
# ---- 6) 外围 CLI 瘦身(已迁 TF 卡 MeowOS/opt/bin)----
echo "==> rootfs 瘦身:移除外围 CLI(已迁卡)"
for t in $MIGRATE_TOOLS; do
if [ -e "$DST/usr/bin/$t" ]; then rm -f "$DST/usr/bin/$t"; echo " removed /usr/bin/$t"; fi
done
# ---- 7) 启动图/背包/关机 logo(M2.1 用户自定义图覆盖 stock)----
echo "==> 启动图补回(M2.1):用户自定义 logo*.jpeg + boot_animation/0.png"
cp -f "$LOGO_DIR/logo_new.jpeg" "$DST/etc/logo.jpeg"; chmod 755 "$DST/etc/logo.jpeg"
cp -f "$LOGO_DIR/logo1_new.jpeg" "$DST/etc/logo1.jpeg"; chmod 755 "$DST/etc/logo1.jpeg"
cp -f "$LOGO_DIR/logo2_new.jpeg" "$DST/etc/logo2.jpeg"; chmod 755 "$DST/etc/logo2.jpeg"
mkdir -p "$DST/etc/boot_animation"
cp -f "$LOGO_DIR/boot_anim_0.png" "$DST/etc/boot_animation/0.png"; chmod 644 "$DST/etc/boot_animation/0.png"
echo " logo.jpeg/logo1.jpeg/logo2.jpeg + boot_animation/0.png ✓"
echo "==> 关机 logo(M2.1):/etc/shutdown_logo.jpeg"
cp -f "$LOGO_DIR/shutdown_logo.jpeg" "$DST/etc/shutdown_logo.jpeg"; chmod 755 "$DST/etc/shutdown_logo.jpeg"
[ -f "$DST/etc/shutdown_logo.jpeg" ] && echo " shutdown_logo.jpeg ✓"
# ---- 8) S99ssh → S84ssh(改名,内容不变,清单不含 S84;基线缺 S99 则跳过)----
echo "==> S99ssh -> S84ssh(改名,内容不变)"
if [ -f "$SRC/etc/init.d/S99ssh" ]; then
cp -f "$SRC/etc/init.d/S99ssh" "$DST/etc/init.d/S84ssh"; chmod 755 "$DST/etc/init.d/S84ssh"
rm -f "$DST/etc/init.d/S99ssh"
diff -q "$SRC/etc/init.d/S99ssh" "$DST/etc/init.d/S84ssh" >/dev/null 2>&1 \
&& echo " S84ssh == 原 S99ssh ✓" || { echo " !!! S84ssh 与 S99ssh 不一致"; exit 1; }
[ ! -e "$DST/etc/init.d/S99ssh" ] && echo " S99ssh 已移除 ✓" || { echo " !!! S99ssh 仍存在"; exit 1; }
else
echo " (基线无 S99ssh,跳过 S99→S84 改名)"
fi
# ---- 9) repack ----
echo "==> repack"
"$ROOT/hiby_os_crack/scripts/repack.sh" \
-i "$DST" \
-k "$ROOT/unpacked_v14/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
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)
echo "rootfs.squashfs = $RFSZ bytes"
if [ "$RFSZ" -le 45088768 ]; then echo "OK <= 上限"; else echo "!!! 超上限"; exit 1; fi
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
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
echo "0 diff ✓"
else
echo "!!! diff found:"; head -20 /tmp/fw_apps_rt_diff.log
exit 1
fi
echo "==> 最终固件 md5"
md5sum "$OUT"
ls -la "$OUT"