Skip to content

Commit be19fc9

Browse files
kkasperczyk-nomarkaj-nordicArekBalysNordic
authored
[nrfconnect] Introduced several improvements for the factory data management (#33195)
* [nrfconnect] Added FactoryDataBase to facilitate dynamic assignments of FactoryDataProvider concrete types to to the generic pointer. Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no> * [nrfconnect] Added non-PM based factory data support Added support for platforms not built using PM. This commit includes fixes only firmware implementation and does not include cmake changes for factory data generation. Signed-off-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no> * [nrfconnect] Improved generation of the factory data Allow to merge the factory data .hex file with the firmware's .hex file when partition manager is not available. * [nrfconnect] Disable External FD if QSPI NOR is not available We need to have support for factory data when the partition manager is enabled but there is no support for QSPI external flash. --------- Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no> Signed-off-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no> Co-authored-by: Marcin Kajor <marcin.kajor@nordicsemi.no> Co-authored-by: Arkadiusz Balys <arkadiusz.balys@nordicsemi.no>
1 parent 062e063 commit be19fc9

File tree

4 files changed

+108
-47
lines changed

4 files changed

+108
-47
lines changed

config/nrfconnect/chip-module/Kconfig

+1-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ config CHIP_MALLOC_SYS_HEAP
106106
config CHIP_FACTORY_DATA
107107
bool "Factory data provider"
108108
select ZCBOR
109-
imply FPROTECT
110109
help
111110
Enables the default nRF Connect factory data provider implementation that
112111
supports reading the factory data encoded in the CBOR format from the
@@ -149,7 +148,7 @@ config CHIP_FACTORY_DATA_WRITE_PROTECT
149148
bool "Enable Factory Data write protection"
150149
select FPROTECT
151150
depends on CHIP_FACTORY_DATA
152-
default y if CHIP_FACTORY_DATA
151+
default y
153152
help
154153
Enables the write protection of the Factory Data partition in the flash memory.
155154
This is a recommended feature, but it requires the Settings partition size to be

config/nrfconnect/chip-module/generate_factory_data.cmake

+24-7
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,21 @@ set(factory_data_output_path ${output_path}/${factory_data_target})
129129
string(APPEND script_args "-o \"${factory_data_output_path}\"\n")
130130
string(APPEND script_args "-s \"${schema_path}\"\n")
131131

132-
# Add optional offset and size arguments to generate both .hex and .json files.
133-
string(APPEND script_args "--offset $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_ADDRESS>\n")
134-
string(APPEND script_args "--size $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_OFFSET>\n")
132+
# Add optional offset and size arguments to generate .hex file as well as .json.
133+
if(CONFIG_PARTITION_MANAGER_ENABLED)
134+
string(APPEND script_args "--offset $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_ADDRESS>\n")
135+
string(APPEND script_args "--size $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_OFFSET>\n")
136+
else()
137+
dt_alias(factory_data_alias PROPERTY "factory-data")
138+
dt_node_exists(factory_data_exists PATH "${factory_data_alias}")
139+
if(NOT ${factory_data_exists})
140+
message(FATAL_ERROR "factory-data alias does not exist in DTS")
141+
endif()
142+
dt_reg_addr(factory_data_addr PATH ${factory_data_alias})
143+
dt_reg_size(factory_data_size PATH ${factory_data_alias})
144+
string(APPEND script_args "--offset ${factory_data_addr}\n")
145+
string(APPEND script_args "--size ${factory_data_size}\n")
146+
endif()
135147

136148
# execute first script to create a JSON file
137149
separate_arguments(separated_script_args NATIVE_COMMAND ${script_args})
@@ -175,10 +187,15 @@ nrfconnect_create_factory_data(factory_data
175187
${FACTORY_DATA_SCHEMA_PATH}
176188
${OUTPUT_FILE_PATH})
177189

178-
if(CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE)
179-
# set custom target for merging factory_data hex file
180-
set_property(GLOBAL PROPERTY factory_data_PM_HEX_FILE ${OUTPUT_FILE_PATH}/factory_data.hex)
181-
set_property(GLOBAL PROPERTY factory_data_PM_TARGET factory_data)
190+
if(CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE)
191+
if(CONFIG_PARTITION_MANAGER_ENABLED)
192+
# set custom target for merging factory_data hex file
193+
set_property(GLOBAL PROPERTY factory_data_PM_HEX_FILE ${OUTPUT_FILE_PATH}/factory_data.hex)
194+
set_property(GLOBAL PROPERTY factory_data_PM_TARGET factory_data)
195+
else()
196+
set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE ${OUTPUT_FILE_PATH}/factory_data.hex ${OUTPUT_FILE_PATH}/zephyr.hex)
197+
set_property(TARGET runners_yaml_props_target PROPERTY hex_file ${OUTPUT_FILE_PATH}/merged.hex)
198+
endif()
182199
endif()
183200

184201

src/platform/nrfconnect/FactoryDataProvider.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,10 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetUserKey(const char * userKe
432432

433433
// Fully instantiate the template class in whatever compilation unit includes this file.
434434
template class FactoryDataProvider<InternalFlashFactoryData>;
435+
#if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1 && (defined(CONFIG_CHIP_QSPI_NOR) || defined(CONFIG_CHIP_SPI_NOR))
435436
template class FactoryDataProvider<ExternalFlashFactoryData>;
437+
#endif // if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1 (defined(CONFIG_CHIP_QSPI_NOR) ||
438+
// defined(CONFIG_CHIP_SPI_NOR))
436439

437440
} // namespace DeviceLayer
438441
} // namespace chip

src/platform/nrfconnect/FactoryDataProvider.h

+80-38
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,20 @@
2525
#include <crypto/CHIPCryptoPALPSA.h>
2626
#endif
2727

28+
#ifdef CONFIG_FPROTECT
2829
#include <fprotect.h>
30+
#endif // if CONFIG_FPROTECT
31+
32+
#if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1
2933
#include <pm_config.h>
34+
#define FACTORY_DATA_ADDRESS PM_FACTORY_DATA_ADDRESS
35+
#define FACTORY_DATA_SIZE PM_FACTORY_DATA_SIZE
36+
#else
37+
#include <zephyr/storage/flash_map.h>
38+
#define FACTORY_DATA_SIZE DT_REG_SIZE(DT_ALIAS(factory_data))
39+
#define FACTORY_DATA_ADDRESS DT_REG_ADDR(DT_ALIAS(factory_data))
40+
#endif // if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1
41+
3042
#include <system/SystemError.h>
3143
#include <zephyr/drivers/flash.h>
3244

@@ -39,8 +51,8 @@ struct InternalFlashFactoryData
3951
{
4052
CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize)
4153
{
42-
data = reinterpret_cast<uint8_t *>(PM_FACTORY_DATA_ADDRESS);
43-
dataSize = PM_FACTORY_DATA_SIZE;
54+
data = reinterpret_cast<uint8_t *>(FACTORY_DATA_ADDRESS);
55+
dataSize = FACTORY_DATA_SIZE;
4456
return CHIP_NO_ERROR;
4557
}
4658

@@ -54,16 +66,16 @@ struct InternalFlashFactoryData
5466
// the application code at runtime anyway.
5567
constexpr size_t FactoryDataBlockBegin()
5668
{
57-
// calculate the nearest multiple of CONFIG_FPROTECT_BLOCK_SIZE smaller than PM_FACTORY_DATA_ADDRESS
58-
return PM_FACTORY_DATA_ADDRESS & (-CONFIG_FPROTECT_BLOCK_SIZE);
69+
// calculate the nearest multiple of CONFIG_FPROTECT_BLOCK_SIZE smaller than FACTORY_DATA_ADDRESS
70+
return FACTORY_DATA_ADDRESS & (-CONFIG_FPROTECT_BLOCK_SIZE);
5971
}
6072

6173
constexpr size_t FactoryDataBlockSize()
6274
{
6375
// calculate the factory data end address rounded up to the nearest multiple of CONFIG_FPROTECT_BLOCK_SIZE
6476
// and make sure we do not overlap with settings partition
6577
constexpr size_t kFactoryDataBlockEnd =
66-
(PM_FACTORY_DATA_ADDRESS + PM_FACTORY_DATA_SIZE + CONFIG_FPROTECT_BLOCK_SIZE - 1) & (-CONFIG_FPROTECT_BLOCK_SIZE);
78+
(FACTORY_DATA_ADDRESS + FACTORY_DATA_SIZE + CONFIG_FPROTECT_BLOCK_SIZE - 1) & (-CONFIG_FPROTECT_BLOCK_SIZE);
6779
static_assert(kFactoryDataBlockEnd <= PM_SETTINGS_STORAGE_ADDRESS,
6880
"FPROTECT memory block, which contains factory data"
6981
"partition overlaps with the settings partition."
@@ -75,44 +87,94 @@ struct InternalFlashFactoryData
7587
#undef TO_STR_IMPL
7688
CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite()
7789
{
90+
#ifdef CONFIG_FPROTECT
7891
int ret = fprotect_area(FactoryDataBlockBegin(), FactoryDataBlockSize());
7992
return System::MapErrorZephyr(ret);
93+
#else
94+
return CHIP_ERROR_NOT_IMPLEMENTED;
95+
#endif // if CONFIG_FPROTECT
8096
}
8197
#else
8298
CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite() { return CHIP_ERROR_NOT_IMPLEMENTED; }
8399
#endif
84100
};
85101

102+
#if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1 && (defined(CONFIG_CHIP_QSPI_NOR) || defined(CONFIG_CHIP_SPI_NOR))
86103
struct ExternalFlashFactoryData
87104
{
88105
CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize)
89106
{
90-
int ret = flash_read(mFlashDevice, PM_FACTORY_DATA_ADDRESS, mFactoryDataBuffer, PM_FACTORY_DATA_SIZE);
107+
int ret = flash_read(mFlashDevice, FACTORY_DATA_ADDRESS, mFactoryDataBuffer, FACTORY_DATA_SIZE);
91108

92109
if (ret != 0)
93110
{
94111
return CHIP_ERROR_READ_FAILED;
95112
}
96113

97114
data = mFactoryDataBuffer;
98-
dataSize = PM_FACTORY_DATA_SIZE;
115+
dataSize = FACTORY_DATA_SIZE;
99116

100117
return CHIP_NO_ERROR;
101118
}
102119

103120
CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite() { return CHIP_ERROR_NOT_IMPLEMENTED; }
104121

105-
const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
106-
uint8_t mFactoryDataBuffer[PM_FACTORY_DATA_SIZE];
122+
const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(nordic_pm_ext_flash));
123+
uint8_t mFactoryDataBuffer[FACTORY_DATA_SIZE];
124+
};
125+
#endif // if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1 && (defined(CONFIG_CHIP_QSPI_NOR) ||
126+
// defined(CONFIG_CHIP_SPI_NOR))
127+
128+
class FactoryDataProviderBase : public chip::Credentials::DeviceAttestationCredentialsProvider,
129+
public CommissionableDataProvider,
130+
public DeviceInstanceInfoProvider
131+
{
132+
public:
133+
/**
134+
* @brief Perform all operations needed to initialize factory data provider.
135+
*
136+
* @returns CHIP_NO_ERROR in case of a success, specific error code otherwise
137+
*/
138+
virtual CHIP_ERROR Init() = 0;
139+
140+
/**
141+
* @brief Get the EnableKey as MutableByteSpan
142+
*
143+
* @param enableKey MutableByteSpan object to obtain EnableKey
144+
* @returns
145+
* CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if factory data does not contain enable_key field, or the value cannot be read
146+
* out. CHIP_ERROR_BUFFER_TOO_SMALL if provided MutableByteSpan is too small
147+
*/
148+
virtual CHIP_ERROR GetEnableKey(MutableByteSpan & enableKey) = 0;
149+
150+
/**
151+
* @brief Get the user data in CBOR format as MutableByteSpan
152+
*
153+
* @param userData MutableByteSpan object to obtain all user data in CBOR format
154+
* @returns
155+
* CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if factory data does not contain user field, or the value cannot be read out.
156+
* CHIP_ERROR_BUFFER_TOO_SMALL if provided MutableByteSpan is too small
157+
*/
158+
virtual CHIP_ERROR GetUserData(MutableByteSpan & userData) = 0;
159+
160+
/**
161+
* @brief Try to find user data key and return its value
162+
*
163+
* @param userKey A key name to be found
164+
* @param buf Buffer to store value of found key
165+
* @param len Length of the buffer. This value will be updated to the actual value if the key is read.
166+
* @returns
167+
* CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if factory data does not contain user key field, or the value cannot be read
168+
* out. CHIP_ERROR_BUFFER_TOO_SMALL if provided buffer length is too small
169+
*/
170+
virtual CHIP_ERROR GetUserKey(const char * userKey, void * buf, size_t & len) = 0;
107171
};
108172

109173
template <class FlashFactoryData>
110-
class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentialsProvider,
111-
public CommissionableDataProvider,
112-
public DeviceInstanceInfoProvider
174+
class FactoryDataProvider : public FactoryDataProviderBase
113175
{
114176
public:
115-
CHIP_ERROR Init();
177+
CHIP_ERROR Init() override;
116178

117179
// ===== Members functions that implement the DeviceAttestationCredentialsProvider
118180
CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override;
@@ -147,33 +209,13 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia
147209
CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;
148210

149211
// ===== Members functions that are platform-specific
150-
CHIP_ERROR GetEnableKey(MutableByteSpan & enableKey);
151-
152-
/**
153-
* @brief Get the user data in CBOR format as MutableByteSpan
154-
*
155-
* @param userData MutableByteSpan object to obtain all user data in CBOR format
156-
* @returns
157-
* CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if factory data does not contain user field, or the value cannot be read out.
158-
* CHIP_ERROR_BUFFER_TOO_SMALL if provided MutableByteSpan is too small
159-
*/
160-
CHIP_ERROR GetUserData(MutableByteSpan & userData);
161-
162-
/**
163-
* @brief Try to find user data key and return its value
164-
*
165-
* @param userKey A key name to be found
166-
* @param buf Buffer to store value of found key
167-
* @param len Length of the buffer. This value will be updated to the actual value if the key is read.
168-
* @returns
169-
* CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if factory data does not contain user field, or the value cannot be read out.
170-
* CHIP_ERROR_BUFFER_TOO_SMALL if provided buffer length is too small
171-
*/
172-
CHIP_ERROR GetUserKey(const char * userKey, void * buf, size_t & len);
212+
CHIP_ERROR GetEnableKey(MutableByteSpan & enableKey) override;
213+
CHIP_ERROR GetUserData(MutableByteSpan & userData) override;
214+
CHIP_ERROR GetUserKey(const char * userKey, void * buf, size_t & len) override;
173215

174216
private:
175-
static constexpr uint16_t kFactoryDataPartitionSize = PM_FACTORY_DATA_SIZE;
176-
static constexpr uint32_t kFactoryDataPartitionAddress = PM_FACTORY_DATA_ADDRESS;
217+
static constexpr uint16_t kFactoryDataPartitionSize = FACTORY_DATA_SIZE;
218+
static constexpr uint32_t kFactoryDataPartitionAddress = FACTORY_DATA_ADDRESS;
177219
static constexpr uint8_t kDACPrivateKeyLength = 32;
178220
static constexpr uint8_t kDACPublicKeyLength = 65;
179221

0 commit comments

Comments
 (0)