// ----------------------------------------------------------------------------- /// @file RepairPresets.c /// @brief Description // ----------------------------------------------------------------------------- // Micro-Key bv // Industrieweg 28, 9804 TG Noordhorn // Postbus 92, 9800 AB Zuidhorn // The Netherlands // Tel: +31 594 503020 // Fax: +31 594 505825 // Email: support@microkey.nl // Web: www.microkey.nl // ----------------------------------------------------------------------------- /// $Revision$ /// $Author$ /// $Date$ // (c) 2017 Micro-Key bv // ----------------------------------------------------------------------------- /// @file RepairPresets.c /// @ingroup {group_name} // ----------------------------------------------------------------------------- // Include files // ----------------------------------------------------------------------------- #include #include "hsb-mrts.h" #include "Error.h" #include "RepairPresets.h" #include "CachedStorage.h" #include "crc32.h" #include "MemoryDevice.h" #include "Logger.h" // ----------------------------------------------------------------------------- // Constant and macro definitions // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Type definitions // ----------------------------------------------------------------------------- struct RepairPresets { bool initialized; bool presetsLoaded; REPAIR_PRESETS_ID currentPresetID; struct CachedStorage* presetStorage; struct MemoryDevice* memoryDevice; }; struct RepairPresetStorageClass { uint32_t crc; struct RepairPreset preset; }; // ----------------------------------------------------------------------------- // File-scope variables // ----------------------------------------------------------------------------- static struct RepairPresets _self = {.initialized = false, .presetsLoaded = false}; struct RepairPresets* const self = &_self; // ----------------------------------------------------------------------------- // Function declarations // ----------------------------------------------------------------------------- static void RepairPresets_verifyCRCs(void); static ErrorStatus RepairPresets_verifyPresetCRC(struct RepairPresetStorageClass* repairPreset); // ----------------------------------------------------------------------------- // Function definitions // ----------------------------------------------------------------------------- ErrorStatus RepairPresets_construct(struct CachedStorage* presetStorage, struct MemoryDevice* memoryDevice) { ErrorStatus returnValue = SUCCESS; if (!self->initialized) { if (returnValue == SUCCESS) { if (presetStorage != NULL) { self->presetStorage = presetStorage; } else { returnValue = ERROR; } } if (returnValue == SUCCESS) { if (memoryDevice != NULL) { if (memoryDevice->initialized) { self->memoryDevice = memoryDevice; } else { returnValue = ERROR; } } else { returnValue = ERROR; } } self->initialized = true; self->presetsLoaded = false; } else { returnValue = ERROR; } return returnValue; } void RepairPresets_destruct(void) { if (self->initialized) { self->initialized = false; self->presetsLoaded = false; } } ErrorStatus RepairPresets_loadPresets(REPAIR_PRESETS_ID presetID) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Destruct the cachedStorage to remove all previous data CachedStorage_destruct(self->presetStorage); // Get the new preset ID self->currentPresetID = presetID; // Construct new cached Storage with base address defined by the preset ID unsigned int pageNumber; switch (self->currentPresetID) { case REPAIR_PRESETS_ANODE: { pageNumber = APP_FLASH_PRESET_ANODE_PAGE; break; } case REPAIR_PRESETS_CATHODE: { pageNumber = APP_FLASH_PRESET_CATHODE_PAGE; break; } case REPAIR_PRESETS_MCP: { pageNumber = APP_FLASH_PRESET_MCP_PAGE; break; } case REPAIR_PRESETS_TESLA: { pageNumber = APP_FLASH_PRESET_TESLA_PAGE; break; } default: { LOGGER_ERROR(mainLog, "Unknown preset ID"); returnValue = ERROR; } } // If Preset ID was valid, go on loading presets from memory if (returnValue == SUCCESS) { // Create new cachedStorage with preset page number returnValue = CachedStorage_construct(self->presetStorage, self->memoryDevice, pageNumber, ((sizeof(struct RepairPresetStorageClass) * REPAIR_PRESETS_NUMBER_OF_PRESETS) / 4)); } else { self->presetsLoaded = false; } // Check the CRC on the loaded presets if (returnValue == SUCCESS) { RepairPresets_verifyCRCs(); } // CRCs are verified // If CRCs are correct on all presets, returnValue will still be SUCCESS if (returnValue == SUCCESS) { self->presetsLoaded = true; } // If any CRC is wrong } else { returnValue = ERROR; } return returnValue; } struct RepairPreset* RepairPresets_getPreset(unsigned int index) { struct RepairPreset* returnValue = NULL; if (self->initialized) { if (self->presetsLoaded) { // Index is human-readable, thus starting with 1 if ((index > 0) || (index <= REPAIR_PRESETS_NUMBER_OF_PRESETS)) { struct RepairPresetStorageClass* tempPreset; tempPreset = (struct RepairPresetStorageClass*)CachedStorage_readBlob(self->presetStorage, (index - 1) * sizeof(struct RepairPresetStorageClass) / 4); returnValue = (struct RepairPreset*)&tempPreset->preset; } } } return returnValue; } void RepairPresets_savePresets(void) { // Commit cache to memory - will not write if no changes have been made CachedStorage_commit(self->presetStorage); } static void RepairPresets_verifyCRCs(void) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { int loopCounter; struct RepairPresetStorageClass _tempPresetStorage; struct RepairPresetStorageClass* tempPresetStorage = &_tempPresetStorage; bool crcErrorFound = false; for (loopCounter = 0; loopCounter < REPAIR_PRESETS_NUMBER_OF_PRESETS; loopCounter++) { // Load next preset from cache tempPresetStorage = (struct RepairPresetStorageClass*)CachedStorage_readBlob(self->presetStorage, loopCounter * sizeof(struct RepairPresetStorageClass) / 4); // Verify CRC returnValue = RepairPresets_verifyPresetCRC(tempPresetStorage); // Check CRC verification if (returnValue != SUCCESS) { crcErrorFound = true; // CRC was not correct - replace corrupted preset with a DEFAULT preset RepairPreset_generateDefaultPreset(&tempPresetStorage->preset, loopCounter + 1); LOGGER_DEBUG(mainLog, "PRESET %d: Softstart: %d, Duration: %d, Voltage: %d", tempPresetStorage->preset.presetNumber, tempPresetStorage->preset.preset[0].softstartDuration, tempPresetStorage->preset.preset[0].duration, tempPresetStorage->preset.preset[0].voltage); // Write default preset to Cache RepairPresets_writePreset(&tempPresetStorage->preset); } } if (crcErrorFound) { Error_postError(ERROR_CRC_PRESETS); } // Commit cache to memory - will not write if no changes have been made CachedStorage_commit(self->presetStorage); } } static ErrorStatus RepairPresets_verifyPresetCRC(struct RepairPresetStorageClass* repairPreset) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Calculate the CRC of the given repair preset uint32_t tempCRC; tempCRC = crc32_calculate(0, &repairPreset->preset, sizeof(struct RepairPreset)); // Compare loaded and calculated CRC values - must be equal if (repairPreset->crc != tempCRC) { // CRCs do not match returnValue = ERROR; LOGGER_ERROR(mainLog, "CRC ERROR at repair preset %d (calculated %X but loaded %X)", repairPreset->preset.presetNumber, (unsigned int)tempCRC, (unsigned int)repairPreset->crc); } } else { returnValue = ERROR; } return returnValue; } ErrorStatus RepairPresets_writePreset(struct RepairPreset* preset) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { struct RepairPresetStorageClass tempPresetStorage; tempPresetStorage.preset = *preset; // Calculate CRC over preset tempPresetStorage.crc = crc32_calculate(0, &tempPresetStorage.preset, sizeof(struct RepairPreset)); // Put default preset on Cache CachedStorage_writeBlob(self->presetStorage, (tempPresetStorage.preset.presetNumber - 1) * sizeof(struct RepairPresetStorageClass) / 4, &tempPresetStorage, sizeof(struct RepairPresetStorageClass) / 4); } else { returnValue = ERROR; } return returnValue; }