Files
MeowOS-For-R3P2/scripts/build/README.md
T
AskaEth c9f0cbaab6 feat(ntp): M22 网络校时 — 复用固件自带 ntpd + hwclock 回写 RTC
真机实测(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 内成功。
2026-11-06 12:49:13 +08:00

154 lines
8.3 KiB
Markdown
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.
# 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`。