真机实测(0.8.47,2026-11-06)定位到的根因不是「没有 NTP 客户端」: 固件自带 ntp-4.2.8p14(/usr/sbin/ntpd)和 /etc/ntp.conf(4 个 pool.ntp.org), 但没有任何 init 脚本/进程启动它 —— 有客户端、没启动。 实测证据: - RTC 存在且可读(/dev/rtc0,10003000.rtc),内核开机 hctosys=1, 冷启动不回到 1970 → 掉电保持;RTC 存 UTC(since_epoch == date +%s)。 - 但 RTC 会走慢且无人纠正:实测系统时间比 NTP 慢 49 s;把系统时间人为 拨错 4 h 后观察 65 s 无人纠正,RTC 也不跟随系统时间。 - UDP/123 出网正常(ntpd -q 一次成功 time set +48.877s);DNS/HTTP 正常。 - udhcpc 的 default.script 不处理 option 42,实测热点也不下发。 - ntpd -q 不会回写 RTC(步进后 sys-rtc 仍差 49 s)→ 必须 hwclock -w -u。 - ntpd 没有超时参数,无服务器时永久存活 → 必须自带看门狗。 - -p 形式的 server 首个 poll 要 ~64 s;配置里加 iburst 后 8 s 内返回。 实现(新增,不改任何基线文件): - /usr/bin/meow_ntpsync:一次性校时器。复用 ntpd -q -g + 运行时生成的 iburst 配置;内置 IP 兜底(阿里/腾讯/Cloudflare)→ DNS 名兜底; 单次 15 s 看门狗、默认路由轮询、1 h 短路、进程锁、失败静默。 成功严格校时后 hwclock -w -u 回写 RTC(RTC 存 UTC,必须 -u)。 - /etc/init.d/S45meow_ntpsync:开机只 setsid 后台拉起并立即返回 (关键路径 +0 秒;后台最长约 150 s 自行退出),失败不阻断 init。 - /usr/share/udhcpc/default.script.d/50meow_ntpsync:只在 bound/renew 触发(设备上唯一可靠的「网络就绪」事件),后台拉起后立即 exit 0; 有 $ntpsrv(option 42)就优先用。基线 default.script 本就有 HOOK_DIR 循环,目录原本为空。 - tests/run_tests.sh:宿主沙箱单测(假 ntpd/hwclock/网络探测)。 验证:dash 与 busybox sh 各 sh -n 通过;单测两套 shell 各 23/23 通过; 真机(/tmp 下运行,未装系统目录)首跑 8 s rc=0、ntpd slew 成功、 RTC 由 1793940395 写成 1793940452(49 s 偏差被纠正)、hwclock -u -r 吻合; 二次运行 0 s 短路;-b -t 3 无网络 5 s 退出 rc=1; DHCP 灌入不可达服务器 192.0.2.x 仍靠 IP 兜底在 ~10 s 内成功。
154 lines
8.3 KiB
Markdown
154 lines
8.3 KiB
Markdown
# MeowOS 固件打包脚本使用说明(scripts/build/)
|
||
|
||
> 本目录是 MeowOS 固件打包的**唯一入口**。核心思想:**只改配置文件,不改脚本**。
|
||
> 新增/更新固件内容 → 改 `fw_content.conf`;打包 → 跑 `build_fw_apps.sh`。
|
||
> 本文档防遗忘,覆盖常见场景与踩坑记录。
|
||
|
||
---
|
||
|
||
## 1. 文件一览
|
||
|
||
| 文件 | 作用 |
|
||
|---|---|
|
||
| `build_fw_apps.sh` | **通用打包脚本**(配置驱动)。读清单 → 组树 → repack → 校验 → 出固件。**不要改它的逻辑**,除非打包流程本身要变。 |
|
||
| `fw_content.conf` | **固件内容清单**(默认配置)。每行一条 `<src>|<dst>|<md5>|<desc>`,声明"哪个本地文件装到固件哪里"。**改固件内容只改这里。** |
|
||
| `README.md` | 本说明。 |
|
||
|
||
> 曾有一批独立脚本 `build_fw_apps_m2xx.sh`(每版复制一个、内部硬编码 md5),**已清理删除**,不再使用。它们的问题:需每版改脚本、且共享 `fw_apps/` 目录互相清空。现统一走"一个通用脚本 + 一个配置文件"。
|
||
|
||
---
|
||
|
||
## 2. 用法
|
||
|
||
```bash
|
||
cd /home/Aska/Project/R3ProII
|
||
|
||
# 用默认配置打包,版本号 0.7.68,输出 r3proii_m2_73.upt
|
||
bash scripts/build/build_fw_apps.sh -v 0.7.68 -o r3proii_m2_73.upt
|
||
|
||
# 用指定配置(并存多套调试/场景配置时)
|
||
bash scripts/build/build_fw_apps.sh -c scripts/build/fw_content.conf -v 0.7.68 -o r3proii_m2_73.upt
|
||
|
||
# 指定基线目录(默认 fw_ssh/squashfs-root)
|
||
bash scripts/build/build_fw_apps.sh -v 0.7.68 -o r3proii_m2_73.upt -b fw_ssh/squashfs-root
|
||
```
|
||
|
||
### 参数
|
||
|
||
| 参数 | 必填 | 说明 |
|
||
|---|---|---|
|
||
| `-c, --config` | 否 | 清单路径,默认 `scripts/build/fw_content.conf`。传别的路径即用另一套配置(互不覆盖)。 |
|
||
| `-v, --version` | **是** | 版本号(如 `0.7.68`),写入固件 `/etc/meowos_version`。 |
|
||
| `-o, --out` | **是** | 输出 `.upt` 路径(如 `r3proii_m2_73.upt`)。若指向仓库内 `fw_apps/` 下(非 `out/`),自动并入 `fw_apps/out/` 归档。 |
|
||
| `-b, --base` | 否 | 基线根文件系统目录,默认 `fw_ssh/squashfs-root`。 |
|
||
|
||
### 产物去哪
|
||
|
||
- **工作区(每次清理重建)**:`fw_apps/build/` —— 组装 squashfs-root 树,用后即弃。
|
||
- **产物归档(不受清理影响)**:`fw_apps/out/` —— 打包好的 `.upt` 固定放这,多次打包互不覆盖、不会误删。
|
||
|
||
> **重要**:`-o` 给相对路径时按"文件命名"即可(如 `-o r3proii_m2_73.upt`),脚本会自动归档到 `fw_apps/out/r3proii_m2_73.upt`。
|
||
|
||
---
|
||
|
||
## 3. 修改固件内容(只改配置)
|
||
|
||
固件里加/换一个组件,只需在 `fw_content.conf` 加/改一行:
|
||
|
||
```
|
||
<src>|<dst>|<md5>|<desc>
|
||
```
|
||
|
||
- `<src>`:仓库内相对路径(相对项目根 `ROOT`),如 `patch_v2/meow_launcherd/meow_launcherd`。
|
||
- `<dst>`:目标绝对路径(装入固件),如 `/usr/bin/meow_launcherd` 或 `/etc/init.d/S90meow_bootmenu`。
|
||
- `<md5>`:**可空 = 不校验**;填了 = 打包前对 `<src>` 做强校验,不一致即 `exit 1`(防呆:源被改/路径错)。**改了源码后要更新这里的 md5**(`md5sum <src>`)。
|
||
- `<desc>`:注释说明(可省略,出现会保留)。
|
||
|
||
规则:
|
||
- `#` 开头为注释,空行忽略。
|
||
- 目标目录自动创建;**每条**条目装入后一律 `chmod 755`(`usr/bin` / `etc/init.d` / `etc/profile.d` 之外同理,例如 udhcpc 钩子 `usr/share/udhcpc/default.script.d/*` 必须可执行才会被调用)。
|
||
- 多重配置并存:复制 `fw_content.conf` 改名,用 `-c` 指定,互不干扰。
|
||
|
||
### 覆盖基线已有文件(清单 `<dst>` 与基线同名)
|
||
|
||
清单条目对目标目录是**无条件 `cp -f` 覆盖**:不校验基线原文件的 md5、也不跳过「已存在」的文件,只要
|
||
`<dst>` 命中就行。脚本里唯一的基线校验是第 2 步的 `usr/bin/hiby_player`(stock a73f2c49…),与清单条目无关。
|
||
|
||
因此覆盖类条目要自己在 `<desc>` 里写清「覆盖基线 xxx(基线 md5 …)」,便于复盘对照基线。例(M21 开机亮度链):
|
||
|
||
```
|
||
patch_v2/bootmenu/S11jpeg_display_shell|/etc/init.d/S11jpeg_display_shell|<md5>|覆盖基线 S11(基线 md5 249220f2…)…
|
||
patch_v2/bootmenu/S22brightness|/etc/init.d/S22brightness|<md5>|新增:…(S21mount_ubifs 之后按用户设置恢复背光)
|
||
```
|
||
|
||
> 覆盖基线 init 脚本时,顺序仍由**文件名**决定(`rcS` 按 `/etc/init.d/S??*` 自然序执行),不能靠清单顺序。
|
||
|
||
### 常见:更新某个二进制后改 md5
|
||
|
||
```bash
|
||
md5sum patch_v2/meow_launcherd/meow_launcherd
|
||
# → 9ca4c5e8a919f59cb2cdd6326da23065
|
||
```
|
||
把 `fw_content.conf` 里对应行 md5 替换成新值即可。
|
||
|
||
---
|
||
|
||
## 4. 打包流程做了哪些事(通用步骤)
|
||
|
||
脚本读清单之外,还会自动做这些固定动作(**无需在清单里声明**):
|
||
|
||
1. 建树:复制基线 `$BASE` → `fw_apps/build/squashfs-root`。
|
||
2. 校验基线:`usr/bin/hiby_player` 必须是 stock(md5 `a73f2c49…`),否则中止(防 stock 被改坏)。
|
||
3. 解析清单:逐条(md5 若有则强校验)→ `cp -f` → `chmod 755`,目录自动建。
|
||
4. 写版本:`echo $VERSION > $DST/etc/meowos_version`(单点版本号来源)。
|
||
5. 外围 CLI 瘦身:从 `/usr/bin` 移除白名单工具(`curl socat tmux jq rsync nano htop ncdu file xxd`——已迁 TF 卡 `MeowOS/opt/bin/`)。
|
||
6. 启动图/背包/关机 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/`。
|
||
7. `S99ssh` → `S84ssh`:改名(内容不变),校验一致后删 `S99ssh`(清单不含 S84)。
|
||
8. repack:`hiby_os_crack/scripts/repack.sh -i $DST -k unpacked_v14/xImage -o $OUT`。
|
||
9. 体积核对:rootfs 分区 ≤ **45,088,768** 字节,超限中止。
|
||
10. unpack 回验:把打包产物解回到官方 squashfs,与 `$DST` 比对 **0 diff**,发现差异即中止并打印 diff。
|
||
|
||
### 清单里**不要**加的东西(通用步骤已处理)
|
||
|
||
- `/etc/meowos_version`(由 `-v` 写入)
|
||
- `/etc/logo*`、`/etc/boot_animation/0.png`、`/etc/shutdown_logo.jpeg`(由 bootlogos/ 拷贝)
|
||
- `/etc/init.d/S84ssh`(由基线 `S99ssh` 改名而来)
|
||
- `usr/bin` 外围 CLI 瘦身(按白名单移除)
|
||
|
||
> **易混淆**:`/etc/shutdown_logo.jpeg` 是**图片**(通用步骤从 `bootlogos/shutdown_logo.jpeg` 拷);`/etc/init.d/S95shutdown_logo` 是**启动/停止脚本**(清单里单独一条 `S95shutdown_logo`,负责关机时显示该图)。二者不同,别混。
|
||
|
||
---
|
||
|
||
## 5. 踩坑记录(重要)
|
||
|
||
- **脚本共享目录互相清空**:早期每个版本一个脚本、都 `rm -rf fw_apps`,并行跑会删掉彼此的 `.upt` 产物。→ 已改为 `fw_apps/build/`(工作区)+ `fw_apps/out/`(归档)分离,且删光独立脚本。
|
||
- **改源码忘更新 md5**:清单里 md5 是强校验,源变了但 md5 没改 → 打包直接失败。**凡是动了清单里列的源文件,先 `md5sum` 更新对应行。**
|
||
- **SDK 库(`meow_ui.a`)不入固件**:它由 APP(如 hello)链接,走 TF 卡 `MeowAPPs/` 热更新,**不要**加进清单。
|
||
- **`fw_apps/` 被 gitignore**:固件产物与组装树都是构建产物,勿提交。
|
||
- **`scripts/build/` 根目录 gitignore**:构建产物与组装树勿提交。但本目录的 **`README.md`/`build_fw_apps.sh`/`fw_content.conf` 已 `git add -f` 入库**(这三个是仓库侧应保留的脚本/配置/说明);其余(`fw_apps/` 产物等)不入库。
|
||
|
||
---
|
||
|
||
## 6. 每次打固件的最小步骤
|
||
|
||
```bash
|
||
# 1. 确认要进的组件 md5 无变化(若改了源码先更新 fw_content.conf)
|
||
md5sum patch_v2/meow_launcherd/meow_launcherd patch_v2/meow_svc_power/meow_svc_power
|
||
|
||
# 2. 打包(版本号 + 输出名)
|
||
bash scripts/build/build_fw_apps.sh -v 0.7.68 -o r3proii_m2_73.upt
|
||
|
||
# 3. 看结果:0 diff、体积 ≤ 上限、最终固件 md5
|
||
# 产物在 fw_apps/out/r3proii_m2_73.upt
|
||
|
||
# 4. 推卡升级:scp 到设备卡根 /usr/data/mnt/sd_0/r3proii.upt(先备份当前为 prevNx)
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 相关权威文档
|
||
|
||
- 固件/升级细节:`docs/MEOWOS_SPEC_REF.md`(版本单点 `/etc/meowos_version`、rootfs 上限 45088768、mtd 分区、升级=写 mtd5)。
|
||
- 组件来源:`patch_v2/`(launcher/bootmenu/svcd/sysui/mdns/nyai/svc_power/svc_perf 等)。
|
||
- 专项服务/电源 CLI:`devdocs/plan/SYSTEM_FRAMEWORK_SERVICES.md`。
|