File syn_boot.c¶
File List > src > syntropic > system > syn_boot.c
Go to the documentation of this file
#if __has_include("syn_config.h")
#include "syn_config.h"
#endif
#if !defined(SYN_USE_BOOT) || SYN_USE_BOOT
#include "../system/syn_errlog.h"
#include "../util/syn_assert.h"
#include "syn_boot.h"
#include <string.h>
#define SYN_BOOT_ERR_CRASH_LOOP 0x0300
#define SYN_BOOT_ERR_SAFE_MODE 0x0301
SYN_Status syn_boot_init(SYN_Boot *boot, SYN_ParamStore *store, uint16_t safe_threshold)
{
if (boot == NULL || store == NULL) {
return SYN_INVALID_PARAM;
}
SYN_ASSERT(boot != NULL);
SYN_ASSERT(store != NULL);
memset(boot, 0, sizeof(*boot));
boot->store = store;
boot->safe_threshold = safe_threshold;
/* Try to load existing boot data */
SYN_Status st = syn_param_load(store, &boot->data);
if (st != SYN_OK) {
/* First boot ever — initialize defaults */
memset(&boot->data, 0, sizeof(boot->data));
boot->data.boot_count = 1;
boot->data.fail_count = 0;
boot->data.was_healthy = 0;
boot->data.last_reset = SYN_RESET_UNKNOWN;
syn_param_save(store, &boot->data);
boot->initialized = true;
return SYN_ERROR; /* first boot, no prior data */
}
/* Increment boot count */
boot->data.boot_count++;
/* Check if last boot was healthy */
if (!boot->data.was_healthy) {
boot->data.fail_count++;
} else {
boot->data.fail_count = 0;
}
/* Mark this boot as NOT yet healthy */
boot->data.was_healthy = 0;
/* Check for safe mode */
if (safe_threshold > 0 && boot->data.fail_count >= safe_threshold) {
boot->safe_mode = true;
}
/* Save updated boot data */
syn_param_save(store, &boot->data);
boot->initialized = true;
boot->errlog = NULL;
/* Log crash-loop and safe-mode events if errlog is later attached.
* Since errlog is typically initialized after boot, users should
* call syn_boot_set_errlog() then syn_boot_log_events(). */
return SYN_OK;
}
SYN_Status syn_boot_mark_healthy(SYN_Boot *boot)
{
if (boot == NULL || !boot->initialized) {
return SYN_INVALID_PARAM;
}
SYN_ASSERT(boot != NULL);
SYN_ASSERT(boot->initialized);
boot->data.was_healthy = 1;
boot->data.fail_count = 0;
return syn_param_save(boot->store, &boot->data);
}
void syn_boot_set_reset_reason(SYN_Boot *boot, uint8_t reason)
{
if (boot == NULL) {
return;
}
SYN_ASSERT(boot != NULL);
boot->data.last_reset = reason;
}
SYN_Status syn_boot_clear_safe_mode(SYN_Boot *boot)
{
if (boot == NULL || !boot->initialized) {
return SYN_INVALID_PARAM;
}
SYN_ASSERT(boot != NULL);
SYN_ASSERT(boot->initialized);
boot->safe_mode = false;
boot->data.fail_count = 0;
boot->data.was_healthy = 1;
return syn_param_save(boot->store, &boot->data);
}
void syn_boot_set_errlog(SYN_Boot *boot, SYN_ErrLog *errlog)
{
if (boot == NULL) {
return;
}
SYN_ASSERT(boot != NULL);
boot->errlog = errlog;
}
void syn_boot_log_events(SYN_Boot *boot)
{
if (boot == NULL || boot->errlog == NULL) {
return;
}
SYN_ASSERT(boot != NULL);
/* Log crash-loop if previous boot wasn't healthy */
if (boot->data.fail_count > 0) {
syn_errlog_record(boot->errlog, SYN_BOOT_ERR_CRASH_LOOP, SYN_ERR_WARNING,
(uint32_t)boot->data.fail_count);
}
/* Log safe mode entry */
if (boot->safe_mode) {
syn_errlog_record(boot->errlog, SYN_BOOT_ERR_SAFE_MODE, SYN_ERR_FATAL,
(uint32_t)boot->data.boot_count);
}
}
#endif /* SYN_USE_BOOT */