fix(boot): M69 普通重启/OTA 重启不再改写持久启动默认,切 Hiby 走一次性指示

用户定案(2026-11-12):/data/meow_boot_default 是「设置里的默认系统」,
只有显式设默认才许写;普通重启与 OTA 重启都不碰它,重启后选单按配置默认
(含 5s 倒计时)。「切换到 HibyOS」是这一次去 Hiby,用一次性指示
/data/meow_boot_once(bootmenu 开机读一次即删),不改持久默认。

meow_svc_power.c
- 新增 boot_default_intent()/apply_boot_default_intent():唯一写入点,
  CLI 与 IPC 共用一张意图表(SET_DEFAULT_* -> 持久;BACK_HIBY -> 一次性;
  REBOOT/UPGRADE/SHUTDOWN -> 两个都不写)。
- POWER_REBOOT 与 CLI `reboot` 删掉 write_boot_default(0)(病根)。
- POWER_BACK_HIBY 与 CLI `reboot --hiby` 改走同一条一次性指示路径。
- 写失败照常重启,只把消息说清楚(不静默假装成功)。

meow_bootmenu.c
- 新增 consume_boot_once():严格解析 0/1、读到即 unlink;删不掉时退一步
  清空内容并记日志,本次照用,绝不让开机失败。
- load_config() 优先级写明并落地:一次性指示 > 持久默认 > meow.conf > 编译默认。
- DEF_BOOT_DEFAULT 1 -> 0(MeowOS):与设置页 boot.default 默认值一致,
  避免「没设过默认/刷完固件首次开机」被丢进 Hiby。

测试(宿主,路径重定向到临时目录,不碰 /data)
- svc_power_bootdefault_test.c:意图表 + 落盘副作用 + 反向控制(改前会写)。
- test_bm_bootdefault.c:一次性指示优先/读一次即删/删后回落/非法内容/删不掉仍可开机。

未提交二进制、未改 scripts/build/fw_content.conf(钉值仍对应现有二进制,
下一轮重编再把 md5 回写)。
This commit is contained in:
AskaEth committed 2026-11-12 10:18:09 +08:00
1 parent a5fce76747
commit 84c7446aa6
4 files changed
+581 -41

No files matched your search

+89 -20
View File
@@ -10,6 +10,12 @@
* 动作逻辑与 launcher `power_menu.c` 的 `sys_do_reboot`/`set_boot_default_hiby`/`bootmode.sh Recovery`
* **同源 0-diff 搬移**,仅入口(CLI vs IPC)与鉴权层不同。
*
* 开机默认语义(M69,用户定案 2026-11-12):`/data/meow_boot_default` 是「设置里的默认系统」,
* **只有显式设默认(POWER_SET_DEFAULT_* / CLI set-default-*)才能写**;普通重启(POWER_REBOOT /
* CLI reboot)与 OTA 升级后的重启(POWER_UPGRADE)都不碰它——重启后选单按配置默认(含倒计时)。
* 「这一次去 Hiby」(POWER_BACK_HIBY / CLI `reboot --hiby`)只写一次性指示 `/data/meow_boot_once`,
* 由 `meow_bootmenu` 开机读一次即删,不改持久默认。
*
* 鉴权(II 期,MPK_SIGNATURE_DESIGN §6):IPC 服务端按【连接级身份】分级——`SO_PEERCRED` 取 pid →
* `readlink /proc/pid/exe` → 命中 `MeowAPPs/<pkg>/` 判定包名,或命中系统二进制 allowlist
* (/usr/bin/meow_*、/usr/data/meow/meow*、MeowPanel 后端)判定为系统身份;其余为 OTHER。
@@ -51,7 +57,8 @@
#define FBIOBLANK 0x4611
#define BACKLIGHT "/sys/class/backlight/backlight_pwm0/brightness"
#define BACKLIGHT_POWER "/sys/class/backlight/backlight_pwm0/bl_power"
#define BOOT_DEFAULT "/data/meow_boot_default" /* 0=MeowOS(默认),1=HibyOS */
#define BOOT_DEFAULT "/data/meow_boot_default" /* 持久默认=设置里的「默认系统」:0=MeowOS,1=HibyOS */
#define BOOT_ONCE "/data/meow_boot_once" /* 一次性指示:1=这次开机进 HibyOS(bootmenu 读一次即删) */
#define COLD_BOOT "/data/meow_cold_boot" /* 冷启标记:1=上次关机,0=上次重启 */
#define MTD_OTA "/dev/mtd5" /* ota 标记分区(8M) */
#define SETTINGS_FILE "/usr/data/meow/settings.conf"
@@ -72,6 +79,10 @@
#define CHG_AC_ONLINE MEOW_PS_DIR "/ac/online"
#define UPGRADE_FW "/usr/data/mnt/sd_0/r3proii.upt" /* 卡根升级固件(写 mtd5 前完整性校验) */
/* 启动默认两个文件的生产路径(语义见文件头);宿主自测可直接重定向这两个指针,不改语义。 */
static const char *g_boot_default_path = BOOT_DEFAULT;
static const char *g_boot_once_path = BOOT_ONCE;
/* 音量语义(与 launcher MEOW_VOL_DEFAULT/MEOW_VOL_MAX_DEFAULT、SDK MEOW_UI_VOL_* 一致):
* audio.volume 默认 60(写 DAC 映射值 0-100);audio.volume_max 默认 100(软上限 clamp)。 */
#ifndef MEOW_VOL_DEFAULT
@@ -279,14 +290,57 @@ static void sys_reboot_do(int cmd)
for (;;) usleep(1000);
}
/* ---------------- boot 默认 ---------------- */
/* 写 /data/meow_boot_default(0=MeowOS 默认 / 1=HibyOS 默认)。 */
static void write_boot_default(int v)
/* ---------------- boot 默认 ----------------
* 两个文件,两种语义(M69,用户定案 2026-11-12):
* · /data/meow_boot_default = 设置里的「默认系统」(持久)。**只有** SET_DEFAULT_* / set-default-*
* 写它;普通重启/升级/关机都不写,重启后由选单读它决定默认项。
* · /data/meow_boot_once = 「这一次去 Hiby」一次性指示。bootmenu 开机读一次即删、优先级更高。
* 写入策略集中在 boot_default_intent()(纯函数,宿主可测),CLI 与 IPC 共用同一张表。 */
static int write_boot_default(int v)
{
char b[8];
snprintf(b, sizeof b, "%d\n", v);
if (write_file_str(BOOT_DEFAULT, b, 0644) < 0) svc_log("write %s fail: %s", BOOT_DEFAULT, strerror(errno));
int rc = write_file_str(g_boot_default_path, b, 0644);
if (rc < 0) svc_log("write %s fail: %s", g_boot_default_path, strerror(errno));
else svc_log("boot_default=%d", v);
return rc;
}
static int write_boot_once(int v)
{
char b[8];
snprintf(b, sizeof b, "%d\n", v);
int rc = write_file_str(g_boot_once_path, b, 0644);
if (rc < 0) svc_log("write %s fail: %s", g_boot_once_path, strerror(errno));
else svc_log("boot_once=%d (one-shot; persistent default untouched)", v);
return rc;
}
/* 动作 → 开机默认写入意图(纯函数):
* *persist: -1=不写持久默认;0/1=把 /data/meow_boot_default 写成该值
* *once: -1=不写一次性指示;0/1=把 /data/meow_boot_once 写成该值
* 表外动作(POWER_REBOOT/POWER_UPGRADE/POWER_SHUTDOWN/读级…)两个都不写。 */
static void boot_default_intent(uint32_t cmd, int *persist, int *once)
{
*persist = -1;
*once = -1;
switch (cmd) {
case POWER_SET_DEFAULT_MEOW: *persist = 0; break; /* 用户显式设默认 */
case POWER_SET_DEFAULT_HIBY: *persist = 1; break; /* 用户显式设默认 */
case POWER_BACK_HIBY: *once = 1; break; /* 这一次去 Hiby(临时) */
default: break;
}
}
/* 按意图落盘(CLI 与 IPC 共用,防两条入口语义漂移)。
* 返回 0;-1=某次写入失败(动作仍照常继续:重启请求不该因标记写失败就不重启)。 */
static int apply_boot_default_intent(uint32_t cmd)
{
int persist = -1, once = -1, rc = 0;
boot_default_intent(cmd, &persist, &once);
if (persist >= 0 && write_boot_default(persist) < 0) rc = -1;
if (once >= 0 && write_boot_once(once) < 0) rc = -1;
return rc;
}
/* ---------------- 关机 logo ---------------- */
@@ -358,7 +412,7 @@ static void battery_fill(char *out, int cap)
static const char *boot_default_str(void)
{
int v = read_file_int_def(BOOT_DEFAULT, -1);
int v = read_file_int_def(g_boot_default_path, -1);
if (v < 0) return "unknown";
return v ? "hiby" : "meow";
}
@@ -455,10 +509,11 @@ static int execute_action(const m_power_action_t *a, m_power_status_t *st)
snprintf(st->msg, sizeof st->msg, "shutdown accepted");
return 1; /* 应答后:logo + poweroff(不返回) */
case POWER_REBOOT:
write_boot_default(0); /* 普通重启恒回 MeowOS(无视之前) */
/* 普通重启:**不写**持久默认、也不写一次性指示。重启后选单按配置默认(5s 倒计时)。
* 用户定案(2026-11-12):POWER_REBOOT 不该碰 /data/meow_boot_default。 */
sync();
st->code = MEOW_OK;
snprintf(st->msg, sizeof st->msg, "reboot accepted (boot=meow)");
snprintf(st->msg, sizeof st->msg, "reboot accepted (boot menu uses configured default)");
return 1;
case POWER_UPGRADE:
{ /* 写 mtd5 前先校验卡上升级固件(升级写保护);校验失败→非 OK、绝不写 mtd5/不 reboot。 */
@@ -474,18 +529,25 @@ static int execute_action(const m_power_action_t *a, m_power_status_t *st)
snprintf(st->msg, sizeof st->msg, "upgrade accepted");
return 1; }
case POWER_BACK_HIBY:
write_boot_default(1);
sync();
st->code = MEOW_OK;
snprintf(st->msg, sizeof st->msg, "reboot -> hiby accepted");
return 1;
{ /* 「切换到 HibyOS」= 这一次去 Hiby:只写一次性指示,持久默认不动。
* 与 CLI `reboot --hiby` 走同一张意图表(boot_default_intent),不写持久默认。 */
int rc = apply_boot_default_intent(POWER_BACK_HIBY);
sync();
st->code = MEOW_OK;
if (rc < 0)
snprintf(st->msg, sizeof st->msg,
"reboot -> hiby accepted; once flag write FAILED (will boot configured default)");
else
snprintf(st->msg, sizeof st->msg,
"reboot -> hiby accepted (once; persistent default unchanged)");
return 1; }
case POWER_SET_DEFAULT_MEOW:
write_boot_default(0);
apply_boot_default_intent(POWER_SET_DEFAULT_MEOW);
st->code = MEOW_OK;
snprintf(st->msg, sizeof st->msg, "boot_default=meow (next boot)");
return 0;
case POWER_SET_DEFAULT_HIBY:
write_boot_default(1);
apply_boot_default_intent(POWER_SET_DEFAULT_HIBY);
st->code = MEOW_OK;
snprintf(st->msg, sizeof st->msg, "boot_default=hiby (next boot)");
return 0;
@@ -846,8 +908,15 @@ static int cli_run(int n, char **v)
return 0; /* 不返回 */
}
if (!strcmp(cmd, "reboot")) {
if (n > 1 && !strcmp(v[1], "--hiby")) { write_boot_default(1); }
else write_boot_default(0); /* 普通重启恒回 MeowOS */
if (n > 1 && !strcmp(v[1], "--hiby")) {
/* 「这一次去 Hiby」:与 IPC POWER_BACK_HIBY 同一张意图表 —— 只写一次性指示,
* 持久默认(设置里的「默认系统」)不动。 */
if (apply_boot_default_intent(POWER_BACK_HIBY) < 0)
fprintf(stderr, "warning: %s write failed; next boot uses configured default\n", BOOT_ONCE);
else
printf("reboot -> hiby (once; persistent default unchanged)\n");
}
/* 普通重启:不写持久默认、不写一次性指示 —— 重启后选单读配置默认。 */
sys_reboot_do(LINUX_REBOOT_CMD_RESTART);
return 0;
}
@@ -863,12 +932,12 @@ static int cli_run(int n, char **v)
return 0;
}
if (!strcmp(cmd, "set-default-hiby")) {
write_boot_default(1);
apply_boot_default_intent(POWER_SET_DEFAULT_HIBY);
printf("boot_default=hiby (next boot)\n");
return 0;
}
if (!strcmp(cmd, "set-default-meow")) {
write_boot_default(0);
apply_boot_default_intent(POWER_SET_DEFAULT_MEOW);
printf("boot_default=meow (next boot)\n");
return 0;
}
@@ -921,7 +990,7 @@ static int cli_run(int n, char **v)
static const char *cli_usage(void)
{
return "shutdown|reboot[--hiby]|upgrade|set-default-hiby|set-default-meow|"
return "shutdown|reboot[--hiby=一次性去Hiby,不改默认]|upgrade|set-default-hiby|set-default-meow|"
"status|battery|reboot-reason|upgrade-status|screen on|off|timeout<秒>|dac on|off|status";
}