1From 5fd2662e1f20b5c645ff0755e84424bae303fa45 Mon Sep 17 00:00:00 2001 2From: Bence Balogh <bence.balogh@arm.com> 3Date: Mon, 9 Sep 2024 09:42:58 +0200 4Subject: [PATCH] Platform: CS1000: Validate both metadata replicas 5 6According to the [1] both metadata replica integrity should be checked 7during the update agent initialization, and if one of the replica is 8corrupted then it should be fixed by copying the other replica. 9 10This commit: 11- Adds the integrity check and correction to the 12 corstone1000_fwu_host_ack() function. This function is called when 13 the Host core has booted. 14- Updates the metadata_read() function so both replica can be read. 15- Adds metadata_write_replica() function to write metadata replicas 16 separately. 17 18[1] https://developer.arm.com/documentation/den0118/a/?lang=en 19 20Signed-off-by: Bence Balogh <bence.balogh@arm.com> 21Upstream-Status: Pending [Not submitted to upstream yet] 22--- 23 .../corstone1000/fw_update_agent/fwu_agent.c | 167 ++++++++++++------ 24 .../corstone1000/fw_update_agent/fwu_agent.h | 7 + 25 2 files changed, 119 insertions(+), 55 deletions(-) 26 27diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c 28index 92b918c67..aad6208e0 100644 29--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c 30+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c 31@@ -395,20 +395,33 @@ static enum fwu_agent_error_t metadata_read_without_validation(struct fwu_metada 32 #endif 33 34 #ifdef BL1_BUILD 35-static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) 36+static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata, uint8_t replica_num) 37 { 38 int ret; 39+ uint32_t replica_offset = 0; 40 41- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, 42- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); 43+ FWU_LOG_MSG("%s: enter\n\r", __func__); 44 45 if (!p_metadata) { 46 return FWU_AGENT_ERROR; 47 } 48 49- ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET, 50- p_metadata, sizeof(struct fwu_metadata)); 51- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { 52+ if (replica_num == 1) { 53+ replica_offset = FWU_METADATA_REPLICA_1_OFFSET; 54+ } else if (replica_num == 2) { 55+ replica_offset = FWU_METADATA_REPLICA_2_OFFSET; 56+ } else { 57+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); 58+ return FWU_AGENT_ERROR; 59+ } 60+ 61+ FWU_LOG_MSG("%s: flash addr = %u, size = %d\n\r", __func__, 62+ replica_offset, sizeof(*p_metadata)); 63+ 64+ 65+ ret = FWU_METADATA_FLASH_DEV.ReadData(replica_offset, 66+ p_metadata, sizeof(*p_metadata)); 67+ if (ret < 0 || ret != sizeof(*p_metadata)) { 68 return FWU_AGENT_ERROR; 69 } 70 71@@ -422,17 +435,27 @@ static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) 72 return FWU_AGENT_SUCCESS; 73 } 74 #else 75-static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) 76+static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata, uint8_t replica_num) 77 { 78 uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; 79 partition_entry_t *part; 80 int ret; 81 82+ FWU_LOG_MSG("%s: enter\n\r", __func__); 83+ 84 if (!p_metadata) { 85 return FWU_AGENT_ERROR; 86 } 87 88- part = get_partition_entry_by_type(&metadata_uuid); 89+ if (replica_num == 1) { 90+ part = get_partition_entry_by_type(&metadata_uuid); 91+ } else if (replica_num == 2) { 92+ part = get_partition_replica_by_type(&metadata_uuid); 93+ } else { 94+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); 95+ return FWU_AGENT_ERROR; 96+ } 97+ 98 if (!part) { 99 FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); 100 return FWU_AGENT_ERROR; 101@@ -461,39 +484,38 @@ static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) 102 103 #ifdef BL1_BUILD 104 static enum fwu_agent_error_t metadata_write( 105- struct fwu_metadata *p_metadata) 106+ struct fwu_metadata *p_metadata, uint8_t replica_num) 107 { 108 int ret; 109+ uint32_t replica_offset = 0; 110 111- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, 112- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); 113+ FWU_LOG_MSG("%s: enter\n\r", __func__); 114 115 if (!p_metadata) { 116 return FWU_AGENT_ERROR; 117 } 118 119- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_1_OFFSET); 120- if (ret != ARM_DRIVER_OK) { 121- return FWU_AGENT_ERROR; 122- } 123- 124- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_1_OFFSET, 125- p_metadata, sizeof(struct fwu_metadata)); 126- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { 127+ if (replica_num == 1) { 128+ replica_offset = FWU_METADATA_REPLICA_1_OFFSET; 129+ } else if (replica_num == 2) { 130+ replica_offset = FWU_METADATA_REPLICA_2_OFFSET; 131+ } else { 132+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); 133 return FWU_AGENT_ERROR; 134 } 135 136 FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, 137- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); 138+ replica_offset, sizeof(*p_metadata)); 139 140- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); 141+ 142+ ret = FWU_METADATA_FLASH_DEV.EraseSector(replica_offset); 143 if (ret != ARM_DRIVER_OK) { 144 return FWU_AGENT_ERROR; 145 } 146 147- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, 148- p_metadata, sizeof(struct fwu_metadata)); 149- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { 150+ ret = FWU_METADATA_FLASH_DEV.ProgramData(replica_offset, 151+ p_metadata, sizeof(*p_metadata)); 152+ if (ret < 0 || ret != sizeof(*p_metadata)) { 153 return FWU_AGENT_ERROR; 154 } 155 156@@ -503,7 +525,7 @@ static enum fwu_agent_error_t metadata_write( 157 } 158 #else 159 static enum fwu_agent_error_t metadata_write( 160- struct fwu_metadata *p_metadata) 161+ struct fwu_metadata *p_metadata, uint8_t replica_num) 162 { 163 uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; 164 partition_entry_t *part; 165@@ -513,7 +535,15 @@ static enum fwu_agent_error_t metadata_write( 166 return FWU_AGENT_ERROR; 167 } 168 169- part = get_partition_entry_by_type(&metadata_uuid); 170+ if (replica_num == 1) { 171+ part = get_partition_entry_by_type(&metadata_uuid); 172+ } else if (replica_num == 2) { 173+ part = get_partition_replica_by_type(&metadata_uuid); 174+ } else { 175+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); 176+ return FWU_AGENT_ERROR; 177+ } 178+ 179 if (!part) { 180 FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); 181 return FWU_AGENT_ERROR; 182@@ -533,32 +563,51 @@ static enum fwu_agent_error_t metadata_write( 183 return FWU_AGENT_ERROR; 184 } 185 186- part = get_partition_replica_by_type(&metadata_uuid); 187- if (!part) { 188- FWU_LOG_MSG("%s: FWU metadata replica partition not found\n\r", __func__); 189- return FWU_AGENT_ERROR; 190- } 191+ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, 192+ p_metadata->active_index, p_metadata->previous_active_index); 193+ return FWU_AGENT_SUCCESS; 194+} 195+#endif 196 197- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, 198- part->start, sizeof(struct fwu_metadata)); 199+static enum fwu_agent_error_t metadata_write_both_replica( 200+ struct fwu_metadata *p_metadata) 201+{ 202+ enum fwu_agent_error_t ret = FWU_AGENT_ERROR; 203 204- ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); 205- if (ret != ARM_DRIVER_OK) { 206- return FWU_AGENT_ERROR; 207+ ret = metadata_write(&_metadata, 1); 208+ if (ret) { 209+ return ret; 210 } 211 212- ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, 213- p_metadata, sizeof(struct fwu_metadata)); 214- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { 215- return FWU_AGENT_ERROR; 216+ ret = metadata_write(&_metadata, 2); 217+ if (ret) { 218+ return ret; 219 } 220 221- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, 222- p_metadata->active_index, p_metadata->previous_active_index); 223 return FWU_AGENT_SUCCESS; 224 } 225-#endif 226 227+enum fwu_agent_error_t fwu_metadata_check_and_correct_integrity(void) 228+{ 229+ enum fwu_agent_error_t ret_replica_1 = FWU_AGENT_ERROR; 230+ enum fwu_agent_error_t ret_replica_2 = FWU_AGENT_ERROR; 231+ 232+ /* Check integrity of both metadata replica */ 233+ ret_replica_1 = metadata_read(&_metadata, 1); 234+ ret_replica_2 = metadata_read(&_metadata, 2); 235+ 236+ if (ret_replica_1 != FWU_AGENT_SUCCESS && ret_replica_2 != FWU_AGENT_SUCCESS) { 237+ return FWU_AGENT_ERROR; 238+ } else if (ret_replica_1 == FWU_AGENT_SUCCESS && ret_replica_2 != FWU_AGENT_SUCCESS) { 239+ metadata_read(&_metadata, 1); 240+ metadata_write(&_metadata, 2); 241+ } else if (ret_replica_1 != FWU_AGENT_SUCCESS && ret_replica_2 == FWU_AGENT_SUCCESS) { 242+ metadata_read(&_metadata, 2); 243+ metadata_write(&_metadata, 1); 244+ } 245+ 246+ return FWU_AGENT_SUCCESS; 247+} 248 249 enum fwu_agent_error_t fwu_metadata_init(void) 250 { 251@@ -617,8 +666,8 @@ enum fwu_agent_error_t fwu_metadata_provision(void) 252 * had a firmware data?. If yes, then don't initialize 253 * metadata 254 */ 255- metadata_read(&_metadata); 256- if(_metadata.active_index < 2 || _metadata.previous_active_index <2){ 257+ metadata_read(&_metadata, 1); 258+ if(_metadata.active_index < 2 || _metadata.previous_active_index < 2){ 259 if(_metadata.active_index ^ _metadata.previous_active_index) 260 return FWU_AGENT_SUCCESS; 261 } 262@@ -652,13 +701,13 @@ enum fwu_agent_error_t fwu_metadata_provision(void) 263 _metadata.crc_32 = crc32((uint8_t *)&_metadata.version, 264 sizeof(struct fwu_metadata) - sizeof(uint32_t)); 265 266- ret = metadata_write(&_metadata); 267+ ret = metadata_write_both_replica(&_metadata); 268 if (ret) { 269 return ret; 270 } 271 272- memset(&_metadata, 0, sizeof(struct fwu_metadata)); 273- ret = metadata_read(&_metadata); 274+ memset(&_metadata, 0, sizeof(_metadata)); 275+ ret = metadata_read(&_metadata, 1); 276 if (ret) { 277 return ret; 278 } 279@@ -825,7 +874,7 @@ static enum fwu_agent_error_t flash_full_capsule( 280 metadata->crc_32 = crc32((uint8_t *)&metadata->version, 281 sizeof(struct fwu_metadata) - sizeof(uint32_t)); 282 283- ret = metadata_write(metadata); 284+ ret = metadata_write_both_replica(metadata); 285 if (ret) { 286 return ret; 287 } 288@@ -852,7 +901,7 @@ enum fwu_agent_error_t corstone1000_fwu_flash_image(void) 289 290 Select_Write_Mode_For_Shared_Flash(); 291 292- if (metadata_read(&_metadata)) { 293+ if (metadata_read(&_metadata, 1)) { 294 ret = FWU_AGENT_ERROR; 295 goto out; 296 } 297@@ -938,7 +987,7 @@ static enum fwu_agent_error_t accept_full_capsule( 298 metadata->crc_32 = crc32((uint8_t *)&metadata->version, 299 sizeof(struct fwu_metadata) - sizeof(uint32_t)); 300 301- ret = metadata_write(metadata); 302+ ret = metadata_write_both_replica(metadata); 303 if (ret) { 304 return ret; 305 } 306@@ -1034,7 +1083,7 @@ static enum fwu_agent_error_t fwu_select_previous( 307 metadata->crc_32 = crc32((uint8_t *)&metadata->version, 308 sizeof(struct fwu_metadata) - sizeof(uint32_t)); 309 310- ret = metadata_write(metadata); 311+ ret = metadata_write_both_replica(metadata); 312 if (ret) { 313 return ret; 314 } 315@@ -1064,7 +1113,7 @@ void bl1_get_active_bl2_image(uint32_t *offset) 316 FWU_ASSERT(0); 317 } 318 319- if (metadata_read(&_metadata)) { 320+ if (metadata_read(&_metadata, 1)) { 321 FWU_ASSERT(0); 322 } 323 324@@ -1203,9 +1252,17 @@ enum fwu_agent_error_t corstone1000_fwu_host_ack(void) 325 return FWU_AGENT_ERROR; 326 } 327 328+ /* This cannot be added to the fwu_metadata_init() because that function is 329+ * called before the logging is enabled by TF-M. */ 330+ ret = fwu_metadata_check_and_correct_integrity(); 331+ if (ret = FWU_AGENT_SUCCESS) { 332+ FWU_LOG_MSG("fwu_metadata_check_and_correct_integrity failed\r\n"); 333+ return ret; 334+ } 335+ 336 Select_Write_Mode_For_Shared_Flash(); 337 338- if (metadata_read(&_metadata)) { 339+ if (metadata_read(&_metadata, 1)) { 340 ret = FWU_AGENT_ERROR; 341 goto out; 342 } 343@@ -1315,7 +1372,7 @@ void host_acknowledgement_timer_to_reset(void) 344 FWU_ASSERT(0); 345 } 346 347- if (metadata_read(&_metadata)) { 348+ if (metadata_read(&_metadata, 1)) { 349 FWU_ASSERT(0); 350 } 351 352diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h 353index 701f20558..78e104277 100644 354--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h 355+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h 356@@ -70,4 +70,11 @@ enum fwu_nv_counter_index_t { 357 enum fwu_agent_error_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index, 358 uint32_t img_security_cnt); 359 360+/* 361+ * Check if both metadata replica is valid by calculating and comparing crc32. 362+ * If one of the replica is corrupted then update it with the valid replica. 363+ * If both of the replicas are corrupted then the correction is not possible. 364+ */ 365+enum fwu_agent_error_t fwu_metadata_check_and_correct_integrity(void); 366+ 367 #endif /* FWU_AGENT_H */ 368-- 3692.25.1 370 371