diff --git a/config/nrfconnect/chip-module/generate_factory_data.cmake b/config/nrfconnect/chip-module/generate_factory_data.cmake index 3c286fc21dddee..21f7360cd03f10 100644 --- a/config/nrfconnect/chip-module/generate_factory_data.cmake +++ b/config/nrfconnect/chip-module/generate_factory_data.cmake @@ -15,25 +15,29 @@ # -# Create a JSON file based on factory data given via kConfigs. +# Create a .hex file in CBOR format based on factory data given via kConfigs. # # This function creates a list of arguments for external script and then run it to write a JSON file. # Created JSON file can be checked using JSON SCHEMA file if it is provided. +# Next, the resulting .hex file is generated based on previously created JSON file. # # This script can be manipulated using following kConfigs: # - To merge generated factory data with final zephyr.hex file set kConfig CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y # - To use default certification paths set CONFIG_CHIP_FACTORY_DATA_USE_DEFAULTS_CERTS_PATH=y # -# During generation process a some file will be created in zephyr's build directory: +# During generation process the following files will be created in zephyr's build directory: # - .json a file containing all factory data written in JSON format. +# - .hex a file containing all factory data in CBOR format. +# - .bin a binary file containing all raw factory data in CBOR format. +# - .cbor a file containing all factory data in CBOR format. # # [Args]: # factory_data_target - a name for target to generate factory_data. # script_path - a path to script that makes a JSON factory data file from given arguments. # schema_path - a path to JSON schema file which can be used to verify generated factory data JSON file. # This argument is optional, if you don't want to verify the JSON file put it empty "". -# output_path - a path to output directory, where created JSON file will be stored. -function(nrfconnect_create_factory_data_json factory_data_target script_path schema_path output_path) +# output_path - a path to output directory, where created hex and JSON files will be stored. +function(nrfconnect_create_factory_data factory_data_target script_path schema_path output_path) # set script args for future purpose set(script_args) @@ -120,62 +124,25 @@ if(CONFIG_CHIP_DEVICE_ENABLE_KEY) string(APPEND script_args "--enable_key \"${CONFIG_CHIP_DEVICE_ENABLE_KEY}\"\n") endif() -# Set output JSON file and path to SCHEMA file to validate generated factory data -set(factory_data_json ${output_path}/${factory_data_target}.json) -string(APPEND script_args "-o \"${factory_data_json}\"\n") +# Set output path and path to SCHEMA file to validate generated factory data +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 $\n") +string(APPEND script_args "--size $\n") + # execute first script to create a JSON file separate_arguments(separated_script_args NATIVE_COMMAND ${script_args}) add_custom_command( - OUTPUT ${factory_data_json} + OUTPUT ${factory_data_output_path}.hex DEPENDS ${FACTORY_DATA_SCRIPT_PATH} COMMAND ${Python3_EXECUTABLE} ${FACTORY_DATA_SCRIPT_PATH} ${separated_script_args} COMMENT "Generating new Factory Data..." ) add_custom_target(${factory_data_target} ALL - DEPENDS ${factory_data_json} - ) - -endfunction() - - -# Create a .hex file with factory data in CBOR format. -# -# This function creates a .hex and .cbor files from given JSON factory data file. -# -# -# During generation process some files will be created in zephyr's build directory: -# - .hex a file containing all factory data in CBOR format. -# - .bin a binary file containing all raw factory data in CBOR format. -# - .cbor a file containing all factory data in CBOR format. -# -# [Args]: -# factory_data_hex_target - a name for target to generate factory data HEX file. -# factory_data_target - a name for target to generate factory data JSON file. -# script_path - a path to script that makes a factory data .hex file from given arguments. -# output_path - a path to output directory, where created JSON file will be stored. -function(nrfconnect_create_factory_data_hex_file factory_data_hex_target factory_data_target script_path output_path) - -# Pass the argument list via file -set(cbor_script_args "-i ${output_path}/${factory_data_target}.json\n") -string(APPEND cbor_script_args "-o ${output_path}/${factory_data_target}\n") -# get partition address and offset from partition manager during compilation -string(APPEND cbor_script_args "--offset $\n") -string(APPEND cbor_script_args "--size $\n") -string(APPEND cbor_script_args "-r\n") - -# execute second script to create a hex file containing factory data in cbor format -separate_arguments(separated_cbor_script_args NATIVE_COMMAND ${cbor_script_args}) -set(factory_data_hex ${output_path}/${factory_data_target}.hex) - -add_custom_command(OUTPUT ${factory_data_hex} - COMMAND ${Python3_EXECUTABLE} ${script_path} ${separated_cbor_script_args} - COMMENT "Generating factory data HEX file..." - DEPENDS ${factory_data_target} ${script_path} - ) -add_custom_target(${factory_data_hex_target} - DEPENDS ${factory_data_hex} + DEPENDS ${factory_data_output_path}.hex ) endfunction() @@ -202,22 +169,16 @@ set(GENERATE_CBOR_SCRIPT_PATH ${CHIP_ROOT}/scripts/tools/nrfconnect/nrfconnect_g set(FACTORY_DATA_SCHEMA_PATH ${CHIP_ROOT}/scripts/tools/nrfconnect/nrfconnect_factory_data.schema) set(OUTPUT_FILE_PATH ${APPLICATION_BINARY_DIR}/zephyr) -# create a JSON file with all factory data -nrfconnect_create_factory_data_json(factory_data - ${FACTORY_DATA_SCRIPT_PATH} - ${FACTORY_DATA_SCHEMA_PATH} - ${OUTPUT_FILE_PATH}) - # create a .hex file with factory data in CBOR format based on the JSON file created previously -nrfconnect_create_factory_data_hex_file(factory_data_hex - factory_data - ${GENERATE_CBOR_SCRIPT_PATH} - ${OUTPUT_FILE_PATH}) +nrfconnect_create_factory_data(factory_data + ${FACTORY_DATA_SCRIPT_PATH} + ${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_hex) + set_property(GLOBAL PROPERTY factory_data_PM_TARGET factory_data) endif() diff --git a/docs/guides/nrfconnect_factory_data_configuration.md b/docs/guides/nrfconnect_factory_data_configuration.md index e4c3be4899df4e..35a34fe709d622 100644 --- a/docs/guides/nrfconnect_factory_data_configuration.md +++ b/docs/guides/nrfconnect_factory_data_configuration.md @@ -30,30 +30,30 @@ data secure by applying hardware write protection.
-- [Configuring factory data for the nRF Connect examples](#configuring-factory-data-for-the-nrf-connect-examples) - - [Overview](#overview) - - [Factory data component table](#factory-data-component-table) - - [Factory data format](#factory-data-format) - - [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) - - [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) - - [Option 1: Using the php-json-schema tool](#option-1-using-the-php-json-schema-tool) - - [Option 2: Using a website validator](#option-2-using-a-website-validator) - - [Option 3: Using the nRF Connect Python script](#option-3-using-the-nrf-connect-python-script) - - [Generating onboarding codes](#generating-onboarding-codes) - - [Enabling onboarding codes generation within the build system](#enabling-onboarding-codes-generation-within-the-build-system) - - [Preparing factory data partition on a device](#preparing-factory-data-partition-on-a-device) - - [Creating a factory data partition with the second script](#creating-a-factory-data-partition-with-the-second-script) - - [Building an example with factory data](#building-an-example-with-factory-data) - - [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list) - - [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces) - - [Default Kconfig values and developing aspects](#default-kconfig-values-and-developing-aspects) - - [Programming factory data](#programming-factory-data) - - [Using own factory data implementation](#using-own-factory-data-implementation) +- [Configuring factory data for the nRF Connect examples](#configuring-factory-data-for-the-nrf-connect-examples) + - [Overview](#overview) + - [Factory data component table](#factory-data-component-table) + - [Factory data format](#factory-data-format) + - [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) + - [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) + - [Option 1: Using the php-json-schema tool](#option-1-using-the-php-json-schema-tool) + - [Option 2: Using a website validator](#option-2-using-a-website-validator) + - [Option 3: Using the nRF Connect Python script](#option-3-using-the-nrf-connect-python-script) + - [Generating onboarding codes](#generating-onboarding-codes) + - [Enabling onboarding codes generation within the build system](#enabling-onboarding-codes-generation-within-the-build-system) + - [Preparing factory data partition on a device](#preparing-factory-data-partition-on-a-device) + - [Creating a factory data partition with the second script](#creating-a-factory-data-partition-with-the-second-script) + - [Building an example with factory data](#building-an-example-with-factory-data) + - [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list) + - [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces) + - [Default Kconfig values and developing aspects](#default-kconfig-values-and-developing-aspects) + - [Programming factory data](#programming-factory-data) + - [Using own factory data implementation](#using-own-factory-data-implementation)
@@ -78,7 +78,7 @@ data stored in the device's flash memory is provided in the CBOR format. However, it is possible to generate the factory data set without using the nRF Connect scripts and implement another parser and a factory data accessor. This is possible if the newly provided implementation is consistent with the -[Factory Data Provider](../../src/platform/nrfconnect/FactoryDataProvider.h). +[Factory Data Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/nrfconnect/FactoryDataProvider.h). For more information about preparing a factory data accessor, see the section about [using own factory data implementation](#using-own-factory-data-implementation). @@ -218,14 +218,19 @@ file written in another way. To make sure that the JSON file is correct and the device is able to read out parameters, [verify the file using the JSON schema tool](#verifying-using-the-json-schema-tool). -### Creating the factory data JSON file with the first script +You can also use only the first script to generate both JSON and HEX files, by providing +optional `offset` and `size` arguments, which results in invoking the script internally. +Such option is the recommended one, but invoking two scripts one by one is also supported +to provide backward compatibility. + +### Creating the factory data JSON and HEX files with the first script A Matter device needs a proper factory data partition stored in the flash memory to read out all required parameters during startup. To simplify the factory data generation, you can use the -[generate_nrfconnect_chip_factory_data.py](../../scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py) +[generate_nrfconnect_chip_factory_data.py](https://github.com/project-chip/connectedhomeip/blob/master/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py) Python script to provide all required parameters and generate a human-readable -JSON file. +JSON file and save it to a HEX file. To use this script, complete the following steps: @@ -245,10 +250,10 @@ To use this script, complete the following steps: --sn --vendor_id, --product_id, --vendor_name, --product_name, --date, --hw_ver, --hw_ver_str, --spake2_it, --spake2_salt, --discriminator ``` - b. Add output file path: + b. Add output path to store .json file, e.g. my_dir/output: ``` - -o + -o ``` c. Generate SPAKE2 verifier using one of the following methods: @@ -337,9 +342,29 @@ To use this script, complete the following steps: --gen_cd ``` - > **Note:** To generate new Certification Declaration, you need the - > `chip-cert` executable. See the note at the end of this section to learn - > how to get it. + > **Note:** To generate new Certification Declaration, you need the `chip-cert` + > executable. See the note at the end of this section to learn how to get + > it. + + k. (optional) Partition offset that is an address in device's NVM memory, where factory data will be stored. + + ``` + --offset + ``` + + > **Note:** To generate a HEX file with factory data, you need to provide both `offset` and `size` optional arguments. + > As a result, `factory_data.hex` and `factory_data.bin` files are created in the `output` directory. The first file contains the required memory offset. + > For this reason, it can be programmed directly to the device using a programmer (for example, `nrfjprog`). + + l. (optional) The maximum partition size in device's NVM memory, where factory data will be stored. + + ``` + --size + ``` + + > **Note:** To generate a HEX file with factory data, you need to provide both `offset` and `size` optional arguments. + > As a result, `factory_data.hex` and `factory_data.bin` files are created in the `output` directory. The first file contains the required memory offset. + > For this reason, it can be programmed directly to the device using a programmer (for example, `nrfjprog`). 4. Run the script using the prepared list of arguments: @@ -370,8 +395,10 @@ $ python scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py \ --passcode 20202021 \ --product_finish "matte" \ --product_color "black" \ ---out "build.json" \ ---schema "scripts/tools/nrfconnect/nrfconnect_factory_data.schema" +--out "build" \ +--schema "scripts/tools/nrfconnect/nrfconnect_factory_data.schema" \ +--offset 0xf7000 \ +--size 0x1000 ``` As the result of the above example, a unique ID for the rotating device ID is @@ -618,7 +645,7 @@ multiple of one flash page (for nRF52 and nRF53 SoCs, a single page size equals See the following code snippet for an example of a factory data partition in the `pm_static.yml` file. The snippet is based on the `pm_static.yml` file from the -[Lock application example](../../examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml) +[Lock application example](https://github.com/project-chip/connectedhomeip/blob/master/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml) and uses the nRF52840 DK: ``` @@ -686,10 +713,13 @@ The output will look similar to the following one: ### Creating a factory data partition with the second script To store the factory data set in the device's persistent storage, convert the -data from the JSON file to its binary representation in the CBOR format. To do -this, use the -[nrfconnect_generate_partition.py](../../scripts/tools/nrfconnect/nrfconnect_generate_partition.py) -to generate the factory data partition: +data from the JSON file to its binary representation in the CBOR format. This is +done by the [generate_nrfconnect_chip_factory_data.py](../../scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py), +if you provide optional `offset` and `size` arguments. If you provided these arguments, skip the following steps of this section. + +You can skip these optional arguments and do this, using the +[nrfconnect_generate_partition.py](https://github.com/project-chip/connectedhomeip/blob/master/scripts/tools/nrfconnect/nrfconnect_generate_partition.py) +script, but this is obsolete solution kept only for backward compatibility: 1. Navigate to the _connectedhomeip_ root directory 2. Run the following command pattern: @@ -750,7 +780,7 @@ Alternatively, you can also add `CONFIG_CHIP_FACTORY_DATA_BUILD=y` Kconfig setting to the example's `prj.conf` file. Each factory data parameter has a default value. These are described in the -[Kconfig file](../../config/nrfconnect/chip-module/Kconfig). Setting a new value +[Kconfig file](https://github.com/project-chip/connectedhomeip/blob/master/config/nrfconnect/chip-module/Kconfig). Setting a new value for the factory data parameter can be done either by providing it as a build argument list or by using interactive Kconfig interfaces. @@ -773,7 +803,7 @@ Alternatively, you can add the relevant Kconfig option lines to the example's You can edit all configuration options using the interactive Kconfig interface. See the -[Configuring nRF Connect examples](../guides/nrfconnect_examples_configuration.md) +[Configuring nRF Connect examples](./nrfconnect_examples_configuration.md) page for information about how to configure Kconfig options. In the configuration window, expand the items @@ -809,52 +839,35 @@ snippet: ### Default Kconfig values and developing aspects -Each factory data parameter has its default value reflected in the Kconfig. The -list below shows some Kconfig settings that are configured in the nRF Connect -build system and have an impact on the application. You can modify them to -achieve the desired behavior of your application. - -- The device uses the test certificates located in the - `credentials/development/attestation/` directory, which are generated using - all default values. If you want to change the default `vendor_id`, - `product_id`, `vendor_name`, or `device_name` and generate new test - certificates, add the `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED=y` - Kconfig option. Remember to build the `chip-cert` application and add it to - the system PATH. - - For developing a production-ready product, you need to write the - certificates obtained during the certification process. To do this, add the - `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER=y` Kconfig option and set the - appropriate paths for the following Kconfig options: - - - `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT` - - `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY` - - `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT` - -- By default, the SPAKE2+ verifier is generated during each example's build. - This means that this value will change automatically if you change any of - the following parameters: - - - `CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE` - - `CONFIG_CHIP_DEVICE_SPAKE2_SALT` - - `CONFIG_CHIP_DEVICE_SPAKE2_IT` - - You can disable the generation of the SPAKE2+ verifier by setting the - `CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER=n` Kconfig option. Then, - you will need to provide the externally-generated SPAKE2+ verifier using the - `CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER` Kconfig value. - -- Generating the rotating device ID unique ID is disabled by default, but you - can enable it by setting the `CONFIG_CHIP_ROTATING_DEVICE_ID=y` and - `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y` Kconfig values. - Moreover, if you set the `CONFIG_CHIP_ROTATING_DEVICE_ID` Kconfig option to - `y` and disable the `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID` - Kconfig option, you will need to provide it manually using the - `CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID` Kconfig value. - -- You can generate the test Certification Declaration by using the - `CONFIG_CHIP_FACTORY_DATA_GENERATE_CD=y` Kconfig option. Remember to build - the `chip-cert` application and add it to the system PATH. +Each factory data parameter has its default value reflected in the Kconfig. +The list below shows some Kconfig settings that are configured in the nRF Connect build system and have an impact on the application. +You can modify them to achieve the desired behavior of your application. + +* The device uses the test certificates located in the `credentials/development/attestation/` directory, which are generated using all default values. + If you want to change the default `vendor_id`, `product_id`, `vendor_name`, or `device_name` and generate new test certificates, add the `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED=y` Kconfig option. + Remember to build the `chip-cert` application and add it to the system PATH. + + For developing a production-ready product, you need to write the certificates obtained during the certification process. + To do this, add the `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER=y` Kconfig option and set the appropriate paths for the following Kconfig options: + + * `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT` + * `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY` + * `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT` + +* By default, the SPAKE2+ verifier is generated during each example's build. This means that this value will change automatically if you change any of the following parameters: + + * `CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE` + * `CONFIG_CHIP_DEVICE_SPAKE2_SALT` + * `CONFIG_CHIP_DEVICE_SPAKE2_IT` + + You can disable the generation of the SPAKE2+ verifier by setting the `CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER=n` Kconfig option. + Then, you will need to provide the externally-generated SPAKE2+ verifier using the `CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER` Kconfig value. + +* Generating the rotating device ID unique ID is disabled by default, but you can enable it by setting the `CONFIG_CHIP_ROTATING_DEVICE_ID=y` and `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y` Kconfig values. + Moreover, if you set the `CONFIG_CHIP_ROTATING_DEVICE_ID` Kconfig option to `y` and disable the `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID` Kconfig option, you will need to provide it manually using the `CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID` Kconfig value. + +* You can generate the test Certification Declaration by using the `CONFIG_CHIP_FACTORY_DATA_GENERATE_CD=y` Kconfig option. + Remember to build the `chip-cert` application and add it to the system PATH.
@@ -924,22 +937,21 @@ $ west flash ## Using own factory data implementation The [factory data generation process](#generating-factory-data) described above -is only an example valid for the nRF Connect platform. You can also create a HEX -file containing all components from the -[factory data component table](#factory-data-component-table) in any format and -then implement a parser to read out all parameters and pass them to a provider. -Each manufacturer can implement a factory data set on its own by implementing a -parser and a factory data accessor inside the Matter stack. Use the -[nRF Connect Provider](../../src/platform/nrfconnect/FactoryDataProvider.h) and -[FactoryDataParser](../../src/platform/nrfconnect/FactoryDataParser.h) as +is only an example valid for the nRF Connect platform. You can well create a HEX +file containing all [factory data components](#factory-data-component-table) in +any format and then implement a parser to read out all parameters and pass them +to a provider. Each manufacturer can implement a factory data set on its own by +implementing a parser and a factory data accessor inside the Matter stack. Use +the [nRF Connect Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/nrfconnect/FactoryDataProvider.h) +and [FactoryDataParser](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/nrfconnect/FactoryDataParser.h) as examples. You can read the factory data set from the device's flash memory in different ways, depending on the purpose and the format. In the nRF Connect example, the factory data is stored in the CBOR format. The device uses the -[Factory Data Parser](../../src/platform/nrfconnect/FactoryDataParser.h) to read +[Factory Data Parser](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/nrfconnect/FactoryDataParser.h) to read out raw data, decode it, and store it in the `FactoryData` structure. The -[Factor Data Provider](../../src/platform/nrfconnect/FactoryDataProvider.cpp) +[Factor Data Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/nrfconnect/FactoryDataProvider.c) implementation uses this parser to get all needed factory data parameters and provide them to the Matter core. diff --git a/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py b/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py index 724484058029d1..7ecd2b71e3fe34 100644 --- a/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py +++ b/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py @@ -28,6 +28,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import load_der_private_key +from nrfconnect_generate_partition import PartitionCreator try: import qrcode @@ -228,6 +229,10 @@ def __init__(self, arguments) -> None: self._factory_data = list() self._user_data = dict() + # If .json extension is included in the output path, remove it, as script adds it automatically. + if self._args.output.endswith(".json"): + self._args.output = self._args.output[:-len(".json")] + try: self._validate_args() except AssertionError as e: @@ -244,9 +249,7 @@ def _validate_args(self): "Cannot find Spake2+ verifier, to generate a new one please provide passcode (--passcode)" assert ((self._args.gen_certs and self._args.chip_cert_path) or (self._args.dac_cert and self._args.pai_cert and self._args.dac_key)), \ "Cannot find paths to DAC or PAI certificates .der files. To generate a new ones please provide a path to chip-cert executable (--chip_cert_path) and add --gen_certs argument" - assert self._args.output.endswith(".json"), \ - "Output path doesn't contain .json file path. ({})".format(self._args.output) - assert self._args.passcode not in INVALID_PASSCODES, \ + assert not (self._args.passcode in INVALID_PASSCODES), \ "Provided invalid passcode!" def generate_json(self): @@ -310,9 +313,9 @@ def generate_json(self): sys.exit(-1) try: - json_file = open(self._args.output, "w+") + json_file = open(self._args.output+".json", "w+") except FileNotFoundError: - print("Cannot create JSON file in this location: {}".format(self._args.output)) + print("Cannot create JSON file in this location: {}".format(self._args.output+".json")) sys.exit(-1) with json_file: # serialize data @@ -422,11 +425,11 @@ def _generate_onboarding_data(self): flow=CommissioningFlow.Standard, vid=self._args.vendor_id, pid=self._args.product_id) - with open(self._args.output[:-len(".json")] + ".txt", "w") as manual_code_file: + with open(self._args.output + ".txt", "w") as manual_code_file: manual_code_file.write("Manualcode : " + setup_payload.generate_manualcode() + "\n") manual_code_file.write("QRCode : " + setup_payload.generate_qrcode()) qr = qrcode.make(setup_payload.generate_qrcode()) - qr.save(self._args.output[:-len(".json")] + ".png") + qr.save(self._args.output + ".png") def main(): @@ -441,7 +444,10 @@ def base64_str(s): return base64.b64decode(s) parser.add_argument("-s", "--schema", type=str, help="JSON schema file to validate JSON output data") parser.add_argument("-o", "--output", type=str, required=True, - help="Output path to store .json file, e.g. my_dir/output.json") + help="Output path to store .json file, e.g. my_dir/output." + "The .json extension will be automatically added by the script and does not need to be provided." + "If provided, an extension will not be added." + "If optional --size and --offset arguments are provided, the script also generates .hex file with factory data.") parser.add_argument("-v", "--verbose", action="store_true", help="Run this script with DEBUG logging level") parser.add_argument("--include_passcode", action="store_true", @@ -543,6 +549,10 @@ def base64_str(s): return base64.b64decode(s) help="[string] Provide one of the product finishes") optional_arguments.add_argument("--product_color", type=str, choices=PRODUCT_COLOR_ENUM.keys(), help="[string] Provide one of the product colors.") + optional_arguments.add_argument("--offset", type=allow_any_int, + help="Partition offset - an address in device's NVM memory, where factory data will be stored.") + optional_arguments.add_argument("--size", type=allow_any_int, + help="The maximum partition size.") args = parser.parse_args() if args.verbose: @@ -551,9 +561,9 @@ def base64_str(s): return base64.b64decode(s) log.basicConfig(format='[%(levelname)s] %(message)s', level=log.INFO) # check if json file already exist - if (exists(args.output) and not args.overwrite): + if (exists(args.output + ".json") and not args.overwrite): log.error(("Output file: {} already exist, to create a new one add argument '--overwrite'. " - "By default overwriting is disabled").format(args.output)) + "By default overwriting is disabled").format(args.output+".json")) return if args.schema and no_jsonschema_module: @@ -572,6 +582,13 @@ def base64_str(s): return base64.b64decode(s) generator = FactoryDataGenerator(args) generator.generate_json() + # If optional partition's offset and size were provided, generate factory data output .hex file. + if args.offset and args.size: + partition_creator = PartitionCreator(args.offset, args.size, args.output + ".json", args.output) + cbor_data = partition_creator.generate_cbor() + partition_creator.create_hex(cbor_data) + partition_creator.create_bin() + if __name__ == "__main__": main()