OreBolt-OS/modules/orebolt-reset/reset.c

131 lines
4.0 KiB
C
Executable File

/*
* reset.c -- System Stack Purge/Reset module
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Factory reset and purge coordinator. State machine: CONFIRM -> RUNNING -> DONE.
* Kills dosbox, brings usb0 down, deletes /data/loot_drop contents,
* calls sync(). Requires explicit PLAY confirmation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <dirent.h>
#include <fcntl.h>
#include <linux/input.h>
#include "h2_ui.h"
#include "log_manager.h"
enum action { ACT_NONE, ACT_CANCEL, ACT_PURGE };
enum state { STATE_CONFIRM, STATE_RUNNING, STATE_DONE };
static int input_fd;
static lv_obj_t *status_lbl;
static enum state state;
static void purge_system(void) {
LOG_INF("executing system purge");
int fd;
FILE *pgrep = popen("pidof dosbox 2>/dev/null", "r");
if (pgrep) {
char pidbuf[16];
if (fgets(pidbuf, sizeof(pidbuf), pgrep)) {
long pid = atol(pidbuf);
if (pid > 0) kill(pid, SIGTERM);
}
pclose(pgrep);
}
fd = open("/sys/class/net/usb0/operstate", O_WRONLY);
if (fd >= 0) { write(fd, "down", 4); close(fd); }
fd = open("/data/loot_drop", O_RDONLY | O_DIRECTORY);
if (fd >= 0) {
DIR *d = fdopendir(fd);
if (d) {
struct dirent *ent;
while ((ent = readdir(d)) != NULL) {
if (ent->d_name[0] == '.') continue;
char path[256];
snprintf(path, sizeof(path), "/data/loot_drop/%s", ent->d_name);
unlink(path);
}
closedir(d);
} else { close(fd); }
}
sync();
LOG_INF("purge complete");
}
static enum action read_action(void) {
struct input_event ev;
if (read(input_fd, &ev, sizeof(struct input_event)) <= 0) return ACT_NONE;
if (ev.type != EV_KEY || ev.value != 1) return ACT_NONE;
if (ev.code == H2_KEY_BACK) return ACT_CANCEL;
if (ev.code == H2_KEY_PLAY) return ACT_PURGE;
return ACT_NONE;
}
int main(void) {
init_h2_graphics_runtime("CORE HARDWARE STACK RESET");
LOG_INF("reset module started");
lv_obj_t *scr = lv_scr_act();
lv_obj_t *title = lv_label_create(scr);
lv_label_set_text(title, "SYSTEM STACK RESTORATION");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 15);
lv_obj_set_style_text_color(title, COLOR_PRIMARY, LV_PART_MAIN);
lv_obj_t *box = lv_obj_create(scr);
lv_obj_set_size(box, 290, 140);
lv_obj_align(box, LV_ALIGN_CENTER, 0, 15);
status_lbl = lv_label_create(box);
lv_obj_align(status_lbl, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_text_align(status_lbl, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
input_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
state = STATE_CONFIRM;
enum action act;
while (state != STATE_DONE) {
lv_timer_handler();
switch (state) {
case STATE_CONFIRM:
lv_label_set_text(status_lbl,
"WARNING: Drops connections, clears loot,\nresets network maps.\n\n"
"[PLAY] PURGE [BACK] CANCEL");
act = read_action();
if (act == ACT_CANCEL) state = STATE_DONE;
if (act == ACT_PURGE) {
lv_label_set_text(status_lbl, "EXECUTING PURGE...\nDO NOT POWER DOWN");
lv_obj_set_style_text_color(status_lbl, COLOR_PRIMARY, LV_PART_MAIN);
lv_timer_handler();
purge_system();
lv_label_set_text(status_lbl, "PURGE COMPLETE.\n\n[BACK] Exit");
lv_obj_set_style_text_color(status_lbl, COLOR_ACCENT, LV_PART_MAIN);
state = STATE_RUNNING;
}
break;
case STATE_RUNNING:
act = read_action();
if (act == ACT_CANCEL) state = STATE_DONE;
break;
default:
state = STATE_DONE;
break;
}
usleep(15000);
}
if (input_fd >= 0) close(input_fd);
LOG_INF("reset module exited");
return 0;
}