/* * 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 #include #include #include #include #include #include #include #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; }