Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrfconnect] Improved generation of factory data #423

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions config/nrfconnect/chip-module/Kconfig
Original file line number Diff line number Diff line change
@@ -106,7 +106,6 @@ config CHIP_MALLOC_SYS_HEAP
config CHIP_FACTORY_DATA
bool "Factory data provider"
select ZCBOR
imply FPROTECT
help
Enables the default nRF Connect factory data provider implementation that
supports reading the factory data encoded in the CBOR format from the
@@ -149,7 +148,7 @@ config CHIP_FACTORY_DATA_WRITE_PROTECT
bool "Enable Factory Data write protection"
select FPROTECT
depends on CHIP_FACTORY_DATA
default y if CHIP_FACTORY_DATA
default y
help
Enables the write protection of the Factory Data partition in the flash memory.
This is a recommended feature, but it requires the Settings partition size to be
31 changes: 24 additions & 7 deletions config/nrfconnect/chip-module/generate_factory_data.cmake
Original file line number Diff line number Diff line change
@@ -129,9 +129,21 @@ set(factory_data_output_path ${output_path}/${factory_data_target})
string(APPEND script_args "-o \"${factory_data_output_path}\"\n")
string(APPEND script_args "-s \"${schema_path}\"\n")

# Add optional offset and size arguments to generate both .hex and .json files.
string(APPEND script_args "--offset $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_ADDRESS>\n")
string(APPEND script_args "--size $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_OFFSET>\n")
# Add optional offset and size arguments to generate .hex file as well as .json.
if(CONFIG_PARTITION_MANAGER_ENABLED)
string(APPEND script_args "--offset $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_ADDRESS>\n")
string(APPEND script_args "--size $<TARGET_PROPERTY:partition_manager,PM_FACTORY_DATA_OFFSET>\n")
else()
dt_alias(factory_data_alias PROPERTY "factory-data")
dt_node_exists(factory_data_exists PATH "${factory_data_alias}")
if(NOT ${factory_data_exists})
message(FATAL_ERROR "factory-data alias does not exist in DTS")
endif()
dt_reg_addr(factory_data_addr PATH ${factory_data_alias})
dt_reg_size(factory_data_size PATH ${factory_data_alias})
string(APPEND script_args "--offset ${factory_data_addr}\n")
string(APPEND script_args "--size ${factory_data_size}\n")
endif()

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

if(CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE)
# set custom target for merging factory_data hex file
set_property(GLOBAL PROPERTY factory_data_PM_HEX_FILE ${OUTPUT_FILE_PATH}/factory_data.hex)
set_property(GLOBAL PROPERTY factory_data_PM_TARGET factory_data)
if(CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE)
if(CONFIG_PARTITION_MANAGER_ENABLED)
# set custom target for merging factory_data hex file
set_property(GLOBAL PROPERTY factory_data_PM_HEX_FILE ${OUTPUT_FILE_PATH}/factory_data.hex)
set_property(GLOBAL PROPERTY factory_data_PM_TARGET factory_data)
else()
set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE ${OUTPUT_FILE_PATH}/factory_data.hex ${OUTPUT_FILE_PATH}/zephyr.hex)
set_property(TARGET runners_yaml_props_target PROPERTY hex_file ${OUTPUT_FILE_PATH}/merged.hex)
endif()
endif()


4 changes: 2 additions & 2 deletions docs/guides/nrfconnect_factory_data_configuration.md
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ data secure by applying hardware write protection.
- [Appearance field description](#appearance-field-description)
- [Enabling factory data support](#enabling-factory-data-support)
- [Generating factory data](#generating-factory-data)
- [Creating the factory data JSON file with the first script](#creating-the-factory-data-json-file-with-the-first-script)
- [Creating the factory data JSON and HEX files with the first script](#creating-the-factory-data-json-and-hex-files-with-the-first-script)
- [How to set user data](#how-to-set-user-data)
- [How to handle user data](#how-to-handle-user-data)
- [Verifying using the JSON Schema tool](#verifying-using-the-json-schema-tool)
@@ -597,7 +597,7 @@ To generate a manual pairing code and a QR code, complete the following steps:
```

2. Complete steps 1, 2, and 3 from the
[Creating the factory data JSON file with the first script](#creating-the-factory-data-json-file-with-the-first-script)
[Creating the factory data JSON and HEX files with the first script](#creating-the-factory-data-json-and-hex-files-with-the-first-script)
section to prepare the final invocation of the Python script.

3. Add the `--generate_onboarding` argument to the Python script final
2 changes: 2 additions & 0 deletions src/platform/nrfconnect/FactoryDataProvider.cpp
Original file line number Diff line number Diff line change
@@ -509,7 +509,9 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetUserKey(const char * userKe

// Fully instantiate the template class in whatever compilation unit includes this file.
template class FactoryDataProvider<InternalFlashFactoryData>;
#if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1
template class FactoryDataProvider<ExternalFlashFactoryData>;
#endif // if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1

} // namespace DeviceLayer
} // namespace chip
40 changes: 29 additions & 11 deletions src/platform/nrfconnect/FactoryDataProvider.h
Original file line number Diff line number Diff line change
@@ -25,8 +25,20 @@
#include <crypto/CHIPCryptoPALPSA.h>
#endif

#ifdef CONFIG_FPROTECT
#include <fprotect.h>
#endif // if CONFIG_FPROTECT

#if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1
#include <pm_config.h>
#define FACTORY_DATA_ADDRESS PM_FACTORY_DATA_ADDRESS
#define FACTORY_DATA_SIZE PM_FACTORY_DATA_SIZE
#else
#include <zephyr/storage/flash_map.h>
#define FACTORY_DATA_SIZE DT_REG_SIZE(DT_ALIAS(factory_data))
#define FACTORY_DATA_ADDRESS DT_REG_ADDR(DT_ALIAS(factory_data))
#endif // if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1

#include <system/SystemError.h>
#include <zephyr/drivers/flash.h>

@@ -39,8 +51,8 @@ struct InternalFlashFactoryData
{
CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize)
{
data = reinterpret_cast<uint8_t *>(PM_FACTORY_DATA_ADDRESS);
dataSize = PM_FACTORY_DATA_SIZE;
data = reinterpret_cast<uint8_t *>(FACTORY_DATA_ADDRESS);
dataSize = FACTORY_DATA_SIZE;
return CHIP_NO_ERROR;
}

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

constexpr size_t FactoryDataBlockSize()
{
// calculate the factory data end address rounded up to the nearest multiple of CONFIG_FPROTECT_BLOCK_SIZE
// and make sure we do not overlap with settings partition
constexpr size_t kFactoryDataBlockEnd =
(PM_FACTORY_DATA_ADDRESS + PM_FACTORY_DATA_SIZE + CONFIG_FPROTECT_BLOCK_SIZE - 1) & (-CONFIG_FPROTECT_BLOCK_SIZE);
(FACTORY_DATA_ADDRESS + FACTORY_DATA_SIZE + CONFIG_FPROTECT_BLOCK_SIZE - 1) & (-CONFIG_FPROTECT_BLOCK_SIZE);
static_assert(kFactoryDataBlockEnd <= PM_SETTINGS_STORAGE_ADDRESS,
"FPROTECT memory block, which contains factory data"
"partition overlaps with the settings partition."
@@ -75,36 +87,42 @@ struct InternalFlashFactoryData
#undef TO_STR_IMPL
CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite()
{
#ifdef CONFIG_FPROTECT
int ret = fprotect_area(FactoryDataBlockBegin(), FactoryDataBlockSize());
return System::MapErrorZephyr(ret);
#else
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif // if CONFIG_FPROTECT
}
#else
CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite() { return CHIP_ERROR_NOT_IMPLEMENTED; }
#endif
};

#if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1
struct ExternalFlashFactoryData
{
CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize)
{
int ret = flash_read(mFlashDevice, PM_FACTORY_DATA_ADDRESS, mFactoryDataBuffer, PM_FACTORY_DATA_SIZE);
int ret = flash_read(mFlashDevice, FACTORY_DATA_ADDRESS, mFactoryDataBuffer, FACTORY_DATA_SIZE);

if (ret != 0)
{
return CHIP_ERROR_READ_FAILED;
}

data = mFactoryDataBuffer;
dataSize = PM_FACTORY_DATA_SIZE;
dataSize = FACTORY_DATA_SIZE;

return CHIP_NO_ERROR;
}

CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite() { return CHIP_ERROR_NOT_IMPLEMENTED; }

const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
uint8_t mFactoryDataBuffer[PM_FACTORY_DATA_SIZE];
const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(nordic_pm_ext_flash));
uint8_t mFactoryDataBuffer[FACTORY_DATA_SIZE];
};
#endif // if defined(USE_PARTITION_MANAGER) && USE_PARTITION_MANAGER == 1

class FactoryDataProviderBase : public chip::Credentials::DeviceAttestationCredentialsProvider,
public CommissionableDataProvider,
@@ -198,8 +216,8 @@ class FactoryDataProvider : public FactoryDataProviderBase
CHIP_ERROR GetUserKey(const char * userKey, void * buf, size_t & len) override;

private:
static constexpr uint16_t kFactoryDataPartitionSize = PM_FACTORY_DATA_SIZE;
static constexpr uint32_t kFactoryDataPartitionAddress = PM_FACTORY_DATA_ADDRESS;
static constexpr uint16_t kFactoryDataPartitionSize = FACTORY_DATA_SIZE;
static constexpr uint32_t kFactoryDataPartitionAddress = FACTORY_DATA_ADDRESS;
static constexpr uint8_t kDACPrivateKeyLength = 32;
static constexpr uint8_t kDACPublicKeyLength = 65;

Loading