From fc27bd4b191acf1ab1851d634202879e8d89f905 Mon Sep 17 00:00:00 2001 From: Ralf Waldukat Date: Sun, 15 Feb 2026 12:41:10 +0700 Subject: [PATCH] feat(safety): Add bounds checking for voltage, current and calibration values Adds validation to prevent out-of-range values from being written to hardware or stored as calibration coefficients. Changes: - pwrctl.c: Add sanity limits (65V max input, 60V max output, 20A max current) - opendps.c: Validate calibration coefficients with reasonable bounds Invalid values are rejected, maintaining the last valid state. Prevents potential hardware damage from invalid ADC readings or calibration data. --- opendps/opendps.c | 16 ++++++++++++++++ opendps/pwrctl.c | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/opendps/opendps.c b/opendps/opendps.c index 302884e..ac4d376 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -332,31 +332,47 @@ set_param_status_t opendps_set_parameter(char *name, char *value) set_param_status_t opendps_set_calibration(char *name, float *value) { past_id_t param; + float min_val, max_val; if (strcmp(name,"A_ADC_K")==0){ param = past_A_ADC_K; + min_val = 0.1f; max_val = 100.0f; } else if(strcmp(name,"A_ADC_C")==0){ param = past_A_ADC_C; + min_val = -1000.0f; max_val = 1000.0f; } else if(strcmp(name,"A_DAC_K")==0){ param = past_A_DAC_K; + min_val = 0.01f; max_val = 10.0f; } else if(strcmp(name,"A_DAC_C")==0){ param = past_A_DAC_C; + min_val = 0.0f; max_val = 1000.0f; } else if(strcmp(name,"V_ADC_K")==0){ param = past_V_ADC_K; + min_val = 1.0f; max_val = 100.0f; } else if(strcmp(name,"V_ADC_C")==0){ param = past_V_ADC_C; + min_val = -1000.0f; max_val = 1000.0f; } else if(strcmp(name,"V_DAC_K")==0){ param = past_V_DAC_K; + min_val = 0.01f; max_val = 1.0f; } else if(strcmp(name,"V_DAC_C")==0){ param = past_V_DAC_C; + min_val = 0.0f; max_val = 100.0f; } else if(strcmp(name,"VIN_ADC_K")==0){ param = past_VIN_ADC_K; + min_val = 1.0f; max_val = 100.0f; } else if(strcmp(name,"VIN_ADC_C")==0){ param = past_VIN_ADC_C; + min_val = -1000.0f; max_val = 1000.0f; } else { return ps_not_supported; } + if (*value < min_val || *value > max_val) { + dbg_printf("Error: calibration value %f out of range [%f, %f]\n", *value, min_val, max_val); + return ps_range_error; + } + if (!past_write_unit(&g_past, param, (void*) value, sizeof(*value))) { dbg_printf("Error: past write opendps set calibration failed!\n"); return ps_flash_error; diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index 56e48b6..9d2f9dc 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -243,6 +243,8 @@ uint32_t pwrctl_calc_vin(uint16_t raw) float value = vin_adc_k_coef * raw + vin_adc_c_coef; if (value <= 0) return 0; + else if (value > 65000) + return 65000; else return value + 0.5f; /** Add 0.5f to value so it is correctly rounded when it is truncated */ } @@ -257,6 +259,8 @@ uint32_t pwrctl_calc_vout(uint16_t raw) float value = v_adc_k_coef * raw + v_adc_c_coef; if (value <= 0) return 0; + else if (value > 60000) + return 60000; else return value + 0.5f; /** Add 0.5f to value so it is correctly rounded when it is truncated */ } @@ -287,6 +291,8 @@ uint32_t pwrctl_calc_iout(uint16_t raw) float value = a_adc_k_coef * raw + a_adc_c_coef; if (value <= 0) return 0; + else if (value > 20000) + return 20000; else return value + 0.5f; /** Add 0.5f to value so correct rounding is done when truncated */ }