/* * storage_init() - Validate storage content and copy data to shadow memory * * INPUT * none * OUTPUT * none */ void storage_init(void) { ConfigFlash *stor_config; /* Find storage sector with valid data and set storage_location variable */ if(find_active_storage(&storage_location)) { stor_config = (ConfigFlash *)flash_write_helper(storage_location); } else { /* Set to storage sector1 as default if no sector has been initialized */ storage_location = STORAGE_SECT_DEFAULT; stor_config = (ConfigFlash *)flash_write_helper(storage_location); } /* Reset shadow configuration in RAM */ storage_reset(); /* Verify storage partition is initialized */ if(memcmp((void *)stor_config->meta.magic , STORAGE_MAGIC_STR, STORAGE_MAGIC_LEN) == 0) { /* Clear out stor_config before finding end config node */ memcpy(shadow_config.meta.uuid, (void *)&stor_config->meta.uuid, sizeof(shadow_config.meta.uuid)); data2hex(shadow_config.meta.uuid, sizeof(shadow_config.meta.uuid), shadow_config.meta.uuid_str); if(stor_config->storage.version) { if(stor_config->storage.version <= STORAGE_VERSION) { storage_from_flash(stor_config); } } /* New app with storage version changed! update the storage space */ if(stor_config->storage.version != STORAGE_VERSION) { storage_commit(); } } else { /* Keep storage area cleared */ storage_reset_uuid(); storage_commit(); } }
/* * memory_storage_hash() - SHA256 hash of storage area * * INPUT * - hash: buffer to be filled with hash * - storage_location: current storage location (changes due to wear leveling) * OUTPUT * none */ int memory_storage_hash(uint8_t *hash, Allocation storage_location) { const uint8_t *storage_location_start; storage_location_start = (const uint8_t *)flash_write_helper(storage_location); sha256_Raw(storage_location_start, STORAGE_SECTOR_LEN, hash); return SHA256_DIGEST_LENGTH; }
/* * find_active_storage() - Find a sector with valid data * * INPUT - * - storage_location: pointer to save config data * OUTPUT - * status * */ bool find_active_storage(Allocation *storage_location) { bool ret_stat = false; Allocation storage_location_use; size_t storage_location_start; /* Find 1st storage sector with valid data */ for(storage_location_use = FLASH_STORAGE1; storage_location_use <= FLASH_STORAGE3; storage_location_use++) { storage_location_start = flash_write_helper(storage_location_use); if(memcmp((void *)storage_location_start, STORAGE_MAGIC_STR, STORAGE_MAGIC_LEN) == 0) { /* Found valid data. Load data and exit */ *storage_location = storage_location_use; ret_stat = true; break; } } return(ret_stat); }
/* * storage_commit() - Write content of configuration in shadow memory to * storage partion in flash * * INPUT * none * OUTPUT * none */ void storage_commit(void) { uint32_t shadow_ram_crc32, shadow_flash_crc32, retries; memcpy((void *)&shadow_config, STORAGE_MAGIC_STR, STORAGE_MAGIC_LEN); for(retries = 0; retries < STORAGE_RETRIES; retries++) { /* Capture CRC for verification at restore */ shadow_ram_crc32 = calc_crc32((uint32_t *)&shadow_config, sizeof(shadow_config) / sizeof(uint32_t)); if(shadow_ram_crc32 == 0) { continue; /* Retry */ } /* Make sure flash is in good state before proceeding */ if(!flash_chk_status()) { flash_clear_status_flags(); continue; /* Retry */ } /* Make sure storage sector is valid before proceeding */ if(storage_location < FLASH_STORAGE1 && storage_location > FLASH_STORAGE3) { /* Let it exhaust the retries and error out */ continue; } flash_unlock(); flash_erase_word(storage_location); wear_leveling_shift(); flash_erase_word(storage_location); /* Load storage data first before loading storage magic */ if(flash_write_word(storage_location, STORAGE_MAGIC_LEN, sizeof(shadow_config) - STORAGE_MAGIC_LEN, (uint8_t *)&shadow_config + STORAGE_MAGIC_LEN)) { if(!flash_write_word(storage_location, 0, STORAGE_MAGIC_LEN, (uint8_t *)&shadow_config)) { continue; /* Retry */ } } else { continue; /* Retry */ } /* Flash write completed successfully. Verify CRC */ shadow_flash_crc32 = calc_crc32((uint32_t *)flash_write_helper( storage_location), sizeof(shadow_config) / sizeof(uint32_t)); if(shadow_flash_crc32 == shadow_ram_crc32) { /* Commit successful, break to exit */ break; } else { continue; /* Retry */ } } flash_lock(); if(retries >= STORAGE_RETRIES) { layout_warning_static("Error Detected. Reboot Device!"); system_halt(); } }