- scripts/build/build_fw_apps.sh: 通用配置驱动 (-c 配置路径可多套调试配置/-v 版本/-o 输出/-b 基线) - scripts/build/fw_content.conf: 固件内容清单 src|dst|md5|desc (md5配置化可空/强校验), 基线=M2.67(13条) - build_fw_apps_m267.sh: M2.67 基线脚本(历史逐版 m2xx 保留工作区勿入库) - 验证: 内容级0 diff(解包rootfs树) ✓; 多配置独立性/md5强校验/空md5跳过/S99→S84/外围CI移除 全过 - 注: .upt容器md5不可复现(repack.sh用mksquashfs+mkisofs内嵌时间戳) — 内容级0 diff为准
199 lines
8.6 KiB
Bash
Executable File
199 lines
8.6 KiB
Bash
Executable File
#!/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 路径(如 fw_apps/r3proii_m2_67.upt)。【必传】
|
||
# -b|--base fw_ssh 基线目录。默认 fw_ssh/squashfs-root。
|
||
#
|
||
# 通用步骤(读清单之外的固定逻辑,参照 build_fw_apps_m267.sh 的权威流程):
|
||
# 1) 解析参数
|
||
# 2) 建树:rm -rf fw_apps && mkdir -p && cp -a $BASE fw_apps/squashfs-root
|
||
# 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
|
||
# ============================================================================
|
||
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=""
|
||
|
||
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; }
|
||
mkdir -p "$(dirname "$OUT")"
|
||
|
||
SRC="$BASE" # 基线(拷贝源)
|
||
DST="$ROOT/fw_apps/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"
|
||
mkdir -p "$ROOT/fw_apps"
|
||
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"
|