1616 */
1717
1818#include " MigrationManager.h"
19+ #include " sl_component_catalog.h"
20+ #include " sl_core.h"
21+ #include < headers/ProvisionManager.h>
22+ #include < headers/ProvisionStorage.h>
23+ #include < lib/support/CodeUtils.h>
24+ #include < lib/support/ScopedBuffer.h>
25+ #include < lib/support/Span.h>
1926#include < platform/CHIPDeviceLayer.h>
2027#include < platform/silabs/SilabsConfig.h>
2128#include < stdio.h>
2229
30+ extern uint8_t linker_static_secure_tokens_begin; // Symbol defined by the linker script needed for MigrateS3Certificates
31+
2332using namespace ::chip::DeviceLayer::Internal;
2433using namespace ::chip::DeviceLayer::PersistedStorage;
2534
@@ -35,25 +44,46 @@ typedef struct
3544 func_ptr migrationFunc;
3645} migrationData_t;
3746
38- #define COUNT_OF (A ) (sizeof (A) / sizeof ((A)[0 ]))
3947static migrationData_t migrationTable[] = {
4048 { .migrationGroup = 1 , .migrationFunc = MigrateKvsMap },
4149 { .migrationGroup = 2 , .migrationFunc = MigrateDacProvider },
4250 { .migrationGroup = 3 , .migrationFunc = MigrateCounterConfigs },
4351 { .migrationGroup = 4 , .migrationFunc = MigrateHardwareVersion },
52+ { .migrationGroup = 5 , .migrationFunc = MigrateS3Certificates },
4453 // add any additional migration neccesary. migrationGroup should stay equal if done in the same commit or increment by 1 for
4554 // each new entry.
4655};
4756
4857} // namespace
4958
50- void MigrationManager::applyMigrations ()
59+ void MigrationManager::ApplyMigrations ()
5160{
61+ #ifdef SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
62+ // Suspend all other threads so they don't interfere with the migration
63+ // This is mostly targeted to the zigbee task that overwrites our certificates
64+ uint32_t threadCount = osThreadGetCount ();
65+ chip::Platform::ScopedMemoryBuffer<osThreadId_t> threadIdTable;
66+ threadIdTable.Alloc (threadCount);
67+ if (threadIdTable.Get () != nullptr )
68+ {
69+ // Forms a table of the active thread ids
70+ osThreadEnumerate (threadIdTable.Get (), threadCount);
71+ for (uint8_t tIdIndex = 0 ; tIdIndex < threadCount; tIdIndex++)
72+ {
73+ osThreadId_t tId = threadIdTable[tIdIndex];
74+ if (tId != osThreadGetId ())
75+ {
76+ osThreadSuspend (tId);
77+ }
78+ }
79+ }
80+ #endif // SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
81+
5282 uint32_t lastMigationGroupDone = 0 ;
5383 SilabsConfig::ReadConfigValue (SilabsConfig::kConfigKey_MigrationCounter , lastMigationGroupDone);
5484
5585 uint32_t completedMigrationGroup = lastMigationGroupDone;
56- for (uint32_t i = 0 ; i < COUNT_OF (migrationTable); i++)
86+ for (uint32_t i = 0 ; i < MATTER_ARRAY_SIZE (migrationTable); i++)
5787 {
5888 if (lastMigationGroupDone < migrationTable[i].migrationGroup )
5989 {
@@ -62,12 +92,27 @@ void MigrationManager::applyMigrations()
6292 }
6393 }
6494 SilabsConfig::WriteConfigValue (SilabsConfig::kConfigKey_MigrationCounter , completedMigrationGroup);
95+
96+ #ifdef SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
97+ // resume all threads
98+ if (threadIdTable.Get () != nullptr )
99+ {
100+ for (uint8_t tIdIndex = 0 ; tIdIndex < threadCount; tIdIndex++)
101+ {
102+ osThreadId_t tId = threadIdTable[tIdIndex];
103+ if (tId != osThreadGetId ())
104+ {
105+ osThreadResume (tId);
106+ }
107+ }
108+ }
109+ #endif // SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
65110}
66111
67112void MigrationManager::MigrateUint16 (uint32_t old_key, uint32_t new_key)
68113{
69114 uint16_t value = 0 ;
70- if (SilabsConfig::ConfigValueExists (old_key) && ( CHIP_NO_ERROR == SilabsConfig::ReadConfigValue (old_key, value) ))
115+ if (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue (old_key, value))
71116 {
72117 if (CHIP_NO_ERROR == SilabsConfig::WriteConfigValue (new_key, value))
73118 {
@@ -80,7 +125,7 @@ void MigrationManager::MigrateUint16(uint32_t old_key, uint32_t new_key)
80125void MigrationManager::MigrateUint32 (uint32_t old_key, uint32_t new_key)
81126{
82127 uint32_t value = 0 ;
83- if (SilabsConfig::ConfigValueExists (old_key) && ( CHIP_NO_ERROR == SilabsConfig::ReadConfigValue (old_key, value) ))
128+ if (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue (old_key, value))
84129 {
85130 if (CHIP_NO_ERROR == SilabsConfig::WriteConfigValue (new_key, value))
86131 {
@@ -132,6 +177,63 @@ void MigrateHardwareVersion(void)
132177 MigrationManager::MigrateUint16 (kOldKey_HardwareVersion , SilabsConfig::kConfigKey_HardwareVersion );
133178}
134179
180+ void MigrateS3Certificates ()
181+ {
182+ #ifdef _SILICON_LABS_32B_SERIES_3
183+ uint32_t tokenStartAddr = reinterpret_cast <uint32_t >(&linker_static_secure_tokens_begin);
184+ uint32_t secondPageAddr = tokenStartAddr + FLASH_PAGE_SIZE;
185+ uint32_t credsBaseAddr = 0 ;
186+
187+ // when credentials have been provided and stored in the first page of the static token location, we temporarely migrate them to
188+ // the second page.
189+ if (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue (SilabsConfig::kConfigKey_Creds_Base_Addr , credsBaseAddr) &&
190+ (credsBaseAddr >= tokenStartAddr && credsBaseAddr < secondPageAddr))
191+ {
192+ uint32_t cdSize = 0 ;
193+ uint32_t dacSize = 0 ;
194+ uint32_t paiSize = 0 ;
195+ Provision::Manager & provision = Provision::Manager::GetInstance ();
196+
197+ // Read the size of each credential type to determine the buffer size needed
198+ VerifyOrReturn (SilabsConfig::ReadConfigValue (SilabsConfig::kConfigKey_Creds_CD_Size , cdSize) == CHIP_NO_ERROR);
199+ VerifyOrReturn (SilabsConfig::ReadConfigValue (SilabsConfig::kConfigKey_Creds_DAC_Size , dacSize) == CHIP_NO_ERROR);
200+ VerifyOrReturn (SilabsConfig::ReadConfigValue (SilabsConfig::kConfigKey_Creds_PAI_Size , paiSize) == CHIP_NO_ERROR);
201+
202+ // Depending on existing configuration, certifications could be overlapping from the first page to the second page.
203+ // To mitigate any risk, we want to read all buffer before starting to move any of them.
204+ // allocate buffers for each certificate.
205+ // ScopedMemoryBuffer will automatically free the memory when it goes out of scope.
206+ Platform::ScopedMemoryBuffer<uint8_t > dacBuffer;
207+ Platform::ScopedMemoryBuffer<uint8_t > paiBuffer;
208+ Platform::ScopedMemoryBuffer<uint8_t > cdBuffer;
209+ dacBuffer.Alloc (dacSize);
210+ VerifyOrReturn (dacBuffer.Get () != nullptr );
211+ paiBuffer.Alloc (paiSize);
212+ VerifyOrReturn (paiBuffer.Get () != nullptr );
213+ cdBuffer.Alloc (cdSize);
214+ VerifyOrReturn (cdBuffer.Get () != nullptr );
215+
216+ MutableByteSpan dacBufferSpan (dacBuffer.Get (), dacSize);
217+ MutableByteSpan paiBufferSpan (paiBuffer.Get (), paiSize);
218+ MutableByteSpan cdBufferSpan (cdBuffer.Get (), cdSize);
219+
220+ provision.Init ();
221+ // Read All certificates are the current location
222+ VerifyOrReturn (provision.GetStorage ().GetDeviceAttestationCert (dacBufferSpan) == CHIP_NO_ERROR);
223+ VerifyOrReturn (provision.GetStorage ().GetProductAttestationIntermediateCert (paiBufferSpan) == CHIP_NO_ERROR);
224+ VerifyOrReturn (provision.GetStorage ().GetCertificationDeclaration (cdBufferSpan) == CHIP_NO_ERROR);
225+
226+ provision.GetStorage ().Initialize (0 , 0 );
227+ provision.GetStorage ().SetCredentialsBaseAddress (secondPageAddr);
228+ // Write all certs back to the second page
229+ // The first set/write, after an Initialize, erases the new page. We don't need to do it explicitly.
230+ provision.GetStorage ().SetDeviceAttestationCert (dacBufferSpan);
231+ provision.GetStorage ().SetProductAttestationIntermediateCert (paiBufferSpan);
232+ provision.GetStorage ().SetCertificationDeclaration (cdBufferSpan);
233+ }
234+ #endif // _SILICON_LABS_32B_SERIES_3
235+ }
236+
135237} // namespace Silabs
136238} // namespace DeviceLayer
137239} // namespace chip
0 commit comments