From 53958d4d325317607ae2be3999642e06b5a9b0b6 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 20 Jan 2022 19:34:04 +0000 Subject: [PATCH] 2022.01 release: - Use CMake as the build system. CMSIS build and CMSIS packs have been removed as a consequence. - Use Open IoT SDK instead of gitmodules to fetch dependencies. - Use AWS embedded C SDK instead of Amazon FreeRTOS distribution - Use MCU Driver HAL for serial, SAI and EMAC driver. - Move TF-M target into BSP Signed-off-by: Vincent Coubard --- .gitignore | 3 + .gitmodules | 19 - CMakeLists.txt | 149 + LICENCE.md | 19 +- README.md | 71 +- blinky.uvmpw | 23 - blinky/CMakeLists.txt | 62 + blinky/main_ns.c | 4 +- blinky/tests/test_blinky.py | 22 +- bsp/CMakeLists.txt | 198 + bsp/an547_bl2.sct | 15 + bsp/an547_ns.sct | 16 + bsp/aws_configs/FreeRTOSConfig.h | 36 +- .../3rdparty/lwip_osal/include/arch/cc.h | 130 + .../3rdparty/lwip_osal/include/arch/perf.h | 40 + .../lwip_osal/include/arch/sys_arch.h | 67 + .../lwip_osal/include/lwipopts_freertos.h | 268 + .../3rdparty/lwip_osal/src/sys_arch.c | 712 + .../3rdparty/mbedtls_config/README.md | 2 + .../mbedtls_config/aws_mbedtls_config.h | 3373 ++ .../3rdparty/mbedtls_config/threading_alt.h | 53 +- .../3rdparty/mbedtls_utils/mbedtls_error.c | 1336 + .../3rdparty/mbedtls_utils/mbedtls_utils.c | 267 + .../mqtt_agent/freertos_agent_message.c | 74 + .../mqtt_agent/freertos_command_pool.c | 145 + .../include/freertos_agent_message.h | 84 + .../include/freertos_command_pool.h | 90 + .../3rdparty/mbedtls_utils/mbedtls_error.h | 63 + .../abstractions/pkcs11/psa/iot_pkcs11_psa.c | 3641 +++ .../pkcs11/psa/iot_pkcs11_psa_input_format.c | 109 + .../pkcs11/psa/iot_pkcs11_psa_input_format.h | 54 + .../psa/iot_pkcs11_psa_object_management.c | 918 + .../psa/iot_pkcs11_psa_object_management.h | 215 + .../freertos/include/platform/iot_network.h | 343 + .../include/platform/iot_network_ble.h | 42 +- .../include/platform/iot_network_freertos.h | 183 + .../platform/iot_platform_types_freertos.h | 84 + .../platform/freertos/iot_clock_freertos.c | 224 + .../platform/freertos/iot_metrics.c | 230 + .../platform/freertos/iot_network_freertos.c | 716 + .../platform/freertos/iot_threads_freertos.c | 364 + .../platform/include/platform/iot_clock.h | 235 + .../platform/include/platform/iot_metrics.h | 113 + .../platform/include/platform/iot_network.h | 343 + .../platform/include/platform/iot_threads.h | 396 + .../include/types/iot_network_types.h | 55 + .../include/types/iot_platform_types.h | 158 + .../include/iot_secure_sockets.h | 667 + .../iot_secure_sockets_config_defaults.h | 72 + .../iot_secure_sockets_wrapper_metrics.h | 44 +- .../secure_sockets/lwip/iot_secure_sockets.c | 1063 + .../secure_sockets/transport_secure_sockets.c | 596 + .../secure_sockets/transport_secure_sockets.h | 204 + .../standard/common/include/iot_atomic.h | 29 +- .../c_sdk/standard/common/include/iot_init.h | 67 + .../common/include/iot_linear_containers.h | 1048 + .../common/include/iot_logging_setup.h | 233 + .../standard/common/include/iot_taskpool.h | 604 + .../private/iot_default_root_certificates.h | 197 + .../include/private/iot_doubly_linked_list.h | 242 + .../common/include/private/iot_error.h | 117 + .../common/include/private/iot_lib_init.h | 23 +- .../common/include/private/iot_logging.h | 240 + .../include/private/iot_static_memory.h | 272 + .../include/private/iot_taskpool_internal.h | 290 + .../common/include/types/iot_taskpool_types.h | 364 + .../standard/common/iot_device_metrics.c | 433 + .../c_sdk/standard/common/iot_init.c | 154 + .../common/iot_static_memory_common.c | 208 + .../standard/common/taskpool/iot_taskpool.c | 1835 ++ .../taskpool/iot_taskpool_static_memory.c | 175 + .../standard/https/include/iot_https_client.h | 898 + .../standard/https/include/iot_https_utils.h | 95 + .../https/include/types/iot_https_types.h | 905 + .../standard/https/src/iot_https_client.c | 3403 ++ .../standard/https/src/iot_https_utils.c | 137 + .../https/src/private/iot_https_internal.h | 539 + .../c_sdk/standard/mqtt/include/iot_mqtt.h | 869 + .../standard/mqtt/include/iot_mqtt_agent.h | 358 + .../include/iot_mqtt_agent_config_defaults.h | 180 + .../mqtt/include/iot_mqtt_config_defaults.h | 115 + .../standard/mqtt/include/iot_mqtt_lib.h | 113 + .../mqtt/include/types/iot_mqtt_types.h | 1091 + .../http_demo_helpers/http_demo_utils.c | 290 + .../http_demo_helpers/http_demo_utils.h | 125 + .../mqtt_demo_helpers/mqtt_demo_helpers.c | 1165 + .../mqtt_demo_helpers/mqtt_demo_helpers.h | 172 + .../mqtt_subscription_manager.c | 171 + .../mqtt_subscription_manager.h | 145 + .../ota_application_version.c | 39 +- .../common/pkcs11_helpers/pkcs11_helpers.c | 103 + .../common/pkcs11_helpers/pkcs11_helpers.h | 55 +- .../demos/coreMQTT_Agent/mqtt_agent_task.c | 1037 + .../coreMQTT_Agent/simple_sub_pub_demo.c | 569 + .../coreMQTT_Agent/subscription_manager.c | 170 + .../coreMQTT_Agent/subscription_manager.h | 150 + .../demos/demo_runner/aws_demo.c | 95 + .../demos/demo_runner/aws_demo_network_addr.c | 106 + .../demos/demo_runner/iot_demo_freertos.c | 446 + .../demos/demo_runner/iot_demo_runner.c | 96 + .../include/aws_dev_mode_key_provisioning.h | 258 + .../src/aws_dev_mode_key_provisioning.c | 1344 + .../network_manager/aws_iot_network_manager.c | 1204 + .../iot_network_manager_private.h | 189 + .../standard/crypto/include/iot_crypto.h | 103 + .../standard/crypto/src/iot_crypto.c | 393 + .../standard/tls/include/iot_tls.h | 178 + .../freertos_plus/standard/tls/src/iot_tls.c | 1096 + .../logging/include/iot_logging_task.h | 134 + .../logging/include/logging_levels.h | 109 + .../logging/include/logging_stack.h | 121 + bsp/aws_libraries/logging/iot_logging.c | 454 + .../iot_logging_task_dynamic_buffers.c | 484 + bsp/freertos-platform/NetworkInterface.c | 253 - bsp/freertos-platform/application_helpers.c | 18 +- .../bsp_serial.c} | 36 +- .../freertos-platform/bsp_serial.h | 4 +- bsp/freertos-platform/lan91c111.c | 372 - bsp/freertos-platform/lan91c111.h | 398 - bsp/freertos-platform/lwip_emac_netif.c | 264 + bsp/freertos-platform/lwip_emac_netif.h | 43 + bsp/freertos-platform/lwip_memory_manager.c | 204 + bsp/freertos-platform/lwip_memory_manager.h | 12 + bsp/freertos-platform/lwip_stack.c | 286 + bsp/freertos-platform/lwip_stack.h | 16 + bsp/freertos-platform/lwipopts.h | 11 + bsp/interface/include/psa/README.md | 1 - bsp/interface/include/psa/client.h | 188 - .../include/psa/crypto_client_struct.h | 48 - bsp/interface/include/psa/crypto_compat.h | 364 - bsp/interface/include/psa/error.h | 60 - .../include/psa/internal_trusted_storage.h | 164 - bsp/interface/include/psa/service.h | 330 - bsp/interface/include/psa/storage_common.h | 49 - bsp/interface/include/psa_manifest/pid.h | 42 - bsp/interface/include/psa_manifest/sid.h | 171 - bsp/interface/include/tfm_api.h | 141 - bsp/interface/include/tfm_crypto_defs.h | 167 - bsp/interface/include/tfm_veneers.h | 197 - bsp/mcuboot_config/mcuboot_config.h | 80 - .../intermedia_tfm_audit_logging.c | 12 - .../load_info_tfm_audit_logging.c | 104 - .../psa_manifest/tfm_audit_logging.h | 28 - .../auto_generated/intermedia_tfm_crypto.c | 12 - .../auto_generated/load_info_tfm_crypto.c | 111 - .../crypto/psa_manifest/tfm_crypto.h | 28 - .../intermedia_tfm_firmware_update.c | 12 - .../load_info_tfm_firmware_update.c | 153 - .../psa_manifest/tfm_firmware_update.h | 33 - .../intermedia_tfm_initial_attestation.c | 12 - .../load_info_tfm_initial_attestation.c | 116 - .../psa_manifest/tfm_initial_attestation.h | 29 - .../intermedia_tfm_internal_trusted_storage.c | 12 - .../load_info_tfm_internal_trusted_storage.c | 130 - .../tfm_internal_trusted_storage.h | 31 - .../auto_generated/intermedia_tfm_platform.c | 12 - .../auto_generated/load_info_tfm_platform.c | 120 - .../platform/psa_manifest/tfm_platform.h | 30 - .../intermedia_tfm_protected_storage.c | 12 - .../load_info_tfm_protected_storage.c | 147 - .../psa_manifest/tfm_protected_storage.h | 32 - .../intermedia_tfm_ffm11_partition.c | 12 - .../load_info_tfm_ffm11_partition.c | 123 - .../psa_manifest/tfm_ffm11_partition.h | 30 - .../cmsis_func/tfm_secure_irq_handlers.inc | 72 - .../spm/cmsis_func/tfm_spm_db_func.inc | 1133 - bsp/secure_fw/spm/cmsis_func/tfm_veneers.c | 376 - .../cmsis_psa/tfm_secure_irq_handlers_ipc.inc | 28 - .../intermedia_tfm_attest_test_service.c | 12 - .../load_info_tfm_attest_test_service.c | 107 - .../psa_manifest/tfm_attest_test_service.h | 28 - .../intermedia_tfm_ss_core_test.c | 12 - .../load_info_tfm_ss_core_test.c | 201 - .../psa_manifest/tfm_ss_core_test.h | 37 - .../intermedia_tfm_ss_core_test_2.c | 12 - .../load_info_tfm_ss_core_test_2.c | 129 - .../psa_manifest/tfm_ss_core_test_2.h | 31 - .../intermedia_tfm_flih_test_service.c | 12 - .../load_info_tfm_flih_test_service.c | 122 - .../psa_manifest/tfm_flih_test_service.h | 30 - .../intermedia_tfm_ipc_client_test.c | 12 - .../load_info_tfm_ipc_client_test.c | 155 - .../psa_manifest/tfm_ipc_client_test.h | 33 - .../intermedia_tfm_ipc_service_test.c | 12 - .../load_info_tfm_ipc_service_test.c | 139 - .../psa_manifest/tfm_ipc_service_test.h | 32 - .../intermedia_tfm_ps_test_service.c | 12 - .../load_info_tfm_ps_test_service.c | 108 - .../psa_manifest/tfm_ps_test_service.h | 28 - .../intermedia_tfm_secure_client_2.c | 12 - .../load_info_tfm_secure_client_2.c | 106 - .../psa_manifest/tfm_secure_client_2.h | 28 - .../intermedia_tfm_secure_client_service.c | 12 - .../load_info_tfm_secure_client_service.c | 141 - .../psa_manifest/tfm_secure_client_service.h | 28 - .../intermedia_tfm_slih_test_service.c | 12 - .../load_info_tfm_slih_test_service.c | 122 - .../psa_manifest/tfm_slih_test_service.h | 29 - .../arm/mps3/an547/CMakeLists.txt | 187 + bsp/tf_m_targets/arm/mps3/an547/README.rst | 101 + bsp/tf_m_targets/arm/mps3/an547/boot_hal.c | 82 + .../an547/cmsis_drivers/Driver_AN547_MPC.c | 811 + .../mps3/an547/cmsis_drivers/Driver_Flash.c | 283 + .../an547/cmsis_drivers/Driver_SSE300_PPC.c | 1305 + .../an547/cmsis_drivers/Driver_SSE300_PPC.h | 131 + .../mps3/an547/cmsis_drivers/Driver_USART.c | 700 + .../an547/cmsis_drivers/config/RTE_Device.h | 114 + .../config/cmsis_driver_config.h | 43 + bsp/tf_m_targets/arm/mps3/an547/config.cmake | 6 + .../arm/mps3/an547/device/config/device_cfg.h | 73 + .../arm/mps3/an547/device/include/cmsis.h | 78 + .../an547/device/include/device_definition.h | 249 + .../device/include/platform_description.h | 26 + .../mps3/an547/device/include/platform_irq.h | 155 + .../mps3/an547/device/include/platform_pins.h | 114 + .../mps3/an547/device/include/platform_regs.h | 506 + .../an547/device/include/system_core_init.h | 48 + .../device/source/armclang/an547_bl2.sct | 49 + .../an547/device/source/armclang/an547_ns.sct | 49 + .../an547/device/source/device_definition.c | 677 + .../mps3/an547/device/source/gcc/an547_bl2.ld | 191 + .../mps3/an547/device/source/gcc/an547_ns.ld | 190 + .../an547/device/source/startup_an547_bl2.c | 344 + .../an547/device/source/startup_an547_ns.c | 454 + .../an547/device/source/startup_an547_s.c | 359 + .../an547/device/source/system_core_init.c | 85 + .../an547/native_drivers/arm_mps3_io_drv.c | 146 + .../an547/native_drivers/arm_mps3_io_drv.h | 111 + .../mps3/an547/native_drivers/mpc_sie_drv.c | 791 + .../mps3/an547/native_drivers/mpc_sie_drv.h | 354 + .../an547/native_drivers/mpu_armv8m_drv.c | 156 + .../an547/native_drivers/mpu_armv8m_drv.h | 153 + .../an547/native_drivers/ppc_sse300_drv.c | 456 + .../an547/native_drivers/ppc_sse300_drv.h | 220 + .../an547/native_drivers/smsc9220_eth_drv.c | 1079 + .../an547/native_drivers/smsc9220_eth_drv.h | 544 + .../syscounter_armv8-m_cntrl_drv.c | 485 + .../syscounter_armv8-m_cntrl_drv.h | 503 + .../native_drivers/systimer_armv8-m_drv.c | 345 + .../native_drivers/systimer_armv8-m_drv.h | 411 + .../an547/native_drivers/uart_cmsdk_drv.c | 264 + .../an547/native_drivers/uart_cmsdk_drv.h | 221 + .../arm/mps3/an547/partition/flash_layout.h | 218 + .../an547/partition/platform_base_address.h | 263 + .../arm/mps3/an547/partition/region_defs.h | 148 + bsp/tf_m_targets/arm/mps3/an547/plat_test.c | 92 + bsp/tf_m_targets/arm/mps3/an547/preload.cmake | 16 + .../an547/services/src/tfm_platform_system.c | 33 + bsp/tf_m_targets/arm/mps3/an547/spm_hal.c | 187 + bsp/tf_m_targets/arm/mps3/an547/target_cfg.c | 736 + bsp/tf_m_targets/arm/mps3/an547/target_cfg.h | 166 + .../arm/mps3/an547/tfm_hal_isolation.c | 167 + .../arm/mps3/an547/tfm_peripherals_def.h | 48 + bsp/tfm_s.sct | 16 + kws.uvmpw | 23 - kws/CMakeLists.txt | 191 + kws/include/ml_interface.h | 4 + .../3rdparty/tinycbor/.appveyor.yml | 35 - .../3rdparty/tinycbor/.gitattributes | 4 - .../dependency/3rdparty/tinycbor/.gitignore | 81 - .../source/dependency/3rdparty/tinycbor/.tag | 1 - .../dependency/3rdparty/tinycbor/.travis.yml | 84 - .../dependency/3rdparty/tinycbor/Doxyfile | 49 - .../dependency/3rdparty/tinycbor/LICENSE | 21 - .../dependency/3rdparty/tinycbor/Makefile | 240 - .../dependency/3rdparty/tinycbor/README | 13 - .../source/dependency/3rdparty/tinycbor/TODO | 25 - .../dependency/3rdparty/tinycbor/VERSION | 1 - .../dependency/3rdparty/tinycbor/src/cbor.dox | 123 - .../dependency/3rdparty/tinycbor/src/cbor.h | 607 - .../3rdparty/tinycbor/src/cborencoder.c | 645 - .../src/cborencoder_close_container_checked.c | 57 - .../3rdparty/tinycbor/src/cborerrorstrings.c | 182 - .../3rdparty/tinycbor/src/cborinternal_p.h | 161 - .../3rdparty/tinycbor/src/cborjson.h | 62 - .../3rdparty/tinycbor/src/cborparser.c | 1449 - .../tinycbor/src/cborparser_dup_string.c | 119 - .../3rdparty/tinycbor/src/cborpretty.c | 580 - .../3rdparty/tinycbor/src/cborpretty_stdio.c | 87 - .../3rdparty/tinycbor/src/cbortojson.c | 699 - .../3rdparty/tinycbor/src/cborvalidation.c | 670 - .../3rdparty/tinycbor/src/compilersupport_p.h | 205 - .../3rdparty/tinycbor/src/open_memstream.c | 82 - .../3rdparty/tinycbor/src/parsetags.pl | 116 - .../dependency/3rdparty/tinycbor/src/src.pri | 16 - .../dependency/3rdparty/tinycbor/src/tags.txt | 23 - .../3rdparty/tinycbor/src/tinycbor-version.h | 3 - .../3rdparty/tinycbor/src/tinycbor.pro | 6 - .../dependency/3rdparty/tinycbor/src/utf8_p.h | 104 - .../3rdparty/tinycbor/tests/.gitignore | 15 - .../3rdparty/tinycbor/tests/c90/c90.pro | 7 - .../3rdparty/tinycbor/tests/c90/tst_c90.c | 30 - .../3rdparty/tinycbor/tests/cpp/cpp.pro | 5 - .../3rdparty/tinycbor/tests/cpp/tst_cpp.cpp | 42 - .../tinycbor/tests/encoder/encoder.pro | 9 - .../tinycbor/tests/encoder/tst_encoder.cpp | 734 - .../3rdparty/tinycbor/tests/parser/parser.pro | 10 - .../tinycbor/tests/parser/tst_parser.cpp | 2204 -- .../3rdparty/tinycbor/tests/tests.pro | 3 - .../3rdparty/tinycbor/tests/tojson/tojson.pro | 8 - .../tinycbor/tests/tojson/tst_tojson.cpp | 721 - .../3rdparty/tinycbor/tinycbor.pc.in | 11 - .../tinycbor/tools/cbordump/cbordump.c | 164 - .../tinycbor/tools/cbordump/cbordump.pro | 10 - .../tinycbor/tools/json2cbor/json2cbor.c | 493 - .../tinycbor/tools/json2cbor/json2cbor.pro | 20 - .../coreJSON/.github/CONTRIBUTING.md | 62 - .../coreJSON/.github/workflows/ci.yml | 163 - .../coreJSON/.github/workflows/release.yml | 114 - .../source/dependency/coreJSON/.gitignore | 13 - .../source/dependency/coreJSON/.gitmodules | 12 - .../source/dependency/coreJSON/CHANGELOG.md | 20 - .../source/dependency/coreJSON/LICENSE | 19 - .../source/dependency/coreJSON/MISRA.md | 26 - .../source/dependency/coreJSON/README.md | 112 - .../source/dependency/coreJSON/SECURITY.md | 5 - .../coreJSON/docs/doxygen/config.doxyfile | 2005 -- .../coreJSON/docs/doxygen/layout.xml | 228 - .../coreJSON/docs/doxygen/pages.dox | 95 - .../coreJSON/docs/doxygen/style.css | 132 - .../source/dependency/coreJSON/lexicon.txt | 118 - .../source/dependency/coreJSON/manifest.yml | 5 - .../dependency/coreJSON/source/core_json.c | 1806 -- .../coreJSON/source/include/core_json.h | 324 - .../coreJSON/source/include/stdbool.readme | 30 - .../coreJSON/source/include/stdint.readme | 37 - .../dependency/coreJSON/test/cbmc/.gitignore | 21 - .../coreJSON/test/cbmc/include/README.md | 1 - .../test/cbmc/include/core_json_annex.h | 109 - .../JSON_Iterate/JSON_Iterate_harness.c | 79 - .../test/cbmc/proofs/JSON_Iterate/Makefile | 27 - .../test/cbmc/proofs/JSON_Iterate/README.md | 23 - .../cbmc/proofs/JSON_Iterate/cbmc-proof.txt | 1 - .../cbmc/proofs/JSON_Iterate/cbmc-viewer.json | 7 - .../proofs/JSON_Search/JSON_Search_harness.c | 76 - .../test/cbmc/proofs/JSON_Search/Makefile | 35 - .../test/cbmc/proofs/JSON_Search/README.md | 30 - .../cbmc/proofs/JSON_Search/cbmc-proof.txt | 1 - .../cbmc/proofs/JSON_Search/cbmc-viewer.json | 7 - .../test/cbmc/proofs/JSON_Validate/Makefile | 24 - .../test/cbmc/proofs/JSON_Validate/README.md | 21 - .../cbmc/proofs/JSON_Validate/cbmc-proof.txt | 1 - .../proofs/JSON_Validate/cbmc-viewer.json | 7 - .../coreJSON/test/cbmc/proofs/Makefile | 24 - .../test/cbmc/proofs/Makefile-json.common | 22 - .../test/cbmc/proofs/Makefile-project-defines | 42 - .../test/cbmc/proofs/Makefile-project-targets | 25 - .../test/cbmc/proofs/Makefile-project-testing | 11 - .../cbmc/proofs/Makefile-template-defines | 1 - .../coreJSON/test/cbmc/proofs/Makefile.common | 1 - .../coreJSON/test/cbmc/proofs/README.md | 27 - .../test/cbmc/proofs/run-cbmc-proofs.py | 258 - .../test/cbmc/proofs/skipAnyLiteral/Makefile | 19 - .../test/cbmc/proofs/skipAnyLiteral/README.md | 16 - .../cbmc/proofs/skipAnyLiteral/cbmc-proof.txt | 1 - .../proofs/skipAnyLiteral/cbmc-viewer.json | 7 - .../test/cbmc/proofs/skipCollection/Makefile | 29 - .../test/cbmc/proofs/skipCollection/README.md | 26 - .../cbmc/proofs/skipCollection/cbmc-proof.txt | 1 - .../proofs/skipCollection/cbmc-viewer.json | 7 - .../skipCollection/skipCollection_harness.c | 56 - .../test/cbmc/proofs/skipEscape/Makefile | 19 - .../test/cbmc/proofs/skipEscape/README.md | 17 - .../cbmc/proofs/skipEscape/cbmc-proof.txt | 1 - .../cbmc/proofs/skipEscape/cbmc-viewer.json | 7 - .../proofs/skipEscape/skipEscape_harness.c | 56 - .../test/cbmc/proofs/skipNumber/Makefile | 20 - .../test/cbmc/proofs/skipNumber/README.md | 20 - .../cbmc/proofs/skipNumber/cbmc-proof.txt | 1 - .../cbmc/proofs/skipNumber/cbmc-viewer.json | 7 - .../proofs/skipNumber/skipNumber_harness.c | 70 - .../test/cbmc/proofs/skipSpace/Makefile | 17 - .../test/cbmc/proofs/skipSpace/README.md | 14 - .../test/cbmc/proofs/skipSpace/cbmc-proof.txt | 1 - .../cbmc/proofs/skipSpace/cbmc-viewer.json | 7 - .../cbmc/proofs/skipSpace/skipSpace_harness.c | 53 - .../cbmc/proofs/skipSpaceAndComma/Makefile | 18 - .../cbmc/proofs/skipSpaceAndComma/README.md | 14 - .../proofs/skipSpaceAndComma/cbmc-proof.txt | 1 - .../proofs/skipSpaceAndComma/cbmc-viewer.json | 7 - .../skipSpaceAndComma_harness.c | 56 - .../test/cbmc/proofs/skipString/Makefile | 21 - .../test/cbmc/proofs/skipString/README.md | 17 - .../cbmc/proofs/skipString/cbmc-proof.txt | 1 - .../cbmc/proofs/skipString/cbmc-viewer.json | 7 - .../proofs/skipString/skipString_harness.c | 56 - .../test/cbmc/proofs/skipUTF8/Makefile | 19 - .../test/cbmc/proofs/skipUTF8/README.md | 17 - .../test/cbmc/proofs/skipUTF8/cbmc-proof.txt | 1 - .../cbmc/proofs/skipUTF8/cbmc-viewer.json | 7 - .../cbmc/proofs/skipUTF8/skipUTF8_harness.c | 56 - .../coreJSON/test/cbmc/sources/README.md | 1 - .../coreJSON/test/cbmc/stubs/README.md | 1 - .../coreJSON/test/cbmc/stubs/skipAnyLiteral.c | 36 - .../coreJSON/test/cbmc/stubs/skipCollection.c | 40 - .../coreJSON/test/cbmc/stubs/skipDigits.c | 48 - .../coreJSON/test/cbmc/stubs/skipEscape.c | 37 - .../coreJSON/test/cbmc/stubs/skipNumber.c | 36 - .../test/cbmc/stubs/skipSpaceAndComma.c | 38 - .../coreJSON/test/cbmc/stubs/skipString.c | 36 - .../coreJSON/test/unit-test/catch_assert.h | 77 - .../coreJSON/test/unit-test/core_json_utest.c | 1873 -- .../coreJSON/tools/coverity/misra.config | 39 - .../dependency/coreJSON/tools/uncrustify.cfg | 160 - .../coreJSON/tools/unity/project.yml | 12 - kws/ota/ota_for_aws/source/include/ota.h | 803 - .../source/include/ota_appversion32.h | 69 - .../source/include/ota_base64_private.h | 106 - .../source/include/ota_cbor_private.h | 75 - .../source/include/ota_config_defaults.h | 356 - .../source/include/ota_http_interface.h | 136 - .../source/include/ota_http_private.h | 110 - .../source/include/ota_interface_private.h | 111 - .../source/include/ota_mqtt_interface.h | 162 - .../source/include/ota_mqtt_private.h | 157 - .../source/include/ota_os_interface.h | 301 - .../source/include/ota_platform_interface.h | 307 - .../ota_for_aws/source/include/ota_private.h | 437 - .../ota_for_aws/source/include/stdbool.readme | 30 - .../ota_for_aws/source/include/stdint.readme | 37 - kws/ota/ota_for_aws/source/ota.c | 3730 --- kws/ota/ota_for_aws/source/ota_base64.c | 516 - kws/ota/ota_for_aws/source/ota_cbor.c | 364 - kws/ota/ota_for_aws/source/ota_http.c | 203 - kws/ota/ota_for_aws/source/ota_interface.c | 147 - kws/ota/ota_for_aws/source/ota_mqtt.c | 1262 - .../source/portable/os/ota_os_freertos.c | 367 - .../source/portable/os/ota_os_freertos.h | 166 - .../source/portable/os/ota_os_posix.c | 419 - .../source/portable/os/ota_os_posix.h | 173 - kws/source/blink_task.c | 2 +- kws/source/main_ns.c | 24 +- kws/source/ml_interface.cc | 109 +- kws/source/model_config.cc | 3 - kws/source/peripheral_memmap.h | 1 + kws/tests/test_ml.py | 31 +- lib/AWS/CMakeLists.txt | 193 + lib/AWS/FreeRTOS-Plus-TCP/CMakeLists.txt | 53 + lib/AWS/aws-iot-device-sdk-fetch.cmake | 19 + lib/AWS/backoff_algorithm/CMakeLists.txt | 11 + lib/AWS/coreHTTP/CMakeLists.txt | 24 + lib/AWS/coreJSON/CMakeLists.txt | 21 + lib/AWS/coreMQTT-Agent/CMakeLists.txt | 37 + lib/AWS/coreMQTT/CMakeLists.txt | 25 + lib/AWS/corePKCS11/CMakeLists.txt | 46 + lib/AWS/mbedtls/CMakeLists.txt | 115 + lib/AWS/ota_for_aws/CMakeLists.txt | 39 + .../AWS/patches/apply.sh | 18 +- lib/AWS/patches/ota_for_aws.patch | 80 + lib/AWS/patches/tinycbor.patch | 105 + lib/AWS/tinycbor/CMakeLists.txt | 20 + lib/VHT | 2 +- lib/amazon_freertos | 1 - lib/lwip/CMakeLists.txt | 72 + lib/lwip/lwip-fetch.cmake | 13 + lib/mbedcrypto | 1 - lib/mcuboot | 1 - lib/ml-embedded-evaluation-kit | 1 - lib/tf-m | 1 - lib/tfm_test | 1 - patches/.gitignore | 1 - patches/VHT.patch | 20 - patches/amazon_freertos.patch | 19 - patches/clean.py | 37 - patches/mbedcrypto.patch | 55 - patches/ml-embedded-evaluation-kit.patch | 89 +- patches/tf-m.patch | 1140 + ...WIP-Fix-system-reset-issue-with-MPCs.patch | 123 - ...tup-AN547-NS-side-in-priveleged-mode.patch | 26 - ...003-WIP-Add-first-files-of-tfm-extra.patch | 782 - patches/tf-m/0004-Update-platform-AN547.patch | 2586 -- ...TT-mutual-authentication-demo-on-FVP.patch | 26 - patches/tf-m/0006.patch | 25772 ---------------- resources/Keyword-detection-overview.png | Bin 184263 -> 204853 bytes scripts/ARM.DevSummitDemo.pack.desc | 64 - scripts/bootstrap.sh | 66 - scripts/build.sh | 42 +- scripts/make_cmsis_pack.sh | 132 - scripts/run.sh | 4 +- scripts/sign_binaries.sh | 67 - scripts/sign_update_binaries.sh | 48 - tfm.blinky_ns.cprj | 82 - tfm.blinky_ns.uvoptx | 624 - tfm.blinky_ns.uvprojx | 875 - tfm.bootloader.cprj | 154 - tfm.bootloader.uvoptx | 1472 - tfm.bootloader.uvprojx | 1298 - tfm.kws_ns.cprj | 654 - tfm.kws_ns.uvoptx | 6952 ----- tfm.kws_ns.uvprojx | 4442 --- tfm.secure.cprj | 279 - tfm.secure.uvoptx | 2712 -- tfm.secure.uvprojx | 2592 -- 493 files changed, 63335 insertions(+), 91185 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 blinky.uvmpw create mode 100644 blinky/CMakeLists.txt create mode 100644 bsp/CMakeLists.txt create mode 100644 bsp/aws_libraries/3rdparty/lwip_osal/include/arch/cc.h create mode 100644 bsp/aws_libraries/3rdparty/lwip_osal/include/arch/perf.h create mode 100644 bsp/aws_libraries/3rdparty/lwip_osal/include/arch/sys_arch.h create mode 100644 bsp/aws_libraries/3rdparty/lwip_osal/include/lwipopts_freertos.h create mode 100644 bsp/aws_libraries/3rdparty/lwip_osal/src/sys_arch.c create mode 100644 bsp/aws_libraries/3rdparty/mbedtls_config/README.md create mode 100644 bsp/aws_libraries/3rdparty/mbedtls_config/aws_mbedtls_config.h rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/skipAnyLiteral_harness.c => bsp/aws_libraries/3rdparty/mbedtls_config/threading_alt.h (53%) create mode 100644 bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_error.c create mode 100644 bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_utils.c create mode 100644 bsp/aws_libraries/abstractions/mqtt_agent/freertos_agent_message.c create mode 100644 bsp/aws_libraries/abstractions/mqtt_agent/freertos_command_pool.c create mode 100644 bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_agent_message.h create mode 100644 bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_command_pool.h create mode 100644 bsp/aws_libraries/abstractions/pkcs11/corePKCS11/source/dependency/3rdparty/mbedtls_utils/mbedtls_error.h create mode 100644 bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa.c create mode 100644 bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.c create mode 100644 bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.h create mode 100644 bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.c create mode 100644 bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.h create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network.h rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/JSON_Validate_harness.c => bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_ble.h (63%) create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_freertos.h create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_platform_types_freertos.h create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/iot_clock_freertos.c create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/iot_metrics.c create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/iot_network_freertos.c create mode 100644 bsp/aws_libraries/abstractions/platform/freertos/iot_threads_freertos.c create mode 100644 bsp/aws_libraries/abstractions/platform/include/platform/iot_clock.h create mode 100644 bsp/aws_libraries/abstractions/platform/include/platform/iot_metrics.h create mode 100644 bsp/aws_libraries/abstractions/platform/include/platform/iot_network.h create mode 100644 bsp/aws_libraries/abstractions/platform/include/platform/iot_threads.h create mode 100644 bsp/aws_libraries/abstractions/platform/include/types/iot_network_types.h create mode 100644 bsp/aws_libraries/abstractions/platform/include/types/iot_platform_types.h create mode 100644 bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets.h create mode 100644 bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/include/skipGeneric.h => bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h (58%) create mode 100644 bsp/aws_libraries/abstractions/secure_sockets/lwip/iot_secure_sockets.c create mode 100755 bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.c create mode 100755 bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipSpace.c => bsp/aws_libraries/c_sdk/standard/common/include/iot_atomic.h (76%) create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/iot_init.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/iot_linear_containers.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/iot_logging_setup.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/iot_taskpool.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/private/iot_default_root_certificates.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/private/iot_doubly_linked_list.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/private/iot_error.h rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipUTF8.c => bsp/aws_libraries/c_sdk/standard/common/include/private/iot_lib_init.h (75%) create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/private/iot_logging.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/private/iot_static_memory.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/private/iot_taskpool_internal.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/include/types/iot_taskpool_types.h create mode 100644 bsp/aws_libraries/c_sdk/standard/common/iot_device_metrics.c create mode 100644 bsp/aws_libraries/c_sdk/standard/common/iot_init.c create mode 100644 bsp/aws_libraries/c_sdk/standard/common/iot_static_memory_common.c create mode 100644 bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool.c create mode 100644 bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool_static_memory.c create mode 100644 bsp/aws_libraries/c_sdk/standard/https/include/iot_https_client.h create mode 100644 bsp/aws_libraries/c_sdk/standard/https/include/iot_https_utils.h create mode 100644 bsp/aws_libraries/c_sdk/standard/https/include/types/iot_https_types.h create mode 100644 bsp/aws_libraries/c_sdk/standard/https/src/iot_https_client.c create mode 100644 bsp/aws_libraries/c_sdk/standard/https/src/iot_https_utils.c create mode 100644 bsp/aws_libraries/c_sdk/standard/https/src/private/iot_https_internal.h create mode 100644 bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt.h create mode 100644 bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent.h create mode 100644 bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent_config_defaults.h create mode 100644 bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_config_defaults.h create mode 100644 bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_lib.h create mode 100644 bsp/aws_libraries/c_sdk/standard/mqtt/include/types/iot_mqtt_types.h create mode 100644 bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.c create mode 100644 bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.h create mode 100644 bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.c create mode 100644 bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.h create mode 100644 bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.c create mode 100644 bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.h rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipAnyScalar.c => bsp/aws_libraries/demos/common/ota_demo_helpers/ota_application_version.c (61%) create mode 100644 bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.c rename kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipGeneric.c => bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.h (54%) create mode 100644 bsp/aws_libraries/demos/coreMQTT_Agent/mqtt_agent_task.c create mode 100644 bsp/aws_libraries/demos/coreMQTT_Agent/simple_sub_pub_demo.c create mode 100644 bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.c create mode 100644 bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.h create mode 100644 bsp/aws_libraries/demos/demo_runner/aws_demo.c create mode 100644 bsp/aws_libraries/demos/demo_runner/aws_demo_network_addr.c create mode 100644 bsp/aws_libraries/demos/demo_runner/iot_demo_freertos.c create mode 100644 bsp/aws_libraries/demos/demo_runner/iot_demo_runner.c create mode 100644 bsp/aws_libraries/demos/dev_mode_key_provisioning/include/aws_dev_mode_key_provisioning.h create mode 100644 bsp/aws_libraries/demos/dev_mode_key_provisioning/src/aws_dev_mode_key_provisioning.c create mode 100644 bsp/aws_libraries/demos/network_manager/aws_iot_network_manager.c create mode 100644 bsp/aws_libraries/demos/network_manager/iot_network_manager_private.h create mode 100644 bsp/aws_libraries/freertos_plus/standard/crypto/include/iot_crypto.h create mode 100644 bsp/aws_libraries/freertos_plus/standard/crypto/src/iot_crypto.c create mode 100644 bsp/aws_libraries/freertos_plus/standard/tls/include/iot_tls.h create mode 100644 bsp/aws_libraries/freertos_plus/standard/tls/src/iot_tls.c create mode 100644 bsp/aws_libraries/logging/include/iot_logging_task.h create mode 100644 bsp/aws_libraries/logging/include/logging_levels.h create mode 100644 bsp/aws_libraries/logging/include/logging_stack.h create mode 100644 bsp/aws_libraries/logging/iot_logging.c create mode 100644 bsp/aws_libraries/logging/iot_logging_task_dynamic_buffers.c delete mode 100644 bsp/freertos-platform/NetworkInterface.c rename bsp/{source/serial.c => freertos-platform/bsp_serial.c} (52%) rename kws/include/serial.h => bsp/freertos-platform/bsp_serial.h (94%) delete mode 100644 bsp/freertos-platform/lan91c111.c delete mode 100644 bsp/freertos-platform/lan91c111.h create mode 100644 bsp/freertos-platform/lwip_emac_netif.c create mode 100644 bsp/freertos-platform/lwip_emac_netif.h create mode 100644 bsp/freertos-platform/lwip_memory_manager.c create mode 100644 bsp/freertos-platform/lwip_memory_manager.h create mode 100644 bsp/freertos-platform/lwip_stack.c create mode 100644 bsp/freertos-platform/lwip_stack.h create mode 100644 bsp/freertos-platform/lwipopts.h delete mode 100644 bsp/interface/include/psa/README.md delete mode 100644 bsp/interface/include/psa/client.h delete mode 100644 bsp/interface/include/psa/crypto_client_struct.h delete mode 100644 bsp/interface/include/psa/crypto_compat.h delete mode 100644 bsp/interface/include/psa/error.h delete mode 100644 bsp/interface/include/psa/internal_trusted_storage.h delete mode 100644 bsp/interface/include/psa/service.h delete mode 100644 bsp/interface/include/psa/storage_common.h delete mode 100644 bsp/interface/include/psa_manifest/pid.h delete mode 100644 bsp/interface/include/psa_manifest/sid.h delete mode 100644 bsp/interface/include/tfm_api.h delete mode 100644 bsp/interface/include/tfm_crypto_defs.h delete mode 100644 bsp/interface/include/tfm_veneers.h delete mode 100644 bsp/mcuboot_config/mcuboot_config.h delete mode 100644 bsp/secure_fw/partitions/audit_logging/auto_generated/intermedia_tfm_audit_logging.c delete mode 100644 bsp/secure_fw/partitions/audit_logging/auto_generated/load_info_tfm_audit_logging.c delete mode 100644 bsp/secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h delete mode 100644 bsp/secure_fw/partitions/crypto/auto_generated/intermedia_tfm_crypto.c delete mode 100644 bsp/secure_fw/partitions/crypto/auto_generated/load_info_tfm_crypto.c delete mode 100644 bsp/secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h delete mode 100644 bsp/secure_fw/partitions/firmware_update/auto_generated/intermedia_tfm_firmware_update.c delete mode 100644 bsp/secure_fw/partitions/firmware_update/auto_generated/load_info_tfm_firmware_update.c delete mode 100644 bsp/secure_fw/partitions/firmware_update/psa_manifest/tfm_firmware_update.h delete mode 100644 bsp/secure_fw/partitions/initial_attestation/auto_generated/intermedia_tfm_initial_attestation.c delete mode 100644 bsp/secure_fw/partitions/initial_attestation/auto_generated/load_info_tfm_initial_attestation.c delete mode 100644 bsp/secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h delete mode 100644 bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/intermedia_tfm_internal_trusted_storage.c delete mode 100644 bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/load_info_tfm_internal_trusted_storage.c delete mode 100644 bsp/secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h delete mode 100644 bsp/secure_fw/partitions/platform/auto_generated/intermedia_tfm_platform.c delete mode 100644 bsp/secure_fw/partitions/platform/auto_generated/load_info_tfm_platform.c delete mode 100644 bsp/secure_fw/partitions/platform/psa_manifest/tfm_platform.h delete mode 100644 bsp/secure_fw/partitions/protected_storage/auto_generated/intermedia_tfm_protected_storage.c delete mode 100644 bsp/secure_fw/partitions/protected_storage/auto_generated/load_info_tfm_protected_storage.c delete mode 100644 bsp/secure_fw/partitions/protected_storage/psa_manifest/tfm_protected_storage.h delete mode 100644 bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/intermedia_tfm_ffm11_partition.c delete mode 100644 bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/load_info_tfm_ffm11_partition.c delete mode 100644 bsp/secure_fw/partitions/tfm_ffm11_partition/psa_manifest/tfm_ffm11_partition.h delete mode 100644 bsp/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc delete mode 100644 bsp/secure_fw/spm/cmsis_func/tfm_spm_db_func.inc delete mode 100644 bsp/secure_fw/spm/cmsis_func/tfm_veneers.c delete mode 100644 bsp/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc delete mode 100644 bsp/test_services/tfm_attest_test_service/auto_generated/intermedia_tfm_attest_test_service.c delete mode 100644 bsp/test_services/tfm_attest_test_service/auto_generated/load_info_tfm_attest_test_service.c delete mode 100644 bsp/test_services/tfm_attest_test_service/psa_manifest/tfm_attest_test_service.h delete mode 100644 bsp/test_services/tfm_core_test/auto_generated/intermedia_tfm_ss_core_test.c delete mode 100644 bsp/test_services/tfm_core_test/auto_generated/load_info_tfm_ss_core_test.c delete mode 100644 bsp/test_services/tfm_core_test/psa_manifest/tfm_ss_core_test.h delete mode 100644 bsp/test_services/tfm_core_test_2/auto_generated/intermedia_tfm_ss_core_test_2.c delete mode 100644 bsp/test_services/tfm_core_test_2/auto_generated/load_info_tfm_ss_core_test_2.c delete mode 100644 bsp/test_services/tfm_core_test_2/psa_manifest/tfm_ss_core_test_2.h delete mode 100644 bsp/test_services/tfm_flih_test_service/auto_generated/intermedia_tfm_flih_test_service.c delete mode 100644 bsp/test_services/tfm_flih_test_service/auto_generated/load_info_tfm_flih_test_service.c delete mode 100644 bsp/test_services/tfm_flih_test_service/psa_manifest/tfm_flih_test_service.h delete mode 100644 bsp/test_services/tfm_ipc_client/auto_generated/intermedia_tfm_ipc_client_test.c delete mode 100644 bsp/test_services/tfm_ipc_client/auto_generated/load_info_tfm_ipc_client_test.c delete mode 100644 bsp/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h delete mode 100644 bsp/test_services/tfm_ipc_service/auto_generated/intermedia_tfm_ipc_service_test.c delete mode 100644 bsp/test_services/tfm_ipc_service/auto_generated/load_info_tfm_ipc_service_test.c delete mode 100644 bsp/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_test.h delete mode 100644 bsp/test_services/tfm_ps_test_service/auto_generated/intermedia_tfm_ps_test_service.c delete mode 100644 bsp/test_services/tfm_ps_test_service/auto_generated/load_info_tfm_ps_test_service.c delete mode 100644 bsp/test_services/tfm_ps_test_service/psa_manifest/tfm_ps_test_service.h delete mode 100644 bsp/test_services/tfm_secure_client_2/auto_generated/intermedia_tfm_secure_client_2.c delete mode 100644 bsp/test_services/tfm_secure_client_2/auto_generated/load_info_tfm_secure_client_2.c delete mode 100644 bsp/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h delete mode 100644 bsp/test_services/tfm_secure_client_service/auto_generated/intermedia_tfm_secure_client_service.c delete mode 100644 bsp/test_services/tfm_secure_client_service/auto_generated/load_info_tfm_secure_client_service.c delete mode 100644 bsp/test_services/tfm_secure_client_service/psa_manifest/tfm_secure_client_service.h delete mode 100644 bsp/test_services/tfm_slih_test_service/auto_generated/intermedia_tfm_slih_test_service.c delete mode 100644 bsp/test_services/tfm_slih_test_service/auto_generated/load_info_tfm_slih_test_service.c delete mode 100644 bsp/test_services/tfm_slih_test_service/psa_manifest/tfm_slih_test_service.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/CMakeLists.txt create mode 100644 bsp/tf_m_targets/arm/mps3/an547/README.rst create mode 100644 bsp/tf_m_targets/arm/mps3/an547/boot_hal.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_AN547_MPC.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_Flash.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_USART.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/RTE_Device.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/cmsis_driver_config.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/config.cmake create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/config/device_cfg.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/cmsis.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/device_definition.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/platform_description.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/platform_irq.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/platform_pins.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/platform_regs.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/include/system_core_init.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_bl2.sct create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_ns.sct create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/device_definition.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_bl2.ld create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_ns.ld create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_bl2.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_ns.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_s.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/device/source/system_core_init.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/partition/flash_layout.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/partition/platform_base_address.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/partition/region_defs.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/plat_test.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/preload.cmake create mode 100644 bsp/tf_m_targets/arm/mps3/an547/services/src/tfm_platform_system.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/spm_hal.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/target_cfg.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/target_cfg.h create mode 100644 bsp/tf_m_targets/arm/mps3/an547/tfm_hal_isolation.c create mode 100644 bsp/tf_m_targets/arm/mps3/an547/tfm_peripherals_def.h delete mode 100644 kws.uvmpw create mode 100644 kws/CMakeLists.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.appveyor.yml delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitattributes delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitignore delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.tag delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.travis.yml delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Doxyfile delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/LICENSE delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/README delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/TODO delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/VERSION delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.dox delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder_close_container_checked.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborerrorstrings.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborinternal_p.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborjson.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser_dup_string.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty_stdio.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbortojson.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborvalidation.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/compilersupport_p.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/open_memstream.c delete mode 100755 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/parsetags.pl delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/src.pri delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tags.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor-version.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/utf8_p.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/.gitignore delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/c90.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/tst_c90.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/cpp.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/tst_cpp.cpp delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/encoder.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/parser.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/tst_parser.cpp delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tests.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tojson.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tst_tojson.cpp delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tinycbor.pc.in delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.pro delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/.github/CONTRIBUTING.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/ci.yml delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/release.yml delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/.gitignore delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/.gitmodules delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/CHANGELOG.md delete mode 100755 kws/ota/ota_for_aws/source/dependency/coreJSON/LICENSE delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/MISRA.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/SECURITY.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/config.doxyfile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/layout.xml delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/pages.dox delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/style.css delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/lexicon.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/manifest.yml delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/source/core_json.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/source/include/core_json.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/source/include/stdbool.readme delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/source/include/stdint.readme delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/.gitignore delete mode 120000 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/include/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/include/core_json_annex.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Iterate/JSON_Iterate_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Iterate/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Iterate/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Iterate/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Iterate/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Search/JSON_Search_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Search/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Search/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Search/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Search/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile-json.common delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile-project-defines delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile-project-targets delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile-project-testing delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile-template-defines delete mode 120000 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/Makefile.common delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/README.md delete mode 100755 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/run-cbmc-proofs.py delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipCollection/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipCollection/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipCollection/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipCollection/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipCollection/skipCollection_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipEscape/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipEscape/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipEscape/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipEscape/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipEscape/skipEscape_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipNumber/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipNumber/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipNumber/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipNumber/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipNumber/skipNumber_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpace/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpace/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpace/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpace/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpace/skipSpace_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpaceAndComma/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpaceAndComma/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpaceAndComma/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpaceAndComma/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipSpaceAndComma/skipSpaceAndComma_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipString/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipString/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipString/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipString/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipString/skipString_harness.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipUTF8/Makefile delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipUTF8/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipUTF8/cbmc-proof.txt delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipUTF8/cbmc-viewer.json delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipUTF8/skipUTF8_harness.c delete mode 120000 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/sources/README.md delete mode 120000 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/README.md delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipAnyLiteral.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipCollection.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipDigits.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipEscape.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipNumber.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipSpaceAndComma.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipString.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/unit-test/catch_assert.h delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/test/unit-test/core_json_utest.c delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/tools/coverity/misra.config delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/tools/uncrustify.cfg delete mode 100644 kws/ota/ota_for_aws/source/dependency/coreJSON/tools/unity/project.yml delete mode 100644 kws/ota/ota_for_aws/source/include/ota.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_appversion32.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_base64_private.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_cbor_private.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_config_defaults.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_http_interface.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_http_private.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_interface_private.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_mqtt_interface.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_mqtt_private.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_os_interface.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_platform_interface.h delete mode 100644 kws/ota/ota_for_aws/source/include/ota_private.h delete mode 100644 kws/ota/ota_for_aws/source/include/stdbool.readme delete mode 100644 kws/ota/ota_for_aws/source/include/stdint.readme delete mode 100644 kws/ota/ota_for_aws/source/ota.c delete mode 100644 kws/ota/ota_for_aws/source/ota_base64.c delete mode 100644 kws/ota/ota_for_aws/source/ota_cbor.c delete mode 100644 kws/ota/ota_for_aws/source/ota_http.c delete mode 100644 kws/ota/ota_for_aws/source/ota_interface.c delete mode 100644 kws/ota/ota_for_aws/source/ota_mqtt.c delete mode 100644 kws/ota/ota_for_aws/source/portable/os/ota_os_freertos.c delete mode 100644 kws/ota/ota_for_aws/source/portable/os/ota_os_freertos.h delete mode 100644 kws/ota/ota_for_aws/source/portable/os/ota_os_posix.c delete mode 100644 kws/ota/ota_for_aws/source/portable/os/ota_os_posix.h create mode 100644 kws/source/peripheral_memmap.h create mode 100644 lib/AWS/CMakeLists.txt create mode 100644 lib/AWS/FreeRTOS-Plus-TCP/CMakeLists.txt create mode 100644 lib/AWS/aws-iot-device-sdk-fetch.cmake create mode 100644 lib/AWS/backoff_algorithm/CMakeLists.txt create mode 100644 lib/AWS/coreHTTP/CMakeLists.txt create mode 100644 lib/AWS/coreJSON/CMakeLists.txt create mode 100644 lib/AWS/coreMQTT-Agent/CMakeLists.txt create mode 100644 lib/AWS/coreMQTT/CMakeLists.txt create mode 100644 lib/AWS/corePKCS11/CMakeLists.txt create mode 100644 lib/AWS/mbedtls/CMakeLists.txt create mode 100644 lib/AWS/ota_for_aws/CMakeLists.txt rename ci/build_examples.sh => lib/AWS/patches/apply.sh (70%) mode change 100755 => 100644 create mode 100644 lib/AWS/patches/ota_for_aws.patch create mode 100644 lib/AWS/patches/tinycbor.patch create mode 100644 lib/AWS/tinycbor/CMakeLists.txt delete mode 160000 lib/amazon_freertos create mode 100644 lib/lwip/CMakeLists.txt create mode 100644 lib/lwip/lwip-fetch.cmake delete mode 160000 lib/mbedcrypto delete mode 160000 lib/mcuboot delete mode 160000 lib/ml-embedded-evaluation-kit delete mode 160000 lib/tf-m delete mode 160000 lib/tfm_test delete mode 100644 patches/.gitignore delete mode 100644 patches/VHT.patch delete mode 100644 patches/amazon_freertos.patch delete mode 100755 patches/clean.py delete mode 100644 patches/mbedcrypto.patch create mode 100644 patches/tf-m.patch delete mode 100644 patches/tf-m/0001-WIP-Fix-system-reset-issue-with-MPCs.patch delete mode 100644 patches/tf-m/0002-WIP-Startup-AN547-NS-side-in-priveleged-mode.patch delete mode 100644 patches/tf-m/0003-WIP-Add-first-files-of-tfm-extra.patch delete mode 100644 patches/tf-m/0004-Update-platform-AN547.patch delete mode 100644 patches/tf-m/0005-Import-AWS-MQTT-mutual-authentication-demo-on-FVP.patch delete mode 100644 patches/tf-m/0006.patch delete mode 100644 scripts/ARM.DevSummitDemo.pack.desc delete mode 100755 scripts/make_cmsis_pack.sh delete mode 100755 scripts/sign_binaries.sh delete mode 100755 scripts/sign_update_binaries.sh delete mode 100644 tfm.blinky_ns.cprj delete mode 100644 tfm.blinky_ns.uvoptx delete mode 100644 tfm.blinky_ns.uvprojx delete mode 100644 tfm.bootloader.cprj delete mode 100644 tfm.bootloader.uvoptx delete mode 100644 tfm.bootloader.uvprojx delete mode 100644 tfm.kws_ns.cprj delete mode 100644 tfm.kws_ns.uvoptx delete mode 100644 tfm.kws_ns.uvprojx delete mode 100644 tfm.secure.cprj delete mode 100644 tfm.secure.uvoptx delete mode 100644 tfm.secure.uvprojx diff --git a/.gitignore b/.gitignore index 0459097..ce8dd97 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ tfz **/ota_build **/cmake-build-debug **/.idea + +# build dirs +lib/tf-m-build/ diff --git a/.gitmodules b/.gitmodules index eded360..74fa1fe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,22 +1,3 @@ -[submodule "lib/amazon_freertos"] - path = lib/amazon_freertos - url = https://github.com/aws/amazon-freertos.git -[submodule "lib/mbedcrypto"] - path = lib/mbedcrypto - url = https://github.com/ARMmbed/mbedtls.git -[submodule "lib/mcuboot"] - path = lib/mcuboot - url = https://github.com/mcu-tools/mcuboot.git -[submodule "lib/tf-m"] - path = lib/tf-m - url = https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git - branch = master -[submodule "lib/tfm_test"] - path = lib/tfm_test - url = https://git.trustedfirmware.org/TF-M/tf-m-tests.git [submodule "lib/VHT"] path = lib/VHT url = https://github.com/ARM-software/VHT -[submodule "lib/ml-embedded-evaluation-kit"] - path = lib/ml-embedded-evaluation-kit - url = https://review.mlplatform.org/ml/ethos-u/ml-embedded-evaluation-kit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..81c4ff1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,149 @@ +# Copyright (c) 2021 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.21) + +include(ExternalProject) +include(FetchContent) + +# Declare root and other build paths +set(PRJ_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + +# Declare relative path to TFM target +# Underscore are used to accomodate TF-M conversion in install folder from dash +# to underscore +set(TFM_PLATFORM_LOCAL_PATH "bsp/tf_m_targets/arm/mps3/an547") + +# Declare the Open IoT SDK +FetchContent_Declare( + open_iot_sdk + GIT_REPOSITORY https://git.gitlab.arm.com/iot/open-iot-sdk/sdk.git + GIT_TAG v2022.01 +) + +# Declare the Open IoT SDK configuration flags +set(IOTSDK_FREERTOS ON) +set(IOTSDK_TFM ON) +set(IOTSDK_ML ON) +set(IOTSDK_CMSIS_RTOS_API ON) +set(IOTSDK_MDH_ARM ON) +set(FETCHCONTENT_QUIET OFF) +set(TFM_PLATFORM "${CMAKE_CURRENT_SOURCE_DIR}/${TFM_PLATFORM_LOCAL_PATH}") +set(TFM_PSA_API OFF) +set(TFM_PARTITION_FIRMWARE_UPDATE ON) + +# Extra arguments for TF-M and ML +set(TFM_CMAKE_ARGS "-DNS=OFF;-DPLATFORM_DEFAULT_UART_STDOUT=ON;-DMCUBOOT_SIGNATURE_KEY_LEN=2048;-DTFM_SYSTEM_FP=2;-DTFM_SYSTEM_FP_NS=2;-DTFM_SYSTEM_FPU=2;-DTFM_PARTITION_AUDIT_LOG=ON;-DITS_MAX_ASSET_SIZE=1300;-DCRYPTO_ENGINE_BUF_SIZE=0x8000") +set(ML_CMAKE_ARGS "-Dkws_LABELS_TXT_FILE=resources/kws/labels/ds_cnn_labels.txt;-Dkws_MODEL_TFLITE_PATH=resources_downloaded/kws/ds_cnn_clustered_int8_vela_H128.tflite;-DUSE_CASE_BUILD=kws;-Dkws_ACTIVATION_BUF_SZ=0x00400000") + +# Set library to std +set(MBED_C_LIB "std") + +# Set FVP variant +set(VARIANT "FVP") + +# Apply TF-M patch +find_package(Git) +set(TFM_PATCH_COMMAND ${GIT_EXECUTABLE} apply "${PRJ_DIR}/patches/tf-m.patch" || true) +set(ML_PATCH_COMMAND ${GIT_EXECUTABLE} apply "${PRJ_DIR}/patches/ml-embedded-evaluation-kit.patch" || true) + +# Make the Open IoT SDK available +FetchContent_MakeAvailable(open_iot_sdk) + +# get paths for the ml kit + +ExternalProject_Get_Property(ml-embedded-evaluation-kit SOURCE_DIR) +ExternalProject_Get_Property(ml-embedded-evaluation-kit BINARY_DIR) +set(ml-embedded-evaluation-kit_SOURCE_DIR "${SOURCE_DIR}") +set(ml-embedded-evaluation-kit_BINARY_DIR "${BINARY_DIR}") +set(ml-embedded-evaluation-kit_GENERATED_DIR "${ml-embedded-evaluation-kit_BINARY_DIR}/generated") +set(ml-embedded-evaluation-kit_LIB_DIR ${ml-embedded-evaluation-kit_BINARY_DIR}/lib) + +# Setup project + +# Start of the project +project(tfm_ns LANGUAGES C CXX) + +# Include module path from Open IoT SDK +list(APPEND CMAKE_MODULE_PATH ${open_iot_sdk_SOURCE_DIR}/components/TF-M) +list(APPEND CMAKE_MODULE_PATH ${open_iot_sdk_SOURCE_DIR}/cmake) + +# Configuration of executable +set(EXE_SUFFIX ".axf") +set(CMAKE_EXECUTABLE_SUFFIX ${EXE_SUFFIX}) + +# Include modules from the SDK +include(ElfToBin) +include(TfmSignImage) + +# Test management +include(CTest) + +# Patch the FreeRTOS target to match config requirements +target_include_directories(freertos-kernel + INTERFACE + ${PRJ_DIR}/bsp/aws_configs + ${PRJ_DIR}/bsp/freertos-platform + ${PRJ_DIR}/kws/include +) + +# Compilation Database +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +add_custom_target(database COMMAND ${CMAKE_COMMAND} -E copy_if_different "${INT_DIR}/compile_commands.json" "${CMAKE_BINARY_DIR}") + +# handle libraries +set(MQTT_CONFIG_PATH ${PRJ_DIR}/bsp/aws_configs) +set(HTTP_CONFIG_PATH ${PRJ_DIR}/bsp/aws_configs) +set(PKCS11_CONFIG_PATH ${PRJ_DIR}/bsp/aws_configs) +set(MBEDTLS_CONFIG_PATH ${PRJ_DIR}/bsp/aws_libraries/3rdparty/mbedtls_config) + +add_subdirectory(lib/lwip) +add_subdirectory(lib/AWS) +add_subdirectory(bsp) + +# Setup Target + +set(CMAKE_EXECUTABLE_SUFFIX ${EXE_SUFFIX}) + +# Add examples targets +add_subdirectory(kws) +add_subdirectory(blinky) + +# Copy tf-m binaries at the root +ExternalProject_Get_Property(tf-m BINARY_DIR) +ExternalProject_Get_Property(tf-m SOURCE_DIR) +add_custom_target(tfm-binaries + BYPRODUCTS + ${CMAKE_BINARY_DIR}/bootloader/bl2.axf + ${CMAKE_BINARY_DIR}/secure_partition/tfm_s.axf + ${CMAKE_BINARY_DIR}/secure_partition/tfm_s_unsigned.bin + ${CMAKE_BINARY_DIR}/secure_partition/tfm_s_signed.bin + + COMMAND ${CMAKE_COMMAND} -E copy + ${BINARY_DIR}/install/outputs/$/bl2.axf + "${CMAKE_CURRENT_BINARY_DIR}/bootloader/bl2.axf" + + COMMAND ${CMAKE_COMMAND} -E copy + ${BINARY_DIR}/install/outputs/$/tfm_s.axf + "${CMAKE_CURRENT_BINARY_DIR}/secure_partition/tfm_s.axf" + + COMMAND + ${ARM_ELF2BIN} --bin --output ${CMAKE_BINARY_DIR}/secure_partition/tfm_s_unsigned.bin ${CMAKE_BINARY_DIR}/secure_partition/tfm_s.axf --bincombined + + COMMAND + python3 ${BINARY_DIR}/install/image_signing/scripts/wrapper/wrapper.py + -v 1.3.0 + --layout ${PRJ_DIR}/bsp/signing_layout_s.c + -k ${SOURCE_DIR}/bl2/ext/mcuboot/root-RSA-2048.pem + --public-key-format full + --align 1 + --pad + --pad-header + -H 0x400 + -s auto + ${CMAKE_BINARY_DIR}/secure_partition/tfm_s_unsigned.bin + ${CMAKE_BINARY_DIR}/secure_partition/tfm_s_signed.bin +) + +add_dependencies(tfm-binaries tf-m) +add_dependencies(tfm-ns-interface tfm-binaries) diff --git a/LICENCE.md b/LICENCE.md index e834636..db14747 100644 --- a/LICENCE.md +++ b/LICENCE.md @@ -3,15 +3,12 @@ as can be found in: LICENSE-apache-2.0.txt Folders containing files under different permissive license than Apache 2.0 are listed below. Each folder should contain its own README file with license specified for its files. The original license text is included in those source files. -- [lib/amazon_freertos](https://github.com/aws/amazon-freertos) - MIT -- [lib/mbedcrypto](https://github.com/ARMmbed/mbedtls) - Apache-2.0 -- [lib/mcuboot](https://github.com/mcu-tools/mcuboot) - Apache-2.0 -- [lib/ml-embedded-evaluation-kit](https://review.mlplatform.org/plugins/gitiles/ml/ethos-u/ml-embedded-evaluation-kit) - Apache-2.0 -- [lib/tf-m](https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git) - BSD-3-Clause -- [lib/tfm_test](https://git.trustedfirmware.org/TF-M/tf-m-tests.git) - BSD-3-Clause +- [bsp/aws_configs](https://github.com/aws/amazon-freertos) - MIT +- [bsp/aws_libraries](https://github.com/aws/amazon-freertos) - MIT +- [lib/aws](https://github.com/aws/aws-iot-device-sdk-embedded-C) - MIT +- [lib/lwip](https://github.com/lwip-tcpip/lwip) - BSD-3-Clause +- [bsp/tf_m_targets](https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git) - BSD-3-Clause - [lib/VHT](https://github.com/ARM-software/VHT) - Apache-2.0 -- [tinycbor](kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor) - MIT License -- [coreJSON](kws/ota/ota_for_aws/source/dependency/coreJSON) - MIT License -- [tfm test service](bsp/test_services) - BSD-3-Clause -- [tfm secure fw](bsp/secure_fw) - BSD-3-Clause -- [tfm interface](bsp/interface) - BSD-3-Clause +- [Open IoT SDK](https://gitlab.oss.arm.com/engineering/iot-m-sw/open-iot-sdk/sdk) - Apache-2.0 +- [bsp/freertos-platform](bsp/freertos-platform/portmacro.h) - Apache-2.0 +- [bsp/freertos-platform/portmacro.h](bsp/freertos-platform/portmacro.h) - MIT diff --git a/README.md b/README.md index ac43072..553ad52 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ This repo contains Arm's first [IoT Total Solution](https://www.arm.com/solution The software supports multiple configurations of the Arm Corstone™-300 subsystem, incorporating the Cortex-M55 processor and Arm Ethos™-U55 microNPU. This total solution provides the complex, non differentiated secure platform software on behalf of the ecosystem, thus enabling you to focus on your next killer app. -This repo also supports a GitHub runner CI/CD workflow right out of the box which leverages [Arm Virtual Hardware](https://www.arm.com/virtual-hardware), a simulation environment that enables software development without the need of physical SoCs. - ## Keyword detection application The keyword detection application runs the DS-CNN model on top of [AWS FreeRTOS](https://docs.aws.amazon.com/freertos/). It detects keywords and inform the user of which keyword has been spotted. The audio data to process are injected at run time using the [Arm Virtual Hardware](https://www.arm.com/virtual-hardware) audio driver. @@ -138,9 +136,6 @@ pytest -s kws/tests To build, run and launch a test of the blinky application, replace `kws` by `blinky`. -Alternatively, the projects can be build using [Keil MDK](https://www.arm.com/products/development-tools/embedded-and-software/keil-mdk). -`blinky.uvmpw` and `kws.uvmpw` contains respectively the `blinky` and `kws` project. - ## Updating audio data The audio data streamed into the Arm Virtual Hardware is read from the file `test.wav` located at the root of the repository. It can be replaced with another audio file with the following configuration: @@ -151,66 +146,7 @@ The audio data streamed into the Arm Virtual Hardware is read from the file `tes # Continuous integration setup -Follow these simple steps to setup a GitHub continuous integration pipeline in a mirror of this repository. - -1. Mirror the repository -```sh -# create a mirror (assumes new repo is already created https://docs.github.com/en/articles/creating-a-new-repository) -git clone --bare https://github.com/ARM-software/ATS-Keyword -cd ATS-Keyword -git push --mirror https://github.com/exampleuser/my-ats-keyword.git - -cd .. - -# clone your new repo -git clone https://github.com/exampleuser/my-ats-keyword.git - -# optionally remove the original repo from your hard drive -rm -rf ATS-Keyword -``` - -2. Launch Arm Virtual Hardware Instance - - To utilize the Arm Virtual Hardware, you will need to create an AWS Account if you don’t already have one. - -```sh -./scripts/vht_cli.py -k start -``` - -3. Launch GitHub Self-Hosted Runner - -```sh -# Login to the ami -ssh ubuntu@ -``` - -Follow your repo's instructions to configure the github self hosted runner on the Arm Virtual Hardware ec2 instance -https://github.com/exampleuser/my-ats-keyword.git/settings/actions/runners/new . The runner process must be launched in detached state (`&` at the end of the command) to persist after the SSH session. - -```sh -# exit the ami and return shell back to your desktop -exit -``` - -4. Trigger the GitHub Runner. - -A first run of the existing action should start right away. Any change to the -repository will trigger a new run. - -```sh -# make a trivial (whitespace) code change and watch the code example compile and -# run test cases on Arm Virtual Hardware on your ec2 instance. - -# add whitespace to this file -vim .github/workflows/avh.yml - -# git push it -git add .github/workflows/avh.yml -git commit -m "initial arm virtual hardware github runner test" -git push origin main -``` - -Refer to GitHub actions [documentation](https://docs.github.com/en/actions) to make additional changes to the workflow. +Step by step instructions on how to setup a continuous integration pipeline in GitHub are provided in a mirror of this repository located at https://github.com/ARM-software/ATS-Keyword. # Setting up AWS connectivity @@ -283,7 +219,7 @@ The application includes OTA update functionality. The application will check fo ## Creating updated firmware -As part of the example build process an updated firmware will be created that will only differ in version number. That is enough to demonstrate the OTA process. If you want to add other changes you will have to copy the non-updated binary elsewhere before running the build again with your changes as the same build is used for both. The update binary is placed in `build/kws/tfm_ns_signed_update.bin`. This is already signed and is the file you will need to upload to a AWS bucket in the next section. +As part of the example build process an updated firmware will be created that will only differ in version number. That is enough to demonstrate the OTA process. If you want to add other changes you will have to copy the non-updated binary elsewhere before running the build again with your changes as the same build is used for both. The update binary is placed in `build/kws/kws_signed_update.bin`. This is already signed and is the file you will need to upload to a AWS bucket in the next section. Upon completion of the build and sign process the signature string will be echoed. This will be needed in the next step. @@ -301,7 +237,7 @@ Upon completion of the build and sign process the signature string will be echoe 10. Paste the signature string that is echoed during the build of the example (it is also available in `build/kws/update-signature.txt`). 11. Select `SHA-256` and `RSA` algorithms. 12. For **Path name of code signing certificate on device** put in `0` (the path is not used) -13. Select upload new file and select the signed update binary (`build/kws/tfm_ns_signed_update.bin`) +13. Select upload new file and select the signed update binary (`build/kws/kws_signed_update.bin`) 14. Select the S3 bucket you created in step 1. to upload the binary to 15. For **Path name of file on device** put in `non_secure image` 16. As the role, select the OTA role you created in step 2. @@ -389,7 +325,6 @@ With ML Eval Kit you can run inferences on either a custom neural network on Eth | Repository | Description | |---------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [Arm AI Ecosystem Catalog](https://www.arm.com/why-arm/partner-ecosystem/ai-ecosystem-catalog) | Connects you to the right partners, enabling you to build the next generation of AI solutions | -| [Arm CMSIS Build](https://arm-software.github.io/CMSIS_5/Build/html/index.html) | Documentation for the build system used by applications in this repository. | | [Arm IoT Ecosystem Catalog](https://www.arm.com/why-arm/partner-ecosystem/iot-ecosystem-catalog) | Explore Arm IoT Ecosystem partners who can help transform an idea into a secure, market-leading device. | | [Arm ML Model Zoo](https://github.com/ARM-software/ML-zoo) | A collection of machine learning models optimized for Arm IP. | | [Arm Virtual Hardware Documentation](https://mdk-packs.github.io/VHT-TFLmicrospeech/overview/html/index.html) | Documentation for [Arm Virtual Hardware](https://www.arm.com/products/development-tools/simulation/virtual-hardware) | diff --git a/blinky.uvmpw b/blinky.uvmpw deleted file mode 100644 index be52780..0000000 --- a/blinky.uvmpw +++ /dev/null @@ -1,23 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - WorkSpace - - - .\tfm.bootloader.uvprojx - - - - .\tfm.secure.uvprojx - - - - .\tfm.blinky_ns.uvprojx - 1 - - -
diff --git a/blinky/CMakeLists.txt b/blinky/CMakeLists.txt new file mode 100644 index 0000000..9c01c64 --- /dev/null +++ b/blinky/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.21) + +# Declare the blinky executable +add_executable(blinky + "${PRJ_DIR}/blinky/freertos_adaptation.c" + "${PRJ_DIR}/blinky/main_ns.c" +) + +target_link_libraries(blinky + startup + lib-bsp + tfm-ns-interface-cmsis-rtos + freertos-kernel-heap-4 + mcu-driver-hal + cmsis-rtos-api + freertos-cmsis-rtos + freertos-kernel +) + +# Copy the result of TF-M build in the top level build directory +# Convert axf files into bin +# Sign binaries +ExternalProject_Get_Property(tf-m BINARY_DIR) +ExternalProject_Get_Property(tf-m SOURCE_DIR) +add_custom_command( + TARGET + blinky + POST_BUILD + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/blinky.axf + + BYPRODUCTS + ${CMAKE_CURRENT_BINARY_DIR}/blinky_unsigned.bin + ${CMAKE_CURRENT_BINARY_DIR}/blinky_signed.bin + + COMMAND + ${ARM_ELF2BIN} --bin --output ${CMAKE_CURRENT_BINARY_DIR}/blinky_unsigned.bin ${CMAKE_CURRENT_BINARY_DIR}/blinky.axf --bincombined + + COMMAND + python3 ${BINARY_DIR}/install/image_signing/scripts/wrapper/wrapper.py + -v 1.0.0 + --layout ${PRJ_DIR}/bsp/signing_layout_ns.c + -k ${BINARY_DIR}/install/image_signing/keys/root-RSA-2048_1.pem + --public-key-format full + --align 1 + --pad + --pad-header + -H 0x400 + -s auto + ${CMAKE_CURRENT_BINARY_DIR}/blinky_unsigned.bin + ${CMAKE_CURRENT_BINARY_DIR}/blinky_signed.bin +) + +add_test( + NAME blinky-test + COMMAND pytest -s blinky/tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND_EXPAND_LISTS +) diff --git a/blinky/main_ns.c b/blinky/main_ns.c index 1fc939c..b604d0f 100644 --- a/blinky/main_ns.c +++ b/blinky/main_ns.c @@ -19,7 +19,7 @@ #include "task.h" #include "tfm_ns_interface.h" #include "psa/protected_storage.h" -#include "serial.h" +#include "bsp_serial.h" /* * Semihosting is a mechanism that enables code running on an ARM target @@ -62,7 +62,7 @@ static void blink_task( void *pvParameters ) int main() { tfm_ns_interface_init(); - serial_init(); + bsp_serial_init(); xTaskCreate(blink_task, "test task", configMINIMAL_STACK_SIZE*2, NULL, configMAX_PRIORITIES-2, NULL); diff --git a/blinky/tests/test_blinky.py b/blinky/tests/test_blinky.py index f956425..1cee33c 100644 --- a/blinky/tests/test_blinky.py +++ b/blinky/tests/test_blinky.py @@ -25,7 +25,7 @@ def fvp_path(): @pytest.fixture def binary_path(): - yield os.path.dirname(os.path.abspath(__file__)) + '/../../build' + yield os.path.dirname(os.path.abspath(__file__)) + '/../../build/blinky' @pytest.fixture def vsi_script_path(): @@ -39,15 +39,15 @@ def fvp(fvp_path, binary_path, vsi_script_path): # Note: It can take few seconds to terminate the FVP cmdline = [ fvp_path, - '-a', f'cpu_core.cpu0*={binary_path}/bootloader/bl2.axf', - '--data', f'{binary_path}/secure_partition/tfm_s_signed.bin@0x38000000', - '--data', f'{binary_path}/blinky/tfm_ns_signed.bin@0x28060000', - '-C', 'cpu_core.mps3_board.visualisation.disable-visualisation=1', - '-C', 'cpu_core.mps3_board.telnetterminal0.start_telnet=0', - '-C', 'cpu_core.mps3_board.uart0.out_file=-', - '-C', 'cpu_core.mps3_board.uart0.unbuffered_output=1', - '-C', 'cpu_core.mps3_board.uart0.shutdown_on_eot=1', - '-C', 'cpu_core.cpu0.semihosting-enable=1', + '-a', f'cpu0*={binary_path}/../bootloader/bl2.axf', + '--data', f'{binary_path}/../secure_partition/tfm_s_signed.bin@0x38000000', + '--data', f'{binary_path}/blinky_signed.bin@0x28060000', + '-C', 'mps3_board.visualisation.disable-visualisation=1', + '-C', 'mps3_board.telnetterminal0.start_telnet=0', + '-C', 'mps3_board.uart0.out_file=-', + '-C', 'mps3_board.uart0.unbuffered_output=1', + '-C', 'mps3_board.uart0.shutdown_on_eot=1', + '-C', 'cpu0.semihosting-enable=1', '-V', f'{vsi_script_path}' ] proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE) @@ -59,7 +59,7 @@ def test_blinky(fvp): # Traces expected in the output expectations = [ 'Starting bootloader', - 'Booting TFM v1.3.0', + 'Booting TFM v1.4.1', 'FreeRTOS blink task started', 'LED on', 'LED off', diff --git a/bsp/CMakeLists.txt b/bsp/CMakeLists.txt new file mode 100644 index 0000000..42b246a --- /dev/null +++ b/bsp/CMakeLists.txt @@ -0,0 +1,198 @@ +# Copyright (c) 2021 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.18) + +set(LIB_NAME lib-bsp) + +add_library(${LIB_NAME} STATIC) + +target_include_directories(${LIB_NAME} + PRIVATE + ${freertos-plus-tcp_SOURCE_DIR}/include + ${freertos-plus-tcp_SOURCE_DIR}/portable/Compiler/GCC + ${aws-iot-device-sdk_SOURCE_DIR}/libraries/standard/corePKCS11/source/dependency/3rdparty/mbedtls_utils + ${aws-iot-device-sdk_SOURCE_DIR}/libraries/standard/corePKCS11/source/dependency/3rdparty/pkcs11 + ${aws-iot-device-sdk_SOURCE_DIR}/libraries/standard/corePKCS11/source/include + ${PRJ_DIR}/kws + ${PRJ_DIR}/kws/include + ${PRJ_DIR}/kws/ota/ota_pal_psa + ${PRJ_DIR}/kws/ota/ota_pal_psa/version + ${PRJ_DIR}/kws/ota/provision + ${PRJ_DIR}/lib/tf-m + ${PRJ_DIR}/lib/tf-m/interface/include + ${PRJ_DIR}/lib/tf-m/interface/include/psa + ${PRJ_DIR}/lib/tf-m/platform/ext + ${PRJ_DIR}/lib/tf-m/platform/ext/cmsis + ${PRJ_DIR}/lib/tf-m/platform/ext/common + ${PRJ_DIR}/lib/tf-m/platform/ext/driver + ${PRJ_DIR}/lib/tf-m/platform/include + ${PRJ_DIR}/lib/tfm_test/ns_interface + PUBLIC + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547 + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/cmsis_drivers + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/cmsis_drivers/config + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/device + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/device/config + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/device/include + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/device/source/armclang + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/native_drivers + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/partition + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/an547/services/src + ${TFM_PLATFORM_TARGET_DIR}/arm/mps3/common + ${PRJ_DIR}/bsp/aws_configs + ${PRJ_DIR}/bsp/aws_libraries/3rdparty/jsmn + ${PRJ_DIR}/bsp/aws_libraries/3rdparty/mbedtls_config + ${PRJ_DIR}/bsp/aws_libraries/3rdparty/mbedtls_utils + ${PRJ_DIR}/bsp/aws_libraries/3rdparty/mbedtls/include + ${PRJ_DIR}/bsp/aws_libraries/3rdparty/pkcs11 + ${PRJ_DIR}/bsp/aws_libraries/abstractions/backoff_algorithm/source/include + ${PRJ_DIR}/bsp/aws_libraries/abstractions/mqtt_agent/include + ${PRJ_DIR}/bsp/aws_libraries/abstractions/pkcs11/psa + ${PRJ_DIR}/bsp/aws_libraries/abstractions/platform/freertos/include + ${PRJ_DIR}/bsp/aws_libraries/abstractions/platform/freertos/include/platform + ${PRJ_DIR}/bsp/aws_libraries/abstractions/platform/include + ${PRJ_DIR}/bsp/aws_libraries/abstractions/platform/include/platform + ${PRJ_DIR}/bsp/aws_libraries/abstractions/platform/include/types + ${PRJ_DIR}/bsp/aws_libraries/abstractions/secure_sockets/include + ${PRJ_DIR}/bsp/aws_libraries/abstractions/transport/secure_sockets + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/common/include + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/common/include/private + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/common/include/types + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/https/include + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/mqtt/include + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/mqtt/include/types + ${PRJ_DIR}/bsp/aws_libraries/c_sdk/standard/mqtt/src/private + ${PRJ_DIR}/bsp/aws_libraries/coreHTTP/source/dependency/3rdparty/http_parser + ${PRJ_DIR}/bsp/aws_libraries/coreHTTP/source/include + ${PRJ_DIR}/bsp/aws_libraries/coreHTTP/source/interface + ${PRJ_DIR}/bsp/aws_libraries/coreMQTT-Agent/source/include + ${PRJ_DIR}/bsp/aws_libraries/coreMQTT/source/include + ${PRJ_DIR}/bsp/aws_libraries/coreMQTT/source/interface + ${PRJ_DIR}/bsp/aws_libraries/demos/common/http_demo_helpers + ${PRJ_DIR}/bsp/aws_libraries/demos/common/mqtt_demo_helpers + ${PRJ_DIR}/bsp/aws_libraries/demos/common/mqtt_subscription_manager + ${PRJ_DIR}/bsp/aws_libraries/demos/common/ota_demo_helpers + ${PRJ_DIR}/bsp/aws_libraries/demos/common/pkcs11_helpers + ${PRJ_DIR}/bsp/aws_libraries/demos/coreMQTT_Agent + ${PRJ_DIR}/bsp/aws_libraries/demos/dev_mode_key_provisioning/include + ${PRJ_DIR}/bsp/aws_libraries/demos/network_manager + ${PRJ_DIR}/bsp/aws_libraries/freertos_plus/aws/ota/include + ${PRJ_DIR}/bsp/aws_libraries/freertos_plus/aws/ota/src + ${PRJ_DIR}/bsp/aws_libraries/freertos_plus/aws/ota/src/http + ${PRJ_DIR}/bsp/aws_libraries/freertos_plus/aws/ota/src/mqtt + ${PRJ_DIR}/bsp/aws_libraries/freertos_plus/standard/crypto/include + ${PRJ_DIR}/bsp/aws_libraries/freertos_plus/standard/tls/include + ${PRJ_DIR}/bsp/aws_libraries/logging/include + ${PRJ_DIR}/bsp/aws_libraries/3rdparty/lwip_osal/include + ${PRJ_DIR}/bsp/freertos-platform +) + +target_sources(${LIB_NAME} + PRIVATE + "${PRJ_DIR}/bsp/freertos-platform/application_helpers.c" + "${PRJ_DIR}/bsp/freertos-platform/print_log.c" +) + +target_link_libraries(${LIB_NAME} + PRIVATE + FreeRTOS-Plus-TCP + freertos-kernel + tfm-ns-interface +) + +target_compile_definitions(${LIB_NAME} + PRIVATE + -DACTIVATION_BUF_SRAM_SZ=0x00400000 + -DACTIVATION_BUF_SZ=0x00400000 + -DARM_MATH_DSP + -DARM_MATH_LOOPUNROLL + -DARM_MATH_MVEI + -DARM_NPU=1 + -DBL2 + -DCONFIG_KWS_SCORE_THRESHOLD=0.8 + -DCPU_CORTEX_M55=1 + -DDAUTH_CHIP_DEFAULT + -DLIBRARY_LOG_LEVEL=3 + -DMBEDTLS_CONFIG_FILE=\"\" + -DMCUBOOT_DATA_SHARING=1 + -DMCUBOOT_IMAGE_NUMBER=2 + -DMCUBOOT_SIGN_RSA + -DMCUBOOT_SIGN_RSA_LEN=2048 + -DMPS3_PLATFORM=1 + -DTFM_PARTITION_AUDIT_LOG + -DTFM_PARTITION_CRYPTO + -DTFM_PARTITION_FIRMWARE_UPDATE + -DTFM_PARTITION_INITIAL_ATTESTATION + -DTFM_PARTITION_INTERNAL_TRUSTED_STORAGE + -DTFM_PARTITION_LOG_LEVEL=TFM_PARTITION_LOG_LEVEL_DEBUG + -DTFM_PARTITION_PLATFORM + -DTFM_PARTITION_PROTECTED_STORAGE + -DTFM_SPM_LOG_LEVEL=0 + -DTFM_SYSTEM_FP=2 + -DTFM_SYSTEM_FP_NS=2 +) + +# BSP serial library + +add_library(bsp_serial STATIC) + +target_sources(bsp_serial + PRIVATE + "${PRJ_DIR}/bsp/freertos-platform/bsp_serial.c" +) + +target_include_directories(bsp_serial + PUBLIC + ${PRJ_DIR}/bsp/freertos-platform +) + +target_link_libraries(bsp_serial + PRIVATE + mcu-driver-hal +) + +target_link_libraries(${LIB_NAME} + PRIVATE + bsp_serial +) + +target_compile_options(${LIB_NAME} + PRIVATE + --target=arm-arm-none-eabi + -Ofast + -Wall + -Wno-error=cpp + -Wno-ignored-optimization-argument + -Wno-unused-command-line-argument + -c + -fdata-sections + -ffunction-sections + -fno-builtin + -funsigned-char + -g + -masm=auto + -mcpu=cortex-m55+fp+mve + -mfloat-abi=hard + -nostdlib + -std=c11 +) + +# Add Startup library +add_library(startup + "${TFM_PLATFORM}/device/source/startup_an547_ns.c" +) + +mbed_set_linker_script(startup "${PRJ_DIR}/bsp/an547_ns.sct") + +ExternalProject_Get_Property(tf-m SOURCE_DIR) +target_include_directories(startup + PRIVATE + "${SOURCE_DIR}/platform/include" +) + +target_link_libraries(startup + PUBLIC + tfm-ns-interface + mcu-driver-hal +) diff --git a/bsp/an547_bl2.sct b/bsp/an547_bl2.sct index 9ffa7c8..4fc3e7b 100644 --- a/bsp/an547_bl2.sct +++ b/bsp/an547_bl2.sct @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2021-2022 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ LR_CODE (0x10000000) { ER_CODE (0x10000000) ((0x00080000)) { diff --git a/bsp/an547_ns.sct b/bsp/an547_ns.sct index 31c73bf..1766381 100644 --- a/bsp/an547_ns.sct +++ b/bsp/an547_ns.sct @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2021-2022 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + LR_CODE (0x28000000 + ((((0) + (0x60000)) + (0x400)))) { ER_CODE (0x28000000 + ((((0) + (0x60000)) + (0x400)))) { ;(((0x200000) - (0x400) - (0x800))) { *.o (RESET +First) diff --git a/bsp/aws_configs/FreeRTOSConfig.h b/bsp/aws_configs/FreeRTOSConfig.h index fa859e9..560173b 100644 --- a/bsp/aws_configs/FreeRTOSConfig.h +++ b/bsp/aws_configs/FreeRTOSConfig.h @@ -28,9 +28,18 @@ /* Here is a good place to include header files that are required across your application. */ -//#include "something.h" -#include "system_core_init.h" -//#include "stdio.h" +#include +#include "aws_secure_sockets_config.h" + +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif + + +extern uint32_t SystemCoreClock; #define configENABLE_FPU 0 #define configENABLE_MPU 0 @@ -67,7 +76,7 @@ extern void print_log( const char *format, ... ); // somehow 300 tick per second gives similar timing (~85%) as 1000 did on the FPGA, so with this 1 ms to 1 tick can be kept... #define configTICK_RATE_HZ ( ( TickType_t ) 300 ) /* Scheduler polling rate of 1000 Hz */ #define configMS_TO_RTOS_TICK( ms ) ( ms ) /* Tick rate is 1000 Hz, so 1 tick is 1 ms */ -#define configMAX_PRIORITIES 5 +#define configMAX_PRIORITIES 56 #define configMINIMAL_STACK_SIZE 1024 #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 @@ -102,7 +111,7 @@ extern void print_log( const char *format, ... ); /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 0 +#define configUSE_TRACE_FACILITY 1 #define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Co-routine related definitions. */ @@ -143,14 +152,16 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define INCLUDE_vTaskDelay 1 #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 #define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_eTaskGetState 0 +#define INCLUDE_eTaskGetState 1 #define INCLUDE_xEventGroupSetBitFromISR 1 -#define INCLUDE_xTimerPendFunctionCall 0 -#define INCLUDE_xTaskAbortDelay 0 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 #define INCLUDE_xTaskGetHandle 0 #define INCLUDE_xTaskResumeFromISR 1 +#define INCLUDE_xEventGroupSetBitsFromISR 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 /* Cortex-M specific definitions. */ #ifdef __NVIC_PRIO_BITS @@ -222,4 +233,11 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ # define democonfigDEMO_STACKSIZE ( configMINIMAL_STACK_SIZE*8 ) #endif +/* Map the FreeRTOS port interrupt handlers to their CMSIS standard names. */ +#define xPortPendSVHandler PendSV_Handler +#define vPortSVCHandler SVC_Handler + +/* Ensure Cortex-M port compatibility. */ +#define SysTick_Handler xPortSysTickHandler + #endif /* FREERTOS_CONFIG_H */ diff --git a/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/cc.h b/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/cc.h new file mode 100644 index 0000000..2dfcd89 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/cc.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +/* Include some files for defining library routines */ +#include /* printf, fflush, FILE */ +#include +#include /* abort */ +/*#include */ +#if ( !defined( __CC_ARM ) ) && ( !defined( __ICCARM__ ) ) && ( !defined( __ARMCC_VERSION ) ) + #include +#endif + +#include "FreeRTOSConfig.h" + +#ifndef BYTE_ORDER + #define BYTE_ORDER LITTLE_ENDIAN +#endif + +#define LWIP_PLATFORM_BYTESWAP 0 + +/** @todo fix some warnings: don't use #pragma if compiling with cygwin gcc */ +/*#ifndef __GNUC__ */ +#if ( !defined( __ICCARM__ ) ) && ( !defined( __GNUC__ ) ) && ( !defined( __CC_ARM ) ) + #include + #pragma warning (disable: 4244) /* disable conversion warning (implicit integer promotion!) */ + #pragma warning (disable: 4127) /* conditional expression is constant */ + #pragma warning (disable: 4996) /* 'strncpy' was declared deprecated */ + #pragma warning (disable: 4103) /* structure packing changed by including file */ +#endif + +#if !defined( LWIP_PROVIDE_ERRNO ) && !defined( LWIP_ERRNO_INCLUDE ) && !defined( LWIP_ERRNO_STDINCLUDE ) + #define LWIP_PROVIDE_ERRNO +#endif + +/* Define generic types used in lwIP */ +#define LWIP_NO_STDINT_H 1 +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; + +typedef size_t mem_ptr_t; +typedef u32_t sys_prot_t; + +/* Define (sn)printf formatters for these lwIP types */ +#define X8_F "02x" +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" +#define SZT_F U32_F + +/* Compiler hints for packing structures */ +#if defined( __ICCARM__ ) + #define PACK_STRUCT_BEGIN __packed + #define PACK_STRUCT_STRUCT __packed +#else + #define PACK_STRUCT_STRUCT __attribute__( ( packed ) ) +#endif + +#if 0 + #ifndef LWIP_DEBUG_USE_PRINTF + #define LWIP_LOGE( fmt, arg ... ) LOG_E( lwip, "[lwip]: "fmt, ## arg ) + #define LWIP_LOGW( fmt, arg ... ) LOG_W( lwip, "[lwip]: "fmt, ## arg ) + #define LWIP_LOGI( fmt, arg ... ) LOG_I( lwip, "[lwip]: "fmt, ## arg ) + #endif +#endif + +#ifdef LWIP_DEBUG_USE_PRINTF +/* Plaform specific diagnostic output */ + #define LWIP_PLATFORM_DIAG( x ) do { printf x; } while( 0 ) +#else + #define LWIP_PLATFORM_DIAG( x ) do { configPRINTF( x ); } while( 0 ) +#endif + +#define LWIP_PLATFORM_ASSERT( x ) \ + do { configPRINTF( ( "Assertion \"%s\" failed at line %d in %s\n", \ + x, __LINE__, __FILE__ ) ); fflush( NULL ); abort(); } while( 0 ) + + +#define LWIP_ERROR( message, expression, handler ) \ + do { if( !( expression ) ) { \ + configPRINTF( ( "Assertion \"%s\" failed at line %d in %s\n", message, __LINE__, __FILE__ ) ); \ + handler; } \ + } while( 0 ) + + +/* C runtime functions redefined */ +/*#define snprintf _snprintf //2015-07-22 Cheng Liu @132663 */ + +u32_t dns_lookup_external_hosts_file( const char * name ); + +#define LWIP_RAND() ( ( u32_t ) rand() ) + +#endif /* __ARCH_CC_H__ */ diff --git a/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/perf.h b/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/perf.h new file mode 100644 index 0000000..b1f4f3e --- /dev/null +++ b/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/perf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP( x ) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/sys_arch.h b/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/sys_arch.h new file mode 100644 index 0000000..0ec37b5 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/lwip_osal/include/arch/sys_arch.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_SYS_ARCH_H__ +#define __ARCH_SYS_ARCH_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL ( ( QueueHandle_t ) NULL ) +#define SYS_SEM_NULL ( ( SemaphoreHandle_t ) NULL ) +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef SemaphoreHandle_t sys_sem_t; +typedef SemaphoreHandle_t sys_mutex_t; +typedef TaskHandle_t sys_thread_t; + +struct sys_mbox +{ + QueueHandle_t xMbox; + TaskHandle_t xTask; +}; +typedef struct sys_mbox sys_mbox_t; + +#define sys_mbox_valid( x ) ( ( ( ( x ) == NULL ) || ( ( x )->xMbox == NULL ) ) ? pdFALSE : pdTRUE ) +#define sys_mbox_set_invalid( x ) do { if( ( x ) != NULL ) { ( x )->xMbox = NULL; ( x )->xTask = NULL; } } while( 0 ) +#define sys_sem_valid( x ) ( ( ( * x ) == NULL ) ? pdFALSE : pdTRUE ) +#define sys_sem_set_invalid( x ) ( ( * x ) = NULL ) + +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t * sys_arch_netconn_sem_get( void ); + #define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get() + #define LWIP_NETCONN_THREAD_SEM_ALLOC() + #define LWIP_NETCONN_THREAD_SEM_FREE() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#endif /* __ARCH_SYS_ARCH_H__ */ diff --git a/bsp/aws_libraries/3rdparty/lwip_osal/include/lwipopts_freertos.h b/bsp/aws_libraries/3rdparty/lwip_osal/include/lwipopts_freertos.h new file mode 100644 index 0000000..03dfbe1 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/lwip_osal/include/lwipopts_freertos.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIPOPTS_FREERTOS_H__ +#define __LWIPOPTS_FREERTOS_H__ + +#include "FreeRTOSConfig.h" + +/* tcpip_thread should run on HIGH priority */ +#define TCPIP_THREAD_NAME "lwIP" +#define TCPIP_THREAD_STACKSIZE ( 512 * 4 ) +#define TCPIP_THREAD_PRIO tskIDLE_PRIORITY + 5 + + +#define TCPIP_MBOX_SIZE 16 +#define DEFAULT_RAW_RECVMBOX_SIZE 16 +#define DEFAULT_UDP_RECVMBOX_SIZE 16 +#define DEFAULT_TCP_RECVMBOX_SIZE 16 +#define DEFAULT_ACCEPTMBOX_SIZE 16 + +/*fix http IOT issue */ +#define LWIP_WND_SCALE 1 +#define TCP_RCV_SCALE 1 +#define MEMP_NUM_NETDB 4 + +/* + *----------------------------- + * Socket options + * ---------------------------- + */ +#define LWIP_NETBUF_RECVINFO 1 +#define LWIP_SOCKET 1 + +/*fix reuse address issue */ +#define SO_REUSE 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVTIMEO 1 +/*for ip display */ +#define LWIP_NETIF_STATUS_CALLBACK 1 + +#define ETH_PAD_SIZE 0 + + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 + +/* + * ------------------------------------ + * ---------- Memory options ---------- + * ------------------------------------ + */ + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#define MEM_SIZE ( 10 * 1024 ) + +/* + * ------------------------------------------------ + * ---------- Internal Memory Pool Sizes ---------- + * ------------------------------------------------ + */ + +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 8 + +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + * connections. */ +#define MEMP_NUM_TCP_PCB 32 + +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + * connections. */ +#define MEMP_NUM_TCP_PCB_LISTEN 32 /*16 original */ + +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + * segments. */ +#define MEMP_NUM_TCP_SEG 255 + +/* MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. (requires the ARP_QUEUEING option) */ +#define MEMP_NUM_ARP_QUEUE 8 + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN 32 + + +/* + * ---------------------------------- + * ---------- Pbuf options ---------- + * ---------------------------------- + */ + + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. + * MT7687 packets have extra TXD header and packet offset. */ +#define PBUF_POOL_BUFSIZE ( 1536 + 128 ) + +/* + * --------------------------------- + * ---------- TCP options ---------- + * --------------------------------- + */ + + +/* TCP Maximum segment size. */ +#define TCP_MSS 1476 + +/* TCP sender buffer space (bytes). */ +#define TCP_SND_BUF ( 24 * 1024 ) /*(12 * 1024) */ + +/* TCP receive window. */ +#define TCP_WND ( 24 * 1024 ) + +/* + * --------------------------------- + * ---------- ARP options ---------- + * --------------------------------- + */ + + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#define ARP_QUEUEING 1 + + +/* + * --------------------------------- + * ---------- DHCP options --------- + * --------------------------------- + */ + + +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + * interfaces. */ +#define LWIP_DHCP 1 + +/* 1 if you want to do an ARP check on the offered address + * (recommended). */ + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#define DHCP_DOES_ARP_CHECK 0 + + +/* + * ---------------------------------- + * ---------- DNS options ----------- + * ---------------------------------- + */ + + +#define LWIP_DNS 1 + + +/* + * ------------------------------------------------ + * ---------- Network Interfaces options ---------- + * ------------------------------------------------ + */ + + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#define LWIP_NETIF_LOOPBACK 1 + + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#define LWIP_LOOPBACK_MAX_PBUFS 12 + + +/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per + * thread calling socket/netconn functions instead of allocating one + * semaphore per netconn (and per select etc.) + */ +#define LWIP_NETCONN_SEM_PER_THREAD 1 + +/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, + * writing from a 2nd thread and closing from a 3rd thread at the same time. + * ATTENTION: Some requirements: + * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from + * multiple threads at once + * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox + * and prevent a task pending on this during/after deletion + */ +#define LWIP_NETCONN_FULLDUPLEX 1 + + +/* + * ------------------------------------ + * ----------- Debug options ---------- + * ------------------------------------ + */ + +/*#define LWIP_DEBUG */ +/*#define UDP_DEBUG LWIP_DBG_ON */ +/*#define SOCKETS_DEBUG LWIP_DBG_ON */ +#define NETIF_DEBUG LWIP_DBG_ON +/*#define ETHARP_DEBUG LWIP_DBG_ON */ +/*#define DHCP_DEBUG LWIP_DBG_ON */ +/*#define IP_DEBUG LWIP_DBG_ON */ + + +/* + * Use the errno.h mechanism from FreeRTOS. + */ +#if ( configUSE_POSIX_ERRNO == 1 ) + +/** + * @brief System error variable, errno. + */ + extern int FreeRTOS_errno; + #define errno FreeRTOS_errno +#endif + +#endif /* __LWIPOPTS_FREERTOS_H__ */ diff --git a/bsp/aws_libraries/3rdparty/lwip_osal/src/sys_arch.c b/bsp/aws_libraries/3rdparty/lwip_osal/src/sys_arch.c new file mode 100644 index 0000000..ee96057 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/lwip_osal/src/sys_arch.c @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/****************************************************************************** */ +/* */ +/* Include OS functionality. */ +/* */ +/****************************************************************************** */ + +/* ------------------------ System architecture includes ----------------------------- */ +#include "arch/sys_arch.h" + +/* ------------------------ lwIP includes --------------------------------- */ +#include "lwip/opt.h" + +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" + +#if !INCLUDE_xTaskAbortDelay + #error "lwIP FreeRTOS port requires INCLUDE_xTaskAbortDelay" +#endif +#if !INCLUDE_xTaskGetCurrentTaskHandle + #error "lwIP FreeRTOS port requires INCLUDE_xTaskGetCurrentTaskHandle" +#endif + +/* Very crude mechanism used to determine if the critical section handling + * functions are being called from an interrupt context or not. This relies on + * the interrupt handler setting this variable manually. */ +portBASE_TYPE xInsideISR = pdFALSE; + +/*---------------------------------------------------------------------------* +* Routine: sys_mbox_new +*---------------------------------------------------------------------------* +* Description: +* Creates a new mailbox +* Inputs: +* int size -- Size of elements in the mailbox +* Outputs: +* sys_mbox_t -- Handle to new mailbox +*---------------------------------------------------------------------------*/ +err_t sys_mbox_new( sys_mbox_t * pxMailBox, + int iSize ) +{ + err_t xReturn = ERR_MEM; + sys_mbox_t pxTempMbox; + + pxTempMbox.xMbox = xQueueCreate( iSize, sizeof( void * ) ); + + if( pxTempMbox.xMbox != NULL ) + { + pxTempMbox.xTask = NULL; + *pxMailBox = pxTempMbox; + xReturn = ERR_OK; + SYS_STATS_INC_USED( mbox ); + } + + return xReturn; +} + + +/*---------------------------------------------------------------------------* +* Routine: sys_mbox_free +*---------------------------------------------------------------------------* +* Description: +* Deallocates a mailbox. If there are messages still present in the +* mailbox when the mailbox is deallocated, it is an indication of a +* programming error in lwIP and the developer should be notified. +* Inputs: +* sys_mbox_t mbox -- Handle of mailbox +* Outputs: +* sys_mbox_t -- Handle to new mailbox +*---------------------------------------------------------------------------*/ +void sys_mbox_free( sys_mbox_t * pxMailBox ) +{ + unsigned long ulMessagesWaiting; + QueueHandle_t xMbox; + TaskHandle_t xTask; + sys_mbox_t volatile * pvxMailBox = pxMailBox; + + if( pvxMailBox != NULL ) + { + ulMessagesWaiting = uxQueueMessagesWaiting( pvxMailBox->xMbox ); + configASSERT( ( ulMessagesWaiting == 0 ) ); + + #if SYS_STATS + { + if( ulMessagesWaiting != 0UL ) + { + SYS_STATS_INC( mbox.err ); + } + + SYS_STATS_DEC( mbox.used ); + } + #endif /* SYS_STATS */ + + taskENTER_CRITICAL(); + xMbox = pvxMailBox->xMbox; + xTask = pvxMailBox->xTask; + pvxMailBox->xMbox = NULL; + taskEXIT_CRITICAL(); + + if( xTask != NULL ) + { + xTaskAbortDelay( xTask ); + } + + vQueueDelete( xMbox ); + } +} + +/*---------------------------------------------------------------------------* +* Routine: sys_mbox_post +*---------------------------------------------------------------------------* +* Description: +* Post the "msg" to the mailbox. +* Inputs: +* sys_mbox_t mbox -- Handle of mailbox +* void *data -- Pointer to data to post +*---------------------------------------------------------------------------*/ +void sys_mbox_post( sys_mbox_t * pxMailBox, + void * pxMessageToPost ) +{ + while( xQueueSendToBack( pxMailBox->xMbox, &pxMessageToPost, portMAX_DELAY ) != pdTRUE ) + { + } +} + +/*---------------------------------------------------------------------------* +* Routine: sys_mbox_trypost +*---------------------------------------------------------------------------* +* Description: +* Try to post the "msg" to the mailbox. Returns immediately with +* error if cannot. +* Inputs: +* sys_mbox_t mbox -- Handle of mailbox +* void *msg -- Pointer to data to post +* Outputs: +* err_t -- ERR_OK if message posted, else ERR_MEM +* if not. +*---------------------------------------------------------------------------*/ +err_t sys_mbox_trypost( sys_mbox_t * pxMailBox, + void * pxMessageToPost ) +{ + err_t xReturn; + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if( xInsideISR != pdFALSE ) + { + xReturn = xQueueSendFromISR( pxMailBox->xMbox, &pxMessageToPost, &xHigherPriorityTaskWoken ); + } + else + { + xReturn = xQueueSend( pxMailBox->xMbox, &pxMessageToPost, ( TickType_t ) 0 ); + } + + if( xReturn == pdPASS ) + { + xReturn = ERR_OK; + } + else + { + /* The queue was already full. */ + xReturn = ERR_MEM; + SYS_STATS_INC( mbox.err ); + } + + return xReturn; +} + +err_t sys_mbox_trypost_fromisr( sys_mbox_t * pxMailBox, + void * pxMessageToPost ) +{ + err_t xReturn; + + xInsideISR = pdTRUE; + xReturn = sys_mbox_trypost( pxMailBox, pxMessageToPost ); + xInsideISR = pdFALSE; + + return xReturn; +} + +/*---------------------------------------------------------------------------* +* Routine: sys_arch_mbox_fetch +*---------------------------------------------------------------------------* +* Description: +* Blocks the thread until a message arrives in the mailbox, but does +* not block the thread longer than "timeout" milliseconds (similar to +* the sys_arch_sem_wait() function). The "msg" argument is a result +* parameter that is set by the function (i.e., by doing "*msg = +* ptr"). The "msg" parameter maybe NULL to indicate that the message +* should be dropped. +* +* The return values are the same as for the sys_arch_sem_wait() function: +* Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a +* timeout. +* +* Note that a function with a similar name, sys_mbox_fetch(), is +* implemented by lwIP. +* Inputs: +* sys_mbox_t mbox -- Handle of mailbox +* void **msg -- Pointer to pointer to msg received +* u32_t timeout -- Number of milliseconds until timeout +* Outputs: +* u32_t -- SYS_ARCH_TIMEOUT if timeout, else 1 +*---------------------------------------------------------------------------*/ +u32_t sys_arch_mbox_fetch( sys_mbox_t * pxMailBox, + void ** ppvBuffer, + u32_t ulTimeOut ) +{ + void * pvDummy; + unsigned long ulReturn = SYS_ARCH_TIMEOUT; + QueueHandle_t xMbox; + TaskHandle_t xTask; + BaseType_t xResult; + sys_mbox_t volatile * pvxMailBox = pxMailBox; + + if( pvxMailBox == NULL ) + { + goto exit; + } + + taskENTER_CRITICAL(); + xMbox = pvxMailBox->xMbox; + xTask = xTaskGetCurrentTaskHandle(); + + if( ( xMbox != NULL ) && ( xTask != NULL ) && ( pvxMailBox->xTask == NULL ) ) + { + pvxMailBox->xTask = xTask; + } + else + { + xMbox = NULL; + } + + taskEXIT_CRITICAL(); + + if( xMbox == NULL ) + { + goto exit; + } + + if( NULL == ppvBuffer ) + { + ppvBuffer = &pvDummy; + } + + if( ulTimeOut != 0UL ) + { + configASSERT( xInsideISR == ( portBASE_TYPE ) 0 ); + + if( pdTRUE == xQueueReceive( xMbox, &( *ppvBuffer ), ulTimeOut / portTICK_PERIOD_MS ) ) + { + ulReturn = 1UL; + } + else + { + /* Timed out. */ + *ppvBuffer = NULL; + } + } + else + { + for( xResult = pdFALSE; ( xMbox != NULL ) && ( xResult != pdTRUE ); ) + { + xResult = xQueueReceive( xMbox, &( *ppvBuffer ), portMAX_DELAY ); + xMbox = pvxMailBox->xMbox; + } + + if( xResult == pdTRUE ) + { + ulReturn = 1UL; + } + } + + pvxMailBox->xTask = NULL; + +exit: + return ulReturn; +} + +/*---------------------------------------------------------------------------* +* Routine: sys_arch_mbox_tryfetch +*---------------------------------------------------------------------------* +* Description: +* Similar to sys_arch_mbox_fetch, but if message is not ready +* immediately, we'll return with SYS_MBOX_EMPTY. On success, 0 is +* returned. +* Inputs: +* sys_mbox_t mbox -- Handle of mailbox +* void **msg -- Pointer to pointer to msg received +* Outputs: +* u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise, +* return ERR_OK. +*---------------------------------------------------------------------------*/ +u32_t sys_arch_mbox_tryfetch( sys_mbox_t * pxMailBox, + void ** ppvBuffer ) +{ + void * pvDummy; + unsigned long ulReturn; + long lResult; + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if( ppvBuffer == NULL ) + { + ppvBuffer = &pvDummy; + } + + if( xInsideISR != pdFALSE ) + { + lResult = xQueueReceiveFromISR( pxMailBox->xMbox, &( *ppvBuffer ), &xHigherPriorityTaskWoken ); + } + else + { + lResult = xQueueReceive( pxMailBox->xMbox, &( *ppvBuffer ), 0UL ); + } + + if( lResult == pdPASS ) + { + ulReturn = ERR_OK; + } + else + { + ulReturn = SYS_MBOX_EMPTY; + } + + return ulReturn; +} + +/*---------------------------------------------------------------------------* +* Routine: sys_sem_new +*---------------------------------------------------------------------------* +* Description: +* Creates and returns a new semaphore. The "ucCount" argument specifies +* the initial state of the semaphore. +* NOTE: Currently this routine only creates counts of 1 or 0 +* Inputs: +* sys_mbox_t mbox -- Handle of mailbox +* u8_t ucCount -- Initial ucCount of semaphore (1 or 0) +* Outputs: +* sys_sem_t -- Created semaphore or 0 if could not create. +*---------------------------------------------------------------------------*/ +err_t sys_sem_new( sys_sem_t * pxSemaphore, + u8_t ucCount ) +{ + err_t xReturn = ERR_MEM; + + vSemaphoreCreateBinary( ( *pxSemaphore ) ); + + if( *pxSemaphore != NULL ) + { + if( ucCount == 0U ) + { + xSemaphoreTake( *pxSemaphore, 1UL ); + } + + xReturn = ERR_OK; + SYS_STATS_INC_USED( sem ); + } + else + { + SYS_STATS_INC( sem.err ); + } + + return xReturn; +} + +/*---------------------------------------------------------------------------* +* Routine: sys_arch_sem_wait +*---------------------------------------------------------------------------* +* Description: +* Blocks the thread while waiting for the semaphore to be +* signaled. If the "timeout" argument is non-zero, the thread should +* only be blocked for the specified time (measured in +* milliseconds). +* +* If the timeout argument is non-zero, the return value is the number of +* milliseconds spent waiting for the semaphore to be signaled. If the +* semaphore wasn't signaled within the specified time, the return value is +* SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore +* (i.e., it was already signaled), the function may return zero. +* +* Notice that lwIP implements a function with a similar name, +* sys_sem_wait(), that uses the sys_arch_sem_wait() function. +* Inputs: +* sys_sem_t sem -- Semaphore to wait on +* u32_t timeout -- Number of milliseconds until timeout +* Outputs: +* u32_t -- Time elapsed or SYS_ARCH_TIMEOUT. +*---------------------------------------------------------------------------*/ +u32_t sys_arch_sem_wait( sys_sem_t * pxSemaphore, + u32_t ulTimeout ) +{ + TickType_t xStartTime, xEndTime, xElapsed; + unsigned long ulReturn; + + xStartTime = xTaskGetTickCount(); + + if( ulTimeout != 0UL ) + { + if( xSemaphoreTake( *pxSemaphore, ulTimeout / portTICK_PERIOD_MS ) == pdTRUE ) + { + xEndTime = xTaskGetTickCount(); + xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS; + ulReturn = xElapsed; + } + else + { + ulReturn = SYS_ARCH_TIMEOUT; + } + } + else + { + while( xSemaphoreTake( *pxSemaphore, portMAX_DELAY ) != pdTRUE ) + { + } + + xEndTime = xTaskGetTickCount(); + xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS; + + if( xElapsed == 0UL ) + { + xElapsed = 1UL; + } + + ulReturn = xElapsed; + } + + return ulReturn; +} + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new( sys_mutex_t * pxMutex ) +{ + err_t xReturn = ERR_MEM; + + *pxMutex = xSemaphoreCreateMutex(); + + if( *pxMutex != NULL ) + { + xReturn = ERR_OK; + SYS_STATS_INC_USED( mutex ); + } + else + { + SYS_STATS_INC( mutex.err ); + } + + return xReturn; +} + +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock( sys_mutex_t * pxMutex ) +{ + while( xSemaphoreTake( *pxMutex, portMAX_DELAY ) != pdPASS ) + { + } +} + +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock( sys_mutex_t * pxMutex ) +{ + xSemaphoreGive( *pxMutex ); +} + + +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free( sys_mutex_t * pxMutex ) +{ + SYS_STATS_DEC( mutex.used ); + vQueueDelete( *pxMutex ); +} + + +/*---------------------------------------------------------------------------* +* Routine: sys_sem_signal +*---------------------------------------------------------------------------* +* Description: +* Signals (releases) a semaphore +* Inputs: +* sys_sem_t sem -- Semaphore to signal +*---------------------------------------------------------------------------*/ +void sys_sem_signal( sys_sem_t * pxSemaphore ) +{ + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if( xInsideISR != pdFALSE ) + { + xSemaphoreGiveFromISR( *pxSemaphore, &xHigherPriorityTaskWoken ); + } + else + { + xSemaphoreGive( *pxSemaphore ); + } +} + +/*---------------------------------------------------------------------------* +* Routine: sys_sem_free +*---------------------------------------------------------------------------* +* Description: +* Deallocates a semaphore +* Inputs: +* sys_sem_t sem -- Semaphore to free +*---------------------------------------------------------------------------*/ +void sys_sem_free( sys_sem_t * pxSemaphore ) +{ + SYS_STATS_DEC( sem.used ); + vQueueDelete( *pxSemaphore ); +} + +/*---------------------------------------------------------------------------* +* Routine: sys_init +*---------------------------------------------------------------------------* +* Description: +* Initialize sys arch +*---------------------------------------------------------------------------*/ +void sys_init( void ) +{ + srand( rand() ); +} + +u32_t sys_now( void ) +{ + return xTaskGetTickCount(); +} + +/*---------------------------------------------------------------------------* +* Routine: sys_thread_new +*---------------------------------------------------------------------------* +* Description: +* Starts a new thread with priority "prio" that will begin its +* execution in the function "thread()". The "arg" argument will be +* passed as an argument to the thread() function. The id of the new +* thread is returned. Both the id and the priority are system +* dependent. +* Inputs: +* char *name -- Name of thread +* void (* thread)(void *arg) -- Pointer to function to run. +* void *arg -- Argument passed into function +* int stacksize -- Required stack amount in bytes +* int prio -- Thread priority +* Outputs: +* sys_thread_t -- Pointer to per-thread timeouts. +*---------------------------------------------------------------------------*/ +sys_thread_t sys_thread_new( const char * pcName, + void ( * pxThread )( void * pvParameters ), + void * pvArg, + int iStackSize, + int iPriority ) +{ + TaskHandle_t xCreatedTask; + portBASE_TYPE xResult; + sys_thread_t xReturn; + + xResult = xTaskCreate( pxThread, pcName, iStackSize, pvArg, iPriority, &xCreatedTask ); + + if( xResult == pdPASS ) + { + xReturn = xCreatedTask; + } + else + { + xReturn = NULL; + } + + return xReturn; +} + +#if LWIP_NETCONN_SEM_PER_THREAD + #if configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 + +/*---------------------------------------------------------------------------* +* Routine: sys_arch_netconn_sem_get +*---------------------------------------------------------------------------* +* Description: +* Lookup the task-specific semaphore; create one if necessary. +* The semaphore pointer lives in the 0th slot of the +* TCB local storage array. Once allocated, it is never released. +*---------------------------------------------------------------------------*/ + sys_sem_t * sys_arch_netconn_sem_get( void ) + { + void * ret; + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + + configASSERT( task != NULL ); + + ret = pvTaskGetThreadLocalStoragePointer( task, 0 ); + + if( ret == NULL ) + { + sys_sem_t * sem; + err_t err; + /* allocate memory for this semaphore */ + sem = mem_malloc( sizeof( sys_sem_t ) ); + configASSERT( sem != NULL ); + err = sys_sem_new( sem, 0 ); + configASSERT( err == ERR_OK ); + configASSERT( sys_sem_valid( sem ) ); + vTaskSetThreadLocalStoragePointer( task, 0, sem ); + ret = sem; + } + + return ret; + } + #else /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */ + #error LWIP_NETCONN_SEM_PER_THREAD needs configNUM_THREAD_LOCAL_STORAGE_POINTERS + #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */ + +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/*---------------------------------------------------------------------------* +* Routine: sys_arch_protect +*---------------------------------------------------------------------------* +* Description: +* This optional function does a "fast" critical region protection and +* returns the previous protection level. This function is only called +* during very short critical regions. An embedded system which supports +* ISR-based drivers might want to implement this function by disabling +* interrupts. Task-based systems might want to implement this by using +* a mutex or disabling tasking. This function should support recursive +* calls from the same task or interrupt. In other words, +* sys_arch_protect() could be called while already protected. In +* that case the return value indicates that it is already protected. +* +* sys_arch_protect() is only required if your port is supporting an +* operating system. +* Outputs: +* sys_prot_t -- Previous protection level (not used here) +*---------------------------------------------------------------------------*/ +sys_prot_t sys_arch_protect( void ) +{ + if( xInsideISR == pdFALSE ) + { + taskENTER_CRITICAL(); + } + + return ( sys_prot_t ) 1; +} + +/*---------------------------------------------------------------------------* +* Routine: sys_arch_unprotect +*---------------------------------------------------------------------------* +* Description: +* This optional function does a "fast" set of critical region +* protection to the value specified by pval. See the documentation for +* sys_arch_protect() for more information. This function is only +* required if your port is supporting an operating system. +* Inputs: +* sys_prot_t -- Previous protection level (not used here) +*---------------------------------------------------------------------------*/ +void sys_arch_unprotect( sys_prot_t xValue ) +{ + ( void ) xValue; + + if( xInsideISR == pdFALSE ) + { + taskEXIT_CRITICAL(); + } +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char * pcMessage ) +{ + ( void ) pcMessage; + printf( "sys_assert : loop forever\n" ); + + for( ; ; ) + { + } +} + +/*-------------------------------------------------------------------------* +* End of File: sys_arch.c +*-------------------------------------------------------------------------*/ diff --git a/bsp/aws_libraries/3rdparty/mbedtls_config/README.md b/bsp/aws_libraries/3rdparty/mbedtls_config/README.md new file mode 100644 index 0000000..232d208 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/mbedtls_config/README.md @@ -0,0 +1,2 @@ +## Background +This folder contains the aws_mbedtls_config.h config file. This is a default configuration that's intended to be used by the AWS demos. The config file is used instead of the config file defined in the mbedTLS library by setting the MBEDTLS_CONFIG_FILE macro and adding its directory to the include path. For building with CMake, the macro is set in the main CMake file if it has not already been set. For building with an IDE, this macro has been set in the IDE project file. For building with make, this macro has been set in its Makefile. \ No newline at end of file diff --git a/bsp/aws_libraries/3rdparty/mbedtls_config/aws_mbedtls_config.h b/bsp/aws_libraries/3rdparty/mbedtls_config/aws_mbedtls_config.h new file mode 100644 index 0000000..c7d8c76 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/mbedtls_config/aws_mbedtls_config.h @@ -0,0 +1,3373 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + * This repository uses Mbed TLS under Apache 2.0 + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + + /** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +#ifdef CONFIG_MEDTLS_USE_AFR_MEMORY + #include + + extern void * pvCalloc( size_t xNumElements, + size_t xSize ) ; + extern void vPortFree( void *pv ); + #define MBEDTLS_PLATFORM_CALLOC_MACRO pvCalloc + #define MBEDTLS_PLATFORM_FREE_MACRO vPortFree +#endif + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - the pointer is checked to be non-NULL only if this option is enabled + * - the content of the buffer is always validated + * + * When this flag is defined, if a library function receives a parameter that + * is invalid, it will: + * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a + * call to the function mbedtls_param_failed() + * - immediately return (with a specific error code unless the function + * returns void and can't communicate an error). + * + * When defining this flag, you also need to: + * - either provide a definition of the function mbedtls_param_failed() in + * your application (see platform_util.h for its prototype) as the library + * calls that function, but does not provide a default definition for it, + * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED() + * below if the above mechanism is not flexible enough to suit your needs. + * See the documentation of this macro later in this file. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ + //#define MBEDTLS_AES_ALT + //#define MBEDTLS_ARC4_ALT + //#define MBEDTLS_ARIA_ALT + //#define MBEDTLS_BLOWFISH_ALT + //#define MBEDTLS_CAMELLIA_ALT + //#define MBEDTLS_CCM_ALT + //#define MBEDTLS_CHACHA20_ALT + //#define MBEDTLS_CHACHAPOLY_ALT + //#define MBEDTLS_CMAC_ALT + //#define MBEDTLS_DES_ALT + //#define MBEDTLS_DHM_ALT + //#define MBEDTLS_ECJPAKE_ALT + //#define MBEDTLS_GCM_ALT + //#define MBEDTLS_NIST_KW_ALT + //#define MBEDTLS_MD2_ALT + //#define MBEDTLS_MD4_ALT + //#define MBEDTLS_MD5_ALT + //#define MBEDTLS_POLY1305_ALT + //#define MBEDTLS_RIPEMD160_ALT + //#define MBEDTLS_RSA_ALT + //#define MBEDTLS_SHA1_ALT + //#define MBEDTLS_SHA256_ALT + //#define MBEDTLS_SHA512_ALT + //#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ + #define MBEDTLS_AES_ROM_TABLES + + /** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ + //#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +//#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KE + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. +*/ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +//#define MBEDTLS_ECP_DP_BP256R1_ENABLED +//#define MBEDTLS_ECP_DP_BP384R1_ENABLED +//#define MBEDTLS_ECP_DP_BP512R1_ENABLED +//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +//#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +//#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +//#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +//#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +//#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +//#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintainance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +//#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +//#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +//#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +//#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +//#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +//#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +//#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +//#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +//#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +//#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +//#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +//#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, a default definition is + * provided that invokes the function mbedtls_param_failed(), + * which is declared in platform_util.h for the benefit of the + * library, but that you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 8192 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ + diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/skipAnyLiteral_harness.c b/bsp/aws_libraries/3rdparty/mbedtls_config/threading_alt.h similarity index 53% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/skipAnyLiteral_harness.c rename to bsp/aws_libraries/3rdparty/mbedtls_config/threading_alt.h index 792f2ee..9d888d9 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/skipAnyLiteral/skipAnyLiteral_harness.c +++ b/bsp/aws_libraries/3rdparty/mbedtls_config/threading_alt.h @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * corePKCS11 V2.0.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -12,45 +12,38 @@ * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF NY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org */ -/** - * @file skipAnyLiteral_harness.c - * @brief Implements the proof harness for the skipAnyLiteral function. - */ - -#include -#include "core_json_annex.h" - -void harness() -{ - char * buf; - size_t start, max; - bool ret; +#ifndef __THREADING_ALT_H__ +#define __THREADING_ALT_H__ - /* max is the buffer length which must be nonzero for non-API functions. */ - __CPROVER_assume( max > 0 ); - /* max is the buffer length which must not exceed unwindings. */ - __CPROVER_assume( max < CBMC_MAX_BUFSIZE ); +#include "FreeRTOS.h" +#include "semphr.h" - /* buf must not be NULL */ - buf = malloc( max ); - __CPROVER_assume( buf != NULL ); +/** + * @brief Mutex struct used to synchronize mbed TLS operations. + * + */ +typedef struct +{ + SemaphoreHandle_t mutex; /**< @brief FreeRTOS semaphore. */ + char is_valid; /**< @brief Flag used by mbedTLS to track wether a mutex is valid. */ +} mbedtls_threading_mutex_t; - ret = skipAnyLiteral( buf, &start, max ); +extern void mbedtls_threading_set_alt( void ( * mutex_init )( mbedtls_threading_mutex_t * ), + void ( * mutex_free )( mbedtls_threading_mutex_t * ), + int ( * mutex_lock )( mbedtls_threading_mutex_t * ), + int ( * mutex_unlock )( mbedtls_threading_mutex_t * ) ); - __CPROVER_assert( isBool( ret ), "A bool value is returned." ); - if( ret == true ) - { - __CPROVER_assert( start <= max, - "The buffer start index does not exceed the buffer length." ); - } -} +#endif /* ifndef __THREADING_ALT_H__ */ diff --git a/bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_error.c b/bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_error.c new file mode 100644 index 0000000..8312fe2 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_error.c @@ -0,0 +1,1336 @@ +/* + * FreeRTOS mbed TLS V0.1.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file mbedtls_error.c + * @brief This files defines the stringification utilities for mbed TLS high-level and low-level codes. + */ + +#include "mbedtls_error.h" + +#if !defined( MBEDTLS_CONFIG_FILE ) + #include "mbedtls/config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#if defined( MBEDTLS_AES_C ) + #include "mbedtls/aes.h" +#endif + +#if defined( MBEDTLS_ARC4_C ) + #include "mbedtls/arc4.h" +#endif + +#if defined( MBEDTLS_ARIA_C ) + #include "mbedtls/aria.h" +#endif + +#if defined( MBEDTLS_BASE64_C ) + #include "mbedtls/base64.h" +#endif + +#if defined( MBEDTLS_BIGNUM_C ) + #include "mbedtls/bignum.h" +#endif + +#if defined( MBEDTLS_BLOWFISH_C ) + #include "mbedtls/blowfish.h" +#endif + +#if defined( MBEDTLS_CAMELLIA_C ) + #include "mbedtls/camellia.h" +#endif + +#if defined( MBEDTLS_CCM_C ) + #include "mbedtls/ccm.h" +#endif + +#if defined( MBEDTLS_CHACHA20_C ) + #include "mbedtls/chacha20.h" +#endif + +#if defined( MBEDTLS_CHACHAPOLY_C ) + #include "mbedtls/chachapoly.h" +#endif + +#if defined( MBEDTLS_CIPHER_C ) + #include "mbedtls/cipher.h" +#endif + +#if defined( MBEDTLS_CMAC_C ) + #include "mbedtls/cmac.h" +#endif + +#if defined( MBEDTLS_CTR_DRBG_C ) + #include "mbedtls/ctr_drbg.h" +#endif + +#if defined( MBEDTLS_DES_C ) + #include "mbedtls/des.h" +#endif + +#if defined( MBEDTLS_DHM_C ) + #include "mbedtls/dhm.h" +#endif + +#if defined( MBEDTLS_ECP_C ) + #include "mbedtls/ecp.h" +#endif + +#if defined( MBEDTLS_ENTROPY_C ) + #include "mbedtls/entropy.h" +#endif + +#if defined( MBEDTLS_GCM_C ) + #include "mbedtls/gcm.h" +#endif + +#if defined( MBEDTLS_HKDF_C ) + #include "mbedtls/hkdf.h" +#endif + +#if defined( MBEDTLS_HMAC_DRBG_C ) + #include "mbedtls/hmac_drbg.h" +#endif + +#if defined( MBEDTLS_MD_C ) + #include "mbedtls/md.h" +#endif + +#if defined( MBEDTLS_MD2_C ) + #include "mbedtls/md2.h" +#endif + +#if defined( MBEDTLS_MD4_C ) + #include "mbedtls/md4.h" +#endif + +#if defined( MBEDTLS_MD5_C ) + #include "mbedtls/md5.h" +#endif + +#if defined( MBEDTLS_NET_C ) + #include "mbedtls/net_sockets.h" +#endif + +#if defined( MBEDTLS_OID_C ) + #include "mbedtls/oid.h" +#endif + +#if defined( MBEDTLS_PADLOCK_C ) + #include "mbedtls/padlock.h" +#endif + +#if defined( MBEDTLS_PEM_PARSE_C ) || defined( MBEDTLS_PEM_WRITE_C ) + #include "mbedtls/pem.h" +#endif + +#if defined( MBEDTLS_PK_C ) + #include "mbedtls/pk.h" +#endif + +#if defined( MBEDTLS_PKCS12_C ) + #include "mbedtls/pkcs12.h" +#endif + +#if defined( MBEDTLS_PKCS5_C ) + #include "mbedtls/pkcs5.h" +#endif + +#if defined( MBEDTLS_PLATFORM_C ) + #include "mbedtls/platform.h" +#endif + +#if defined( MBEDTLS_POLY1305_C ) + #include "mbedtls/poly1305.h" +#endif + +#if defined( MBEDTLS_RIPEMD160_C ) + #include "mbedtls/ripemd160.h" +#endif + +#if defined( MBEDTLS_RSA_C ) + #include "mbedtls/rsa.h" +#endif + +#if defined( MBEDTLS_SHA1_C ) + #include "mbedtls/sha1.h" +#endif + +#if defined( MBEDTLS_SHA256_C ) + #include "mbedtls/sha256.h" +#endif + +#if defined( MBEDTLS_SHA512_C ) + #include "mbedtls/sha512.h" +#endif + +#if defined( MBEDTLS_SSL_TLS_C ) + #include "mbedtls/ssl.h" +#endif + +#if defined( MBEDTLS_THREADING_C ) + #include "mbedtls/threading.h" +#endif + +#if defined( MBEDTLS_X509_USE_C ) || defined( MBEDTLS_X509_CREATE_C ) + #include "mbedtls/x509.h" +#endif + +#if defined( MBEDTLS_XTEA_C ) + #include "mbedtls/xtea.h" +#endif + + +const char * mbedtls_strerror_highlevel( int errnum ) +{ + const char * rc = NULL; + int use_ret; + + if( errnum < 0 ) + { + errnum = -errnum; + } + + if( errnum & 0xFF80 ) + { + use_ret = errnum & 0xFF80; + + /* High level error codes */ + switch( use_ret ) + { + #if defined( MBEDTLS_CIPHER_C ) + case -( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ): + rc = "CIPHER - The selected feature is not available"; + break; + + case -( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ): + rc = "CIPHER - Bad input parameters"; + break; + + case -( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ): + rc = "CIPHER - Failed to allocate memory"; + break; + + case -( MBEDTLS_ERR_CIPHER_INVALID_PADDING ): + rc = "CIPHER - Input data contains invalid padding and is rejected"; + break; + + case -( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ): + rc = "CIPHER - Decryption of block requires a full block"; + break; + + case -( MBEDTLS_ERR_CIPHER_AUTH_FAILED ): + rc = "CIPHER - Authentication failed (for AEAD modes)"; + break; + + case -( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ): + rc = "CIPHER - The context is invalid. For example, because it was freed"; + break; + + case -( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ): + rc = "CIPHER - Cipher hardware accelerator failed"; + break; + #endif /* MBEDTLS_CIPHER_C */ + + #if defined( MBEDTLS_DHM_C ) + case -( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ): + rc = "DHM - Bad input parameters"; + break; + + case -( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED ): + rc = "DHM - Reading of the DHM parameters failed"; + break; + + case -( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ): + rc = "DHM - Making of the DHM parameters failed"; + break; + + case -( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED ): + rc = "DHM - Reading of the public values failed"; + break; + + case -( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ): + rc = "DHM - Making of the public value failed"; + break; + + case -( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED ): + rc = "DHM - Calculation of the DHM secret failed"; + break; + + case -( MBEDTLS_ERR_DHM_INVALID_FORMAT ): + rc = "DHM - The ASN.1 data is not formatted correctly"; + break; + + case -( MBEDTLS_ERR_DHM_ALLOC_FAILED ): + rc = "DHM - Allocation of memory failed"; + break; + + case -( MBEDTLS_ERR_DHM_FILE_IO_ERROR ): + rc = "DHM - Read or write of file failed"; + break; + + case -( MBEDTLS_ERR_DHM_HW_ACCEL_FAILED ): + rc = "DHM - DHM hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_DHM_SET_GROUP_FAILED ): + rc = "DHM - Setting the modulus and generator failed"; + break; + #endif /* MBEDTLS_DHM_C */ + + #if defined( MBEDTLS_ECP_C ) + case -( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ): + rc = "ECP - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ): + rc = "ECP - The buffer is too small to write to"; + break; + + case -( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ): + rc = "ECP - The requested feature is not available, for example, the requested curve is not supported"; + break; + + case -( MBEDTLS_ERR_ECP_VERIFY_FAILED ): + rc = "ECP - The signature is not valid"; + break; + + case -( MBEDTLS_ERR_ECP_ALLOC_FAILED ): + rc = "ECP - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_ECP_RANDOM_FAILED ): + rc = "ECP - Generation of random value, such as ephemeral key, failed"; + break; + + case -( MBEDTLS_ERR_ECP_INVALID_KEY ): + rc = "ECP - Invalid private or public key"; + break; + + case -( MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ): + rc = "ECP - The buffer contains a valid signature followed by more data"; + break; + + case -( MBEDTLS_ERR_ECP_HW_ACCEL_FAILED ): + rc = "ECP - The ECP hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_ECP_IN_PROGRESS ): + rc = "ECP - Operation in progress, call again with the same parameters to continue"; + break; + #endif /* MBEDTLS_ECP_C */ + + #if defined( MBEDTLS_MD_C ) + case -( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ): + rc = "MD - The selected feature is not available"; + break; + + case -( MBEDTLS_ERR_MD_BAD_INPUT_DATA ): + rc = "MD - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_MD_ALLOC_FAILED ): + rc = "MD - Failed to allocate memory"; + break; + + case -( MBEDTLS_ERR_MD_FILE_IO_ERROR ): + rc = "MD - Opening or reading of file failed"; + break; + + case -( MBEDTLS_ERR_MD_HW_ACCEL_FAILED ): + rc = "MD - MD hardware accelerator failed"; + break; + #endif /* MBEDTLS_MD_C */ + + #if defined( MBEDTLS_PEM_PARSE_C ) || defined( MBEDTLS_PEM_WRITE_C ) + case -( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ): + rc = "PEM - No PEM header or footer found"; + break; + + case -( MBEDTLS_ERR_PEM_INVALID_DATA ): + rc = "PEM - PEM string is not as expected"; + break; + + case -( MBEDTLS_ERR_PEM_ALLOC_FAILED ): + rc = "PEM - Failed to allocate memory"; + break; + + case -( MBEDTLS_ERR_PEM_INVALID_ENC_IV ): + rc = "PEM - RSA IV is not in hex-format"; + break; + + case -( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ): + rc = "PEM - Unsupported key encryption algorithm"; + break; + + case -( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ): + rc = "PEM - Private key password can't be empty"; + break; + + case -( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ): + rc = "PEM - Given private key password does not allow for correct decryption"; + break; + + case -( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ): + rc = "PEM - Unavailable feature, e.g. hashing/encryption combination"; + break; + + case -( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ): + rc = "PEM - Bad input parameters to function"; + break; + #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + + #if defined( MBEDTLS_PK_C ) + case -( MBEDTLS_ERR_PK_ALLOC_FAILED ): + rc = "PK - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_PK_TYPE_MISMATCH ): + rc = "PK - Type mismatch, eg attempt to encrypt with an ECDSA key"; + break; + + case -( MBEDTLS_ERR_PK_BAD_INPUT_DATA ): + rc = "PK - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_PK_FILE_IO_ERROR ): + rc = "PK - Read/write of file failed"; + break; + + case -( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ): + rc = "PK - Unsupported key version"; + break; + + case -( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ): + rc = "PK - Invalid key tag or value"; + break; + + case -( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ): + rc = "PK - Key algorithm is unsupported (only RSA and EC are supported)"; + break; + + case -( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ): + rc = "PK - Private key password can't be empty"; + break; + + case -( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ): + rc = "PK - Given private key password does not allow for correct decryption"; + break; + + case -( MBEDTLS_ERR_PK_INVALID_PUBKEY ): + rc = "PK - The pubkey tag or value is invalid (only RSA and EC are supported)"; + break; + + case -( MBEDTLS_ERR_PK_INVALID_ALG ): + rc = "PK - The algorithm tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ): + rc = "PK - Elliptic curve is unsupported (only NIST curves are supported)"; + break; + + case -( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ): + rc = "PK - Unavailable feature, e.g. RSA disabled for RSA key"; + break; + + case -( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ): + rc = "PK - The buffer contains a valid signature followed by more data"; + break; + + case -( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ): + rc = "PK - PK hardware accelerator failed"; + break; + #endif /* MBEDTLS_PK_C */ + + #if defined( MBEDTLS_PKCS12_C ) + case -( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ): + rc = "PKCS12 - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ): + rc = "PKCS12 - Feature not available, e.g. unsupported encryption scheme"; + break; + + case -( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT ): + rc = "PKCS12 - PBE ASN.1 data not as expected"; + break; + + case -( MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ): + rc = "PKCS12 - Given private key password does not allow for correct decryption"; + break; + #endif /* MBEDTLS_PKCS12_C */ + + #if defined( MBEDTLS_PKCS5_C ) + case -( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ): + rc = "PKCS5 - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ): + rc = "PKCS5 - Unexpected ASN.1 data"; + break; + + case -( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ): + rc = "PKCS5 - Requested encryption or digest alg not available"; + break; + + case -( MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ): + rc = "PKCS5 - Given private key password does not allow for correct decryption"; + break; + #endif /* MBEDTLS_PKCS5_C */ + + #if defined( MBEDTLS_RSA_C ) + case -( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ): + rc = "RSA - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_RSA_INVALID_PADDING ): + rc = "RSA - Input data contains invalid padding and is rejected"; + break; + + case -( MBEDTLS_ERR_RSA_KEY_GEN_FAILED ): + rc = "RSA - Something failed during generation of a key"; + break; + + case -( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ): + rc = "RSA - Key failed to pass the validity check of the library"; + break; + + case -( MBEDTLS_ERR_RSA_PUBLIC_FAILED ): + rc = "RSA - The public key operation failed"; + break; + + case -( MBEDTLS_ERR_RSA_PRIVATE_FAILED ): + rc = "RSA - The private key operation failed"; + break; + + case -( MBEDTLS_ERR_RSA_VERIFY_FAILED ): + rc = "RSA - The PKCS#1 verification failed"; + break; + + case -( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ): + rc = "RSA - The output buffer for decryption is not large enough"; + break; + + case -( MBEDTLS_ERR_RSA_RNG_FAILED ): + rc = "RSA - The random generator failed to generate non-zeros"; + break; + + case -( MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION ): + rc = "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality"; + break; + + case -( MBEDTLS_ERR_RSA_HW_ACCEL_FAILED ): + rc = "RSA - RSA hardware accelerator failed"; + break; + #endif /* MBEDTLS_RSA_C */ + + #if defined( MBEDTLS_SSL_TLS_C ) + case -( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ): + rc = "SSL - The requested feature is not available"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ): + rc = "SSL - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_SSL_INVALID_MAC ): + rc = "SSL - Verification of the message MAC failed"; + break; + + case -( MBEDTLS_ERR_SSL_INVALID_RECORD ): + rc = "SSL - An invalid SSL record was received"; + break; + + case -( MBEDTLS_ERR_SSL_CONN_EOF ): + rc = "SSL - The connection indicated an EOF"; + break; + + case -( MBEDTLS_ERR_SSL_UNKNOWN_CIPHER ): + rc = "SSL - An unknown cipher was received"; + break; + + case -( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ): + rc = "SSL - The server has no ciphersuites in common with the client"; + break; + + case -( MBEDTLS_ERR_SSL_NO_RNG ): + rc = "SSL - No RNG was provided to the SSL module"; + break; + + case -( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ): + rc = "SSL - No client certification received from the client, but required by the authentication mode"; + break; + + case -( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ): + rc = "SSL - Our own certificate(s) is/are too large to send in an SSL message"; + break; + + case -( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ): + rc = "SSL - The own certificate is not set, but needed by the server"; + break; + + case -( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ): + rc = "SSL - The own private key or pre-shared key is not set, but needed"; + break; + + case -( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ): + rc = "SSL - No CA Chain is set, but required to operate"; + break; + + case -( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ): + rc = "SSL - An unexpected message was received from our peer"; + break; + + case -( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ): + rc = "SSL - A fatal alert message was received from our peer"; + break; + + case -( MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED ): + rc = "SSL - Verification of our peer failed"; + break; + + case -( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ): + rc = "SSL - The peer notified us that the connection is going to be closed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ): + rc = "SSL - Processing of the ClientHello handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ): + rc = "SSL - Processing of the ServerHello handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ): + rc = "SSL - Processing of the Certificate handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ): + rc = "SSL - Processing of the CertificateRequest handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ): + rc = "SSL - Processing of the ServerKeyExchange handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ): + rc = "SSL - Processing of the ServerHelloDone handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ): + rc = "SSL - Processing of the ClientKeyExchange handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ): + rc = "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ): + rc = "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ): + rc = "SSL - Processing of the CertificateVerify handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ): + rc = "SSL - Processing of the ChangeCipherSpec handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ): + rc = "SSL - Processing of the Finished handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_ALLOC_FAILED ): + rc = "SSL - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ): + rc = "SSL - Hardware acceleration function returned with error"; + break; + + case -( MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ): + rc = "SSL - Hardware acceleration function skipped / left alone data"; + break; + + case -( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ): + rc = "SSL - Processing of the compression / decompression failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ): + rc = "SSL - Handshake protocol not within min/max boundaries"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ): + rc = "SSL - Processing of the NewSessionTicket handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ): + rc = "SSL - Session ticket has expired"; + break; + + case -( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ): + rc = "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)"; + break; + + case -( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ): + rc = "SSL - Unknown identity received (eg, PSK identity)"; + break; + + case -( MBEDTLS_ERR_SSL_INTERNAL_ERROR ): + rc = "SSL - Internal error (eg, unexpected failure in lower-level module)"; + break; + + case -( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ): + rc = "SSL - A counter would wrap (eg, too many messages exchanged)"; + break; + + case -( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ): + rc = "SSL - Unexpected message at ServerHello in renegotiation"; + break; + + case -( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ): + rc = "SSL - DTLS client must retry for hello verification"; + break; + + case -( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ): + rc = "SSL - A buffer is too small to receive or write a message"; + break; + + case -( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ): + rc = "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)"; + break; + + case -( MBEDTLS_ERR_SSL_WANT_READ ): + rc = "SSL - No data of requested type currently available on underlying transport"; + break; + + case -( MBEDTLS_ERR_SSL_WANT_WRITE ): + rc = "SSL - Connection requires a write call"; + break; + + case -( MBEDTLS_ERR_SSL_TIMEOUT ): + rc = "SSL - The operation timed out"; + break; + + case -( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ): + rc = "SSL - The client initiated a reconnect from the same port"; + break; + + case -( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ): + rc = "SSL - Record header looks valid but is not expected"; + break; + + case -( MBEDTLS_ERR_SSL_NON_FATAL ): + rc = "SSL - The alert message received indicates a non-fatal error"; + break; + + case -( MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH ): + rc = "SSL - Couldn't set the hash for verifying CertificateVerify"; + break; + + case -( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ): + rc = "SSL - Internal-only message signaling that further message-processing should be done"; + break; + + case -( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ): + rc = "SSL - The asynchronous operation is not completed yet"; + break; + + case -( MBEDTLS_ERR_SSL_EARLY_MESSAGE ): + rc = "SSL - Internal-only message signaling that a message arrived early"; + break; + + case -( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ): + rc = "SSL - A cryptographic operation is in progress. Try again later"; + break; + #endif /* MBEDTLS_SSL_TLS_C */ + + #if defined( MBEDTLS_X509_USE_C ) || defined( MBEDTLS_X509_CREATE_C ) + case -( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ): + rc = "X509 - Unavailable feature, e.g. RSA hashing/encryption combination"; + break; + + case -( MBEDTLS_ERR_X509_UNKNOWN_OID ): + rc = "X509 - Requested OID is unknown"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_FORMAT ): + rc = "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_VERSION ): + rc = "X509 - The CRT/CRL/CSR version element is invalid"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_SERIAL ): + rc = "X509 - The serial tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_ALG ): + rc = "X509 - The algorithm tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_NAME ): + rc = "X509 - The name tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_DATE ): + rc = "X509 - The date tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_SIGNATURE ): + rc = "X509 - The signature tag or value invalid"; + break; + + case -( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ): + rc = "X509 - The extension tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_X509_UNKNOWN_VERSION ): + rc = "X509 - CRT/CRL/CSR has an unsupported version number"; + break; + + case -( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ): + rc = "X509 - Signature algorithm (oid) is unsupported"; + break; + + case -( MBEDTLS_ERR_X509_SIG_MISMATCH ): + rc = "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)"; + break; + + case -( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ): + rc = "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed"; + break; + + case -( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ): + rc = "X509 - Format not recognized as DER or PEM"; + break; + + case -( MBEDTLS_ERR_X509_BAD_INPUT_DATA ): + rc = "X509 - Input invalid"; + break; + + case -( MBEDTLS_ERR_X509_ALLOC_FAILED ): + rc = "X509 - Allocation of memory failed"; + break; + + case -( MBEDTLS_ERR_X509_FILE_IO_ERROR ): + rc = "X509 - Read/write of file failed"; + break; + + case -( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ): + rc = "X509 - Destination buffer is too small"; + break; + + case -( MBEDTLS_ERR_X509_FATAL_ERROR ): + rc = "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed"; + break; + #endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + /* END generated code */ + } + } + + return rc; +} + +const char * mbedtls_strerror_lowlevel( int errnum ) +{ + const char * rc = NULL; + int use_ret; + + if( errnum < 0 ) + { + errnum = -errnum; + } + + use_ret = errnum & ~0xFF80; + + if( use_ret == 0 ) + { + return NULL; + } + + /* Low level error codes */ + /* */ + switch( use_ret ) + { + #if defined( MBEDTLS_AES_C ) + case -( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ): + rc = "AES - Invalid key length"; + break; + + case -( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ): + rc = "AES - Invalid data input length"; + break; + + case -( MBEDTLS_ERR_AES_BAD_INPUT_DATA ): + rc = "AES - Invalid input data"; + break; + + case -( MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE ): + rc = "AES - Feature not available. For example, an unsupported AES key size"; + break; + + case -( MBEDTLS_ERR_AES_HW_ACCEL_FAILED ): + rc = "AES - AES hardware accelerator failed"; + break; + #endif /* MBEDTLS_AES_C */ + + #if defined( MBEDTLS_ARC4_C ) + case -( MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED ): + rc = "ARC4 - ARC4 hardware accelerator failed"; + break; + #endif /* MBEDTLS_ARC4_C */ + + #if defined( MBEDTLS_ARIA_C ) + case -( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ): + rc = "ARIA - Bad input data"; + break; + + case -( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ): + rc = "ARIA - Invalid data input length"; + break; + + case -( MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE ): + rc = "ARIA - Feature not available. For example, an unsupported ARIA key size"; + break; + + case -( MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED ): + rc = "ARIA - ARIA hardware accelerator failed"; + break; + #endif /* MBEDTLS_ARIA_C */ + + #if defined( MBEDTLS_ASN1_PARSE_C ) + case -( MBEDTLS_ERR_ASN1_OUT_OF_DATA ): + rc = "ASN1 - Out of data when parsing an ASN1 data structure"; + break; + + case -( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ): + rc = "ASN1 - ASN1 tag was of an unexpected value"; + break; + + case -( MBEDTLS_ERR_ASN1_INVALID_LENGTH ): + rc = "ASN1 - Error when trying to determine the length or invalid length"; + break; + + case -( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ): + rc = "ASN1 - Actual length differs from expected length"; + break; + + case -( MBEDTLS_ERR_ASN1_INVALID_DATA ): + rc = "ASN1 - Data is invalid. (not used)"; + break; + + case -( MBEDTLS_ERR_ASN1_ALLOC_FAILED ): + rc = "ASN1 - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ): + rc = "ASN1 - Buffer too small when writing ASN.1 data structure"; + break; + #endif /* MBEDTLS_ASN1_PARSE_C */ + + #if defined( MBEDTLS_BASE64_C ) + case -( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ): + rc = "BASE64 - Output buffer too small"; + break; + + case -( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ): + rc = "BASE64 - Invalid character in input"; + break; + #endif /* MBEDTLS_BASE64_C */ + + #if defined( MBEDTLS_BIGNUM_C ) + case -( MBEDTLS_ERR_MPI_FILE_IO_ERROR ): + rc = "BIGNUM - An error occurred while reading from or writing to a file"; + break; + + case -( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ): + rc = "BIGNUM - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_MPI_INVALID_CHARACTER ): + rc = "BIGNUM - There is an invalid character in the digit string"; + break; + + case -( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ): + rc = "BIGNUM - The buffer is too small to write to"; + break; + + case -( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ): + rc = "BIGNUM - The input arguments are negative or result in illegal output"; + break; + + case -( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ): + rc = "BIGNUM - The input argument for division is zero, which is not allowed"; + break; + + case -( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ): + rc = "BIGNUM - The input arguments are not acceptable"; + break; + + case -( MBEDTLS_ERR_MPI_ALLOC_FAILED ): + rc = "BIGNUM - Memory allocation failed"; + break; + #endif /* MBEDTLS_BIGNUM_C */ + + #if defined( MBEDTLS_BLOWFISH_C ) + case -( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ): + rc = "BLOWFISH - Bad input data"; + break; + + case -( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ): + rc = "BLOWFISH - Invalid data input length"; + break; + + case -( MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED ): + rc = "BLOWFISH - Blowfish hardware accelerator failed"; + break; + #endif /* MBEDTLS_BLOWFISH_C */ + + #if defined( MBEDTLS_CAMELLIA_C ) + case -( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ): + rc = "CAMELLIA - Bad input data"; + break; + + case -( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ): + rc = "CAMELLIA - Invalid data input length"; + break; + + case -( MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED ): + rc = "CAMELLIA - Camellia hardware accelerator failed"; + break; + #endif /* MBEDTLS_CAMELLIA_C */ + + #if defined( MBEDTLS_CCM_C ) + case -( MBEDTLS_ERR_CCM_BAD_INPUT ): + rc = "CCM - Bad input parameters to the function"; + break; + + case -( MBEDTLS_ERR_CCM_AUTH_FAILED ): + rc = "CCM - Authenticated decryption failed"; + break; + + case -( MBEDTLS_ERR_CCM_HW_ACCEL_FAILED ): + rc = "CCM - CCM hardware accelerator failed"; + break; + #endif /* MBEDTLS_CCM_C */ + + #if defined( MBEDTLS_CHACHA20_C ) + case -( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ): + rc = "CHACHA20 - Invalid input parameter(s)"; + break; + + case -( MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE ): + rc = "CHACHA20 - Feature not available. For example, s part of the API is not implemented"; + break; + + case -( MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED ): + rc = "CHACHA20 - Chacha20 hardware accelerator failed"; + break; + #endif /* MBEDTLS_CHACHA20_C */ + + #if defined( MBEDTLS_CHACHAPOLY_C ) + case -( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ): + rc = "CHACHAPOLY - The requested operation is not permitted in the current state"; + break; + + case -( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ): + rc = "CHACHAPOLY - Authenticated decryption failed: data was not authentic"; + break; + #endif /* MBEDTLS_CHACHAPOLY_C */ + + #if defined( MBEDTLS_CMAC_C ) + case -( MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED ): + rc = "CMAC - CMAC hardware accelerator failed"; + break; + #endif /* MBEDTLS_CMAC_C */ + + #if defined( MBEDTLS_CTR_DRBG_C ) + case -( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ): + rc = "CTR_DRBG - The entropy source failed"; + break; + + case -( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ): + rc = "CTR_DRBG - The requested random buffer length is too big"; + break; + + case -( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ): + rc = "CTR_DRBG - The input (entropy + additional data) is too large"; + break; + + case -( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ): + rc = "CTR_DRBG - Read or write error in file"; + break; + #endif /* MBEDTLS_CTR_DRBG_C */ + + #if defined( MBEDTLS_DES_C ) + case -( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ): + rc = "DES - The data input has an invalid length"; + break; + + case -( MBEDTLS_ERR_DES_HW_ACCEL_FAILED ): + rc = "DES - DES hardware accelerator failed"; + break; + #endif /* MBEDTLS_DES_C */ + + #if defined( MBEDTLS_ENTROPY_C ) + case -( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ): + rc = "ENTROPY - Critical entropy source failure"; + break; + + case -( MBEDTLS_ERR_ENTROPY_MAX_SOURCES ): + rc = "ENTROPY - No more sources can be added"; + break; + + case -( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ): + rc = "ENTROPY - No sources have been added to poll"; + break; + + case -( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ): + rc = "ENTROPY - No strong sources have been added to poll"; + break; + + case -( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ): + rc = "ENTROPY - Read/write error in file"; + break; + #endif /* MBEDTLS_ENTROPY_C */ + + #if defined( MBEDTLS_GCM_C ) + case -( MBEDTLS_ERR_GCM_AUTH_FAILED ): + rc = "GCM - Authenticated decryption failed"; + break; + + case -( MBEDTLS_ERR_GCM_HW_ACCEL_FAILED ): + rc = "GCM - GCM hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_GCM_BAD_INPUT ): + rc = "GCM - Bad input parameters to function"; + break; + #endif /* MBEDTLS_GCM_C */ + + #if defined( MBEDTLS_HKDF_C ) + case -( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ): + rc = "HKDF - Bad input parameters to function"; + break; + #endif /* MBEDTLS_HKDF_C */ + + #if defined( MBEDTLS_HMAC_DRBG_C ) + case -( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ): + rc = "HMAC_DRBG - Too many random requested in single call"; + break; + + case -( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ): + rc = "HMAC_DRBG - Input too large (Entropy + additional)"; + break; + + case -( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ): + rc = "HMAC_DRBG - Read/write error in file"; + break; + + case -( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ): + rc = "HMAC_DRBG - The entropy source failed"; + break; + #endif /* MBEDTLS_HMAC_DRBG_C */ + + #if defined( MBEDTLS_MD2_C ) + case -( MBEDTLS_ERR_MD2_HW_ACCEL_FAILED ): + rc = "MD2 - MD2 hardware accelerator failed"; + break; + #endif /* MBEDTLS_MD2_C */ + + #if defined( MBEDTLS_MD4_C ) + case -( MBEDTLS_ERR_MD4_HW_ACCEL_FAILED ): + rc = "MD4 - MD4 hardware accelerator failed"; + break; + #endif /* MBEDTLS_MD4_C */ + + #if defined( MBEDTLS_MD5_C ) + case -( MBEDTLS_ERR_MD5_HW_ACCEL_FAILED ): + rc = "MD5 - MD5 hardware accelerator failed"; + break; + #endif /* MBEDTLS_MD5_C */ + + #if defined( MBEDTLS_NET_C ) + case -( MBEDTLS_ERR_NET_SOCKET_FAILED ): + rc = "NET - Failed to open a socket"; + break; + + case -( MBEDTLS_ERR_NET_CONNECT_FAILED ): + rc = "NET - The connection to the given server / port failed"; + break; + + case -( MBEDTLS_ERR_NET_BIND_FAILED ): + rc = "NET - Binding of the socket failed"; + break; + + case -( MBEDTLS_ERR_NET_LISTEN_FAILED ): + rc = "NET - Could not listen on the socket"; + break; + + case -( MBEDTLS_ERR_NET_ACCEPT_FAILED ): + rc = "NET - Could not accept the incoming connection"; + break; + + case -( MBEDTLS_ERR_NET_RECV_FAILED ): + rc = "NET - Reading information from the socket failed"; + break; + + case -( MBEDTLS_ERR_NET_SEND_FAILED ): + rc = "NET - Sending information through the socket failed"; + break; + + case -( MBEDTLS_ERR_NET_CONN_RESET ): + rc = "NET - Connection was reset by peer"; + break; + + case -( MBEDTLS_ERR_NET_UNKNOWN_HOST ): + rc = "NET - Failed to get an IP address for the given hostname"; + break; + + case -( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ): + rc = "NET - Buffer is too small to hold the data"; + break; + + case -( MBEDTLS_ERR_NET_INVALID_CONTEXT ): + rc = "NET - The context is invalid, eg because it was free()ed"; + break; + + case -( MBEDTLS_ERR_NET_POLL_FAILED ): + rc = "NET - Polling the net context failed"; + break; + + case -( MBEDTLS_ERR_NET_BAD_INPUT_DATA ): + rc = "NET - Input invalid"; + break; + #endif /* MBEDTLS_NET_C */ + + #if defined( MBEDTLS_OID_C ) + case -( MBEDTLS_ERR_OID_NOT_FOUND ): + rc = "OID - OID is not found"; + break; + + case -( MBEDTLS_ERR_OID_BUF_TOO_SMALL ): + rc = "OID - output buffer is too small"; + break; + #endif /* MBEDTLS_OID_C */ + + #if defined( MBEDTLS_PADLOCK_C ) + case -( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ): + rc = "PADLOCK - Input data should be aligned"; + break; + #endif /* MBEDTLS_PADLOCK_C */ + + #if defined( MBEDTLS_PLATFORM_C ) + case -( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ): + rc = "PLATFORM - Hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ): + rc = "PLATFORM - The requested feature is not supported by the platform"; + break; + #endif /* MBEDTLS_PLATFORM_C */ + + #if defined( MBEDTLS_POLY1305_C ) + case -( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ): + rc = "POLY1305 - Invalid input parameter(s)"; + break; + + case -( MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE ): + rc = "POLY1305 - Feature not available. For example, s part of the API is not implemented"; + break; + + case -( MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED ): + rc = "POLY1305 - Poly1305 hardware accelerator failed"; + break; + #endif /* MBEDTLS_POLY1305_C */ + + #if defined( MBEDTLS_RIPEMD160_C ) + case -( MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED ): + rc = "RIPEMD160 - RIPEMD160 hardware accelerator failed"; + break; + #endif /* MBEDTLS_RIPEMD160_C */ + + #if defined( MBEDTLS_SHA1_C ) + case -( MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED ): + rc = "SHA1 - SHA-1 hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ): + rc = "SHA1 - SHA-1 input data was malformed"; + break; + #endif /* MBEDTLS_SHA1_C */ + + #if defined( MBEDTLS_SHA256_C ) + case -( MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED ): + rc = "SHA256 - SHA-256 hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ): + rc = "SHA256 - SHA-256 input data was malformed"; + break; + #endif /* MBEDTLS_SHA256_C */ + + #if defined( MBEDTLS_SHA512_C ) + case -( MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED ): + rc = "SHA512 - SHA-512 hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ): + rc = "SHA512 - SHA-512 input data was malformed"; + break; + #endif /* MBEDTLS_SHA512_C */ + + #if defined( MBEDTLS_THREADING_C ) + case -( MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE ): + rc = "THREADING - The selected feature is not available"; + break; + + case -( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ): + rc = "THREADING - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_THREADING_MUTEX_ERROR ): + rc = "THREADING - Locking / unlocking / free failed with error code"; + break; + #endif /* MBEDTLS_THREADING_C */ + + #if defined( MBEDTLS_XTEA_C ) + case -( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ): + rc = "XTEA - The data input has an invalid length"; + break; + + case -( MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED ): + rc = "XTEA - XTEA hardware accelerator failed"; + break; + #endif /* MBEDTLS_XTEA_C */ + } + + return rc; +} diff --git a/bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_utils.c b/bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_utils.c new file mode 100644 index 0000000..ce42086 --- /dev/null +++ b/bsp/aws_libraries/3rdparty/mbedtls_utils/mbedtls_utils.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/** + * @file mbedtls_utils.c + * @brief Helper functions originating from mbedTLS. + */ + +/* Standard includes. */ +#include + +/* mbedTLS includes. */ +#include "mbedtls/base64.h" +#include "mbedtls/rsa.h" +#include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/oid.h" +/*-----------------------------------------------------------*/ + +/* @brief Converts PEM documents into DER formatted byte arrays. + * This is a helper function from mbedTLS util pem2der.c + * (https://github.com/ARMmbed/mbedtls/blob/development/programs/util/pem2der.c#L75) + * + * \param pucInput[in] Pointer to PEM object + * \param xLen[in] Length of PEM object + * \param pucOutput[out] Pointer to buffer where DER oboject will be placed + * \param pxOlen[in/out] Pointer to length of DER buffer. This value is updated + * to contain the actual length of the converted DER object. + * + * \return 0 if successful. Negative if conversion failed. If buffer is not + * large enough to hold converted object, pxOlen is still updated but -1 is returned. + * + */ +int convert_pem_to_der( const unsigned char * pucInput, + size_t xLen, + unsigned char * pucOutput, + size_t * pxOlen ) +{ + int lRet; + const unsigned char * pucS1; + const unsigned char * pucS2; + const unsigned char * pucEnd = pucInput + xLen; + size_t xOtherLen = 0; + + pucS1 = ( unsigned char * ) strstr( ( const char * ) pucInput, "-----BEGIN" ); + + if( pucS1 == NULL ) + { + return( -1 ); + } + + pucS2 = ( unsigned char * ) strstr( ( const char * ) pucInput, "-----END" ); + + if( pucS2 == NULL ) + { + return( -1 ); + } + + pucS1 += 10; + + while( pucS1 < pucEnd && *pucS1 != '-' ) + { + pucS1++; + } + + while( pucS1 < pucEnd && *pucS1 == '-' ) + { + pucS1++; + } + + if( *pucS1 == '\r' ) + { + pucS1++; + } + + if( *pucS1 == '\n' ) + { + pucS1++; + } + + if( ( pucS2 <= pucS1 ) || ( pucS2 > pucEnd ) ) + { + return( -1 ); + } + + lRet = mbedtls_base64_decode( NULL, 0, &xOtherLen, ( const unsigned char * ) pucS1, pucS2 - pucS1 ); + + if( lRet == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + { + return( lRet ); + } + + if( xOtherLen > *pxOlen ) + { + return( -1 ); + } + + if( ( lRet = mbedtls_base64_decode( pucOutput, xOtherLen, &xOtherLen, ( const unsigned char * ) pucS1, + pucS2 - pucS1 ) ) != 0 ) + { + return( lRet ); + } + + *pxOlen = xOtherLen; + + return( 0 ); +} +/*-----------------------------------------------------------*/ + + +/* This function is a modified version of the static function +rsa_rsassa_pkcs1_v15_encode() inside of rsa.c in mbedTLS. It has been extracted +so that FreeRTOS PKCS #11 libraries and testing may use it. */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ + +/* \brief Formats cryptographically hashed data for RSA signing in accordance + * with PKCS #1 version 1.5. + * + * Currently assumes SHA-256. + */ +int PKI_RSA_RSASSA_PKCS1_v15_Encode( const unsigned char * hash, + size_t dst_len, + unsigned char * dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char * p = dst; + const char * oid = NULL; + mbedtls_md_type_t md_alg = MBEDTLS_MD_SHA256; + unsigned int hashlen = 0; + + const mbedtls_md_info_t * md_info = mbedtls_md_info_from_type( md_alg ); + + if( md_info == NULL ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( ( 8 + hashlen + oid_size >= 0x80 ) || + ( 10 + hashlen < hashlen ) || + ( 10 + hashlen + oid_size < 10 + hashlen ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + nb_pad -= 10 + hashlen + oid_size; + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = ( unsigned char ) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = ( unsigned char ) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = ( unsigned char ) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = ( unsigned char ) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} diff --git a/bsp/aws_libraries/abstractions/mqtt_agent/freertos_agent_message.c b/bsp/aws_libraries/abstractions/mqtt_agent/freertos_agent_message.c new file mode 100644 index 0000000..76b1646 --- /dev/null +++ b/bsp/aws_libraries/abstractions/mqtt_agent/freertos_agent_message.c @@ -0,0 +1,74 @@ +/* + * FreeRTOS V202104.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file freertos_agent_message.c + * @brief Implements functions to interact with queues. + */ + +/* Standard includes. */ +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "semphr.h" + +/* Header include. */ +#include "freertos_agent_message.h" +#include "core_mqtt_agent_message_interface.h" + +/*-----------------------------------------------------------*/ + +bool Agent_MessageSend( MQTTAgentMessageContext_t * pMsgCtx, + MQTTAgentCommand_t * const * pCommandToSend, + uint32_t blockTimeMs ) +{ + BaseType_t queueStatus = pdFAIL; + + if( ( pMsgCtx != NULL ) && ( pCommandToSend != NULL ) ) + { + queueStatus = xQueueSendToBack( pMsgCtx->queue, pCommandToSend, pdMS_TO_TICKS( blockTimeMs ) ); + } + + return ( queueStatus == pdPASS ) ? true : false; +} + +/*-----------------------------------------------------------*/ + +bool Agent_MessageReceive( MQTTAgentMessageContext_t * pMsgCtx, + MQTTAgentCommand_t ** pReceivedCommand, + uint32_t blockTimeMs ) +{ + BaseType_t queueStatus = pdFAIL; + + if( ( pMsgCtx != NULL ) && ( pReceivedCommand != NULL ) ) + { + queueStatus = xQueueReceive( pMsgCtx->queue, pReceivedCommand, pdMS_TO_TICKS( blockTimeMs ) ); + } + + return ( queueStatus == pdPASS ) ? true : false; +} diff --git a/bsp/aws_libraries/abstractions/mqtt_agent/freertos_command_pool.c b/bsp/aws_libraries/abstractions/mqtt_agent/freertos_command_pool.c new file mode 100644 index 0000000..875323c --- /dev/null +++ b/bsp/aws_libraries/abstractions/mqtt_agent/freertos_command_pool.c @@ -0,0 +1,145 @@ +/* + * FreeRTOS V202104.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file freertos_command_pool.c + * @brief Implements functions to obtain and release commands. + */ + +/* Standard includes. */ +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "semphr.h" + +/* Header include. */ +#include "freertos_command_pool.h" +#include "freertos_agent_message.h" + +/*-----------------------------------------------------------*/ + +#define QUEUE_NOT_INITIALIZED ( 0U ) +#define QUEUE_INITIALIZED ( 1U ) + +/** + * @brief The pool of command structures used to hold information on commands (such + * as PUBLISH or SUBSCRIBE) between the command being created by an API call and + * completion of the command by the execution of the command's callback. + */ +static MQTTAgentCommand_t commandStructurePool[ MQTT_COMMAND_CONTEXTS_POOL_SIZE ]; + +/** + * @brief The message context used to guard the pool of MQTTAgentCommand_t structures. + * For FreeRTOS, this is implemented with a queue. Structures may be + * obtained by receiving a pointer from the queue, and returned by + * sending the pointer back into it. + */ +static MQTTAgentMessageContext_t commandStructMessageCtx; + +/** + * @brief Initialization status of the queue. + */ +static volatile uint8_t initStatus = QUEUE_NOT_INITIALIZED; + +/*-----------------------------------------------------------*/ + +void Agent_InitializePool( void ) +{ + size_t i; + MQTTAgentCommand_t * pCommand; + static uint8_t staticQueueStorageArea[ MQTT_COMMAND_CONTEXTS_POOL_SIZE * sizeof( MQTTAgentCommand_t * ) ]; + static StaticQueue_t staticQueueStructure; + bool commandAdded = false; + + if( initStatus == QUEUE_NOT_INITIALIZED ) + { + memset( ( void * ) commandStructurePool, 0x00, sizeof( commandStructurePool ) ); + commandStructMessageCtx.queue = xQueueCreateStatic( MQTT_COMMAND_CONTEXTS_POOL_SIZE, + sizeof( MQTTAgentCommand_t * ), + staticQueueStorageArea, + &staticQueueStructure ); + configASSERT( commandStructMessageCtx.queue ); + + /* Populate the queue. */ + for( i = 0; i < MQTT_COMMAND_CONTEXTS_POOL_SIZE; i++ ) + { + /* Store the address as a variable. */ + pCommand = &commandStructurePool[ i ]; + /* Send the pointer to the queue. */ + commandAdded = Agent_MessageSend( &commandStructMessageCtx, &pCommand, 0U ); + configASSERT( commandAdded ); + } + + initStatus = QUEUE_INITIALIZED; + } +} + +/*-----------------------------------------------------------*/ + +MQTTAgentCommand_t * Agent_GetCommand( uint32_t blockTimeMs ) +{ + MQTTAgentCommand_t * structToUse = NULL; + bool structRetrieved = false; + + /* Check queue has been created. */ + configASSERT( initStatus == QUEUE_INITIALIZED ); + + /* Retrieve a struct from the queue. */ + structRetrieved = Agent_MessageReceive( &commandStructMessageCtx, &( structToUse ), blockTimeMs ); + + if( !structRetrieved ) + { + LogError( ( "No command structure available." ) ); + } + + return structToUse; +} + +/*-----------------------------------------------------------*/ + +bool Agent_ReleaseCommand( MQTTAgentCommand_t * pCommandToRelease ) +{ + bool structReturned = false; + + configASSERT( initStatus == QUEUE_INITIALIZED ); + + /* See if the structure being returned is actually from the pool. */ + if( ( pCommandToRelease >= commandStructurePool ) && + ( pCommandToRelease < ( commandStructurePool + MQTT_COMMAND_CONTEXTS_POOL_SIZE ) ) ) + { + structReturned = Agent_MessageSend( &commandStructMessageCtx, &pCommandToRelease, 0U ); + + /* The send should not fail as the queue was created to hold every command + * in the pool. */ + configASSERT( structReturned ); + LogDebug( ( "Returned Command Context %d to pool", + ( int ) ( pCommandToRelease - commandStructurePool ) ) ); + } + + return structReturned; +} diff --git a/bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_agent_message.h b/bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_agent_message.h new file mode 100644 index 0000000..45bcd45 --- /dev/null +++ b/bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_agent_message.h @@ -0,0 +1,84 @@ +/* + * FreeRTOS V202104.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file freertos_agent_message.h + * @brief Functions to interact with queues. + */ +#ifndef FREERTOS_AGENT_MESSAGE_H +#define FREERTOS_AGENT_MESSAGE_H + +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" + +/* Include MQTT agent messaging interface. */ +#include "core_mqtt_agent_message_interface.h" + +/** + * @ingroup mqtt_agent_struct_types + * @brief Context with which tasks may deliver messages to the agent. + */ +struct MQTTAgentMessageContext +{ + QueueHandle_t queue; +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Send a message to the specified context. + * Must be thread safe. + * + * @param[in] pMsgCtx An #MQTTAgentMessageContext_t. + * @param[in] pCommandToSend Pointer to address to send to queue. + * @param[in] blockTimeMs Block time to wait for a send. + * + * @return `true` if send was successful, else `false`. + */ +bool Agent_MessageSend( MQTTAgentMessageContext_t * pMsgCtx, + MQTTAgentCommand_t * const * pCommandToSend, + uint32_t blockTimeMs ); + +/** + * @brief Receive a message from the specified context. + * Must be thread safe. + * + * @param[in] pMsgCtx An #MQTTAgentMessageContext_t. + * @param[in] pReceivedCommand Pointer to write address of received command. + * @param[in] blockTimeMs Block time to wait for a receive. + * + * @return `true` if receive was successful, else `false`. + */ +bool Agent_MessageReceive( MQTTAgentMessageContext_t * pMsgCtx, + MQTTAgentCommand_t ** pReceivedCommand, + uint32_t blockTimeMs ); + +#endif /* FREERTOS_AGENT_MESSAGE_H */ diff --git a/bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_command_pool.h b/bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_command_pool.h new file mode 100644 index 0000000..b65a834 --- /dev/null +++ b/bsp/aws_libraries/abstractions/mqtt_agent/include/freertos_command_pool.h @@ -0,0 +1,90 @@ +/* + * FreeRTOS V202104.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file freertos_command_pool.h + * @brief Functions to obtain and release a command. + */ +#ifndef FREERTOS_COMMAND_POOL_H +#define FREERTOS_COMMAND_POOL_H + +/* MQTT agent includes. */ +#include "core_mqtt_agent.h" + +/** + * @brief The number of structures to allocate in the command pool. + */ +#ifndef MQTT_COMMAND_CONTEXTS_POOL_SIZE + #define MQTT_COMMAND_CONTEXTS_POOL_SIZE ( 10U ) +#endif + +/** + * @brief Initialize the common task pool. Not thread safe. + */ +void Agent_InitializePool( void ); + +/** + * @brief Obtain a MQTTAgentCommand_t structure from the pool of structures managed by the agent. + * + * @note MQTTAgentCommand_t structures hold everything the MQTT agent needs to process a + * command that originates from application. Examples of commands are PUBLISH and + * SUBSCRIBE. The MQTTAgentCommand_t structure must persist for the duration of the command's + * operation so are obtained from a pool of statically allocated structures when a + * new command is created, and returned to the pool when the command is complete. + * The MQTT_COMMAND_CONTEXTS_POOL_SIZE configuration file constant defines how many + * structures the pool contains. + * + * @param[in] blockTimeMs The length of time the calling task should remain in the + * Blocked state (so not consuming any CPU time) to wait for a MQTTAgentCommand_t structure to + * become available should one not be immediately at the time of the call. + * + * @return A pointer to a MQTTAgentCommand_t structure if one becomes available before + * blockTimeMs time expired, otherwise NULL. + */ +MQTTAgentCommand_t * Agent_GetCommand( uint32_t blockTimeMs ); + +/** + * @brief Give a MQTTAgentCommand_t structure back to the the pool of structures managed by + * the agent. + * + * @note MQTTAgentCommand_t structures hold everything the MQTT agent needs to process a + * command that originates from application. Examples of commands are PUBLISH and + * SUBSCRIBE. The MQTTAgentCommand_t structure must persist for the duration of the command's + * operation so are obtained from a pool of statically allocated structures when a + * new command is created, and returned to the pool when the command is complete. + * The MQTT_COMMAND_CONTEXTS_POOL_SIZE configuration file constant defines how many + * structures the pool contains. + * + * @param[in] pCommandToRelease A pointer to the MQTTAgentCommand_t structure to return to + * the pool. The structure must first have been obtained by calling + * Agent_GetCommand(), otherwise Agent_ReleaseCommand() will + * have no effect. + * + * @return true if the MQTTAgentCommand_t structure was returned to the pool, otherwise false. + */ +bool Agent_ReleaseCommand( MQTTAgentCommand_t * pCommandToRelease ); + +#endif /* FREERTOS_COMMAND_POOL_H */ diff --git a/bsp/aws_libraries/abstractions/pkcs11/corePKCS11/source/dependency/3rdparty/mbedtls_utils/mbedtls_error.h b/bsp/aws_libraries/abstractions/pkcs11/corePKCS11/source/dependency/3rdparty/mbedtls_utils/mbedtls_error.h new file mode 100644 index 0000000..0d9039a --- /dev/null +++ b/bsp/aws_libraries/abstractions/pkcs11/corePKCS11/source/dependency/3rdparty/mbedtls_utils/mbedtls_error.h @@ -0,0 +1,63 @@ +/* + * FreeRTOS Error Code Stringification utilities for mbed TLS v2.16.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file mbedtls_error.h + * @brief Stringification utilities for high-level and low-level codes of mbed TLS. + */ + +#ifndef _MBEDTLS_ERROR_H_ + #define _MBEDTLS_ERROR_H_ + + + #ifdef __cplusplus + extern "C" { + #endif + +/** + * @brief Translate an mbed TLS high level code into its string representation. + * Result includes a terminating null byte. + * + * @param errnum The error code containing the high-level code. + * @return The string representation if high-level code is present; otherwise NULL. + * + * @warning The string returned by this function must never be modified. + */ + const char * mbedtls_strerror_highlevel( int errnum ); + +/** + * @brief Translate an mbed TLS low level code into its string representation, + * Result includes a terminating null byte. + * + * @param errnum The error code containing the low-level code. + * @return The string representation if low-level code is present; otherwise NULL. + * + * @warning The string returned by this function must never be modified. + */ + const char * mbedtls_strerror_lowlevel( int errnum ); + + #ifdef __cplusplus + } + #endif + +#endif /* _MBEDTLS_ERROR_H_ */ diff --git a/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa.c b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa.c new file mode 100644 index 0000000..95106b7 --- /dev/null +++ b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa.c @@ -0,0 +1,3641 @@ +/* + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2019-2020 Arm Limited. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * This file is derivative of amazon-freertos\libraries\abstractions\pkcs11\mbedtls + * \iot_pkcs11_mbedtls.c(amazon-freertos commit 74875b1d2) + */ + +/** + * @file iot_pkcs11_psa.c + * @brief PSA based PKCS#11 implementation. + */ + +/* C runtime includes. */ +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" + +/* PKCS#11 includes. */ +#include "core_pkcs11_config.h" +#include "core_pkcs11.h" +#include "iot_pkcs11_psa_object_management.h" +#include "iot_pkcs11_psa_input_format.h" + +/* Crypto include. */ +#include "iot_crypto.h" + +/* mbedTLS includes. */ +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#define PKCS11_PRINT( X ) vLoggingPrintf X +#define PKCS11_WARNING_PRINT( X ) /* vLoggingPrintf X */ +#define pkcs11NO_OPERATION ( ( CK_MECHANISM_TYPE ) 0xFFFFFFFFUL ) + +/* + * The length of the content of an ECPoint n uncompressed + * representation format defined by SEC1 §2.3.3. + */ +#define pkcs11KEY_ECPOINT_LENGTH ( 65 ) + +/** + * @brief Cryptoki module attribute definitions. + */ +#define pkcs11SLOT_ID ( 1 ) + +/* Private defines for checking that attribute templates are complete. */ +#define LABEL_IN_TEMPLATE ( 1U ) +#define PRIVATE_IN_TEMPLATE ( 1U << 1 ) +#define SIGN_IN_TEMPLATE ( 1U << 2 ) +#define EC_PARAMS_IN_TEMPLATE ( 1U << 3 ) +#define VERIFY_IN_TEMPLATE ( 1U << 4 ) + +/** + * @brief Helper definitions. + */ +#define PKCS11_MODULE_IS_INITIALIZED ( ( xP11Context.xIsInitialized == CK_TRUE ) ? CK_TRUE : CK_FALSE ) +#define PKCS11_SESSION_IS_OPEN( xSessionHandle ) ( ( ( ( P11SessionPtr_t ) xSessionHandle )->xOpened ) == CK_TRUE ? CKR_OK : CKR_SESSION_CLOSED ) +#define PKCS11_SESSION_IS_VALID( xSessionHandle ) ( ( ( P11SessionPtr_t ) xSessionHandle != NULL ) ? PKCS11_SESSION_IS_OPEN( xSessionHandle ) : CKR_SESSION_HANDLE_INVALID ) +#define PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSessionHandle ) ( PKCS11_MODULE_IS_INITIALIZED ? PKCS11_SESSION_IS_VALID( xSessionHandle ) : CKR_CRYPTOKI_NOT_INITIALIZED ) + +typedef struct P11Object_t +{ + CK_OBJECT_HANDLE xHandle; /* The "PSA Handle". */ + CK_BYTE xLabel[ pkcs11configMAX_LABEL_LENGTH + 1 ]; /* Plus 1 for the null terminator. */ +} P11Object_t; + +/* This structure helps the aws_pkcs11_psa.c maintain a mapping of all objects in one place. + * The ObjectList maintains a list of what object handles are available. + */ +typedef struct P11ObjectList_t +{ + SemaphoreHandle_t xMutex; /* Mutex that protects write operations to the xObjects array. */ + P11Object_t xObjects[ pkcs11configMAX_NUM_OBJECTS ]; +} P11ObjectList_t; + +/* PKCS #11 Module Object */ +typedef struct P11Struct_t +{ + CK_BBOOL xIsInitialized; /* Indicates whether PKCS #11 module has been initialized with a call to C_Initialize. */ + P11ObjectList_t xObjectList; /* List of PKCS #11 objects that have been found/created since module initialization. + * The array position indicates the "App Handle" */ +} P11Struct_t, * P11Context_t; + +/* The global PKCS #11 module object. + * Entropy/randomness and object lists are shared across PKCS #11 sessions. */ +static P11Struct_t xP11Context; + +/** + * @brief Session structure. + */ +typedef struct P11Session +{ + CK_ULONG ulState; + CK_BBOOL xOpened; + CK_MECHANISM_TYPE xOperationInProgress; + CK_BBOOL xFindObjectInit; + CK_BYTE * pxFindObjectLabel; + uint8_t xFindObjectLabelLength; + SemaphoreHandle_t xVerifyMutex; /* Protects the verification key from being modified while in use. */ + psa_key_handle_t uxVerifyKey; + CK_MECHANISM_TYPE xVerifyMechanism; /* The mechanism of verify operation in progress. Set during C_VerifyInit. */ + psa_algorithm_t xVerifyAlgorithm; /* Verify algorithm that is compatible with the type of key. */ + SemaphoreHandle_t xSignMutex; /* Protects the signing key from being modified while in use. */ + psa_key_handle_t uxSignKey; + CK_MECHANISM_TYPE xSignMechanism; /* Mechanism of the sign operation in progress. Set during C_SignInit. */ + psa_algorithm_t xSignAlgorithm; /* Signature algorithm that is compatible with the type of key. */ + psa_hash_operation_t *pxHashOperationHandle; /* hash operation handle in PSA crypto service. */ +} P11Session_t, * P11SessionPtr_t; + +/* + * PKCS#11 module implementation. + */ + +/** + * @brief PKCS#11 interface functions implemented by this Cryptoki module. + */ +static CK_FUNCTION_LIST prvP11FunctionList = +{ + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, + C_Initialize, + C_Finalize, + NULL, /*C_GetInfo */ + C_GetFunctionList, + C_GetSlotList, + NULL, /*C_GetSlotInfo*/ + C_GetTokenInfo, + NULL, /*C_GetMechanismList*/ + C_GetMechanismInfo, + C_InitToken, + NULL, /*C_InitPIN*/ + NULL, /*C_SetPIN*/ + C_OpenSession, + C_CloseSession, + NULL, /*C_CloseAllSessions*/ + NULL, /*C_GetSessionInfo*/ + NULL, /*C_GetOperationState*/ + NULL, /*C_SetOperationState*/ + C_Login, /*C_Login*/ + NULL, /*C_Logout*/ + C_CreateObject, + NULL, /*C_CopyObject*/ + C_DestroyObject, + NULL, /*C_GetObjectSize*/ + C_GetAttributeValue, + NULL, /*C_SetAttributeValue*/ + C_FindObjectsInit, + C_FindObjects, + C_FindObjectsFinal, + NULL, /*C_EncryptInit*/ + NULL, /*C_Encrypt*/ + NULL, /*C_EncryptUpdate*/ + NULL, /*C_EncryptFinal*/ + NULL, /*C_DecryptInit*/ + NULL, /*C_Decrypt*/ + NULL, /*C_DecryptUpdate*/ + NULL, /*C_DecryptFinal*/ + C_DigestInit, + NULL, /*C_Digest*/ + C_DigestUpdate, + NULL, /* C_DigestKey*/ + C_DigestFinal, + C_SignInit, + C_Sign, + NULL, /*C_SignUpdate*/ + NULL, /*C_SignFinal*/ + NULL, /*C_SignRecoverInit*/ + NULL, /*C_SignRecover*/ + C_VerifyInit, + C_Verify, + NULL, /*C_VerifyUpdate*/ + NULL, /*C_VerifyFinal*/ + NULL, /*C_VerifyRecoverInit*/ + NULL, /*C_VerifyRecover*/ + NULL, /*C_DigestEncryptUpdate*/ + NULL, /*C_DecryptDigestUpdate*/ + NULL, /*C_SignEncryptUpdate*/ + NULL, /*C_DecryptVerifyUpdate*/ + NULL, /*C_GenerateKey*/ + C_GenerateKeyPair, + NULL, /*C_WrapKey*/ + NULL, /*C_UnwrapKey*/ + NULL, /*C_DeriveKey*/ + NULL, /*C_SeedRandom*/ + C_GenerateRandom, + NULL, /*C_GetFunctionStatus*/ + NULL, /*C_CancelFunction*/ + NULL /*C_WaitForSlotEvent*/ +}; + +/*-----------------------------------------------------------*/ +/** + * @brief Maps an opaque caller session handle into its internal state structure. + */ +P11SessionPtr_t prvSessionPointerFromHandle( CK_SESSION_HANDLE xSession ) +{ + return ( P11SessionPtr_t ) xSession; /*lint !e923 Allow casting integer type to pointer for handle. */ +} + +/** + * @brief Add an object that exists in NVM to the application object array. + * + * @param[in[ xPalHandle The handle used by the PKCS #11 PAL for object. + * @param[out] pxAppHandle Updated to contain the application handle corresponding to xPalHandle. + * @param[in] pcLabel Pointer to object label. + * @param[in] xLabelLength Length of the PKCS #11 label. + * + */ +CK_RV prvAddObjectToList( CK_OBJECT_HANDLE xPalHandle, + CK_OBJECT_HANDLE_PTR pxAppHandle, + uint8_t * pcLabel, + size_t xLabelLength ) +{ + CK_RV xResult = CKR_OK; + BaseType_t xGotSemaphore; + + CK_BBOOL xObjectFound = CK_FALSE; + int lInsertIndex = -1; + int lSearchIndex = pkcs11configMAX_NUM_OBJECTS - 1; + + xGotSemaphore = xSemaphoreTake( xP11Context.xObjectList.xMutex, portMAX_DELAY ); + + if( xGotSemaphore == pdTRUE ) + { + for( lSearchIndex = pkcs11configMAX_NUM_OBJECTS - 1; lSearchIndex >= 0; lSearchIndex-- ) + { + if( xP11Context.xObjectList.xObjects[ lSearchIndex ].xHandle == xPalHandle ) + { + /* Object already exists in list. */ + xObjectFound = CK_TRUE; + + /* Assign the object handle. */ + *pxAppHandle = lSearchIndex + 1; + break; + } + else if( xP11Context.xObjectList.xObjects[ lSearchIndex ].xHandle == CK_INVALID_HANDLE ) + { + lInsertIndex = lSearchIndex; + } + } + + if( xObjectFound == CK_FALSE ) + { + if( lInsertIndex != -1 ) + { + if( xLabelLength < pkcs11configMAX_LABEL_LENGTH ) + { + xP11Context.xObjectList.xObjects[ lInsertIndex ].xHandle = xPalHandle; + memcpy( xP11Context.xObjectList.xObjects[ lInsertIndex ].xLabel, pcLabel, xLabelLength ); + *pxAppHandle = lInsertIndex + 1; + } + else + { + xResult = CKR_DATA_LEN_RANGE; + } + } + else + { + xResult = CKR_BUFFER_TOO_SMALL; + } + } + + xSemaphoreGive( xP11Context.xObjectList.xMutex ); + } + else + { + xResult = CKR_CANT_LOCK; + } + + return xResult; +} + +/** + * @brief Looks up a PKCS #11 object's label and PAL handle given an application handle. + * + * @param[in] xAppHandle The handle of the object being lookedup for, used by the application. + * @param[out] xPalHandle Pointer to the handle corresponding to xPalHandle being used by the PAL. + * @param[out] ppcLabel Pointer to an array containing label. NULL if object not found. + * @param[out] pxLabelLength Pointer to label length (includes a string null terminator). + * 0 if no object found. + */ +void prvFindObjectInListByHandle( CK_OBJECT_HANDLE xAppHandle, + CK_OBJECT_HANDLE_PTR pxPalHandle, + uint8_t ** ppcLabel, + size_t * pxLabelLength ) +{ + int lIndex = xAppHandle - 1; + + *ppcLabel = NULL; + *pxLabelLength = 0; + *pxPalHandle = CK_INVALID_HANDLE; + + if( lIndex < pkcs11configMAX_NUM_OBJECTS ) /* Check that handle is in bounds. */ + { + if( xP11Context.xObjectList.xObjects[ lIndex ].xHandle != CK_INVALID_HANDLE ) + { + *ppcLabel = xP11Context.xObjectList.xObjects[ lIndex ].xLabel; + *pxLabelLength = strlen( ( const char * ) xP11Context.xObjectList.xObjects[ lIndex ].xLabel ) + 1; + *pxPalHandle = xP11Context.xObjectList.xObjects[ lIndex ].xHandle; + } + } +} + +/** + * @brief Searches the PKCS #11 module's object list for label and provides handle. + * + * @param[in] pcLabel Array containing label. + * @param[in] xLableLength Length of the label, in bytes. + * @param[out] pxPalHandle Pointer to the PAL handle to be provided. + * CK_INVALID_HANDLE if no object found. + * @param[out] pxAppHandle Pointer to the application handle to be provided. + * CK_INVALID_HANDLE if no object found. + */ +void prvFindObjectInListByLabel( uint8_t * pcLabel, + size_t xLabelLength, + CK_OBJECT_HANDLE_PTR pxPalHandle, + CK_OBJECT_HANDLE_PTR pxAppHandle ) +{ + uint8_t ucIndex; + + *pxPalHandle = CK_INVALID_HANDLE; + *pxAppHandle = CK_INVALID_HANDLE; + + for( ucIndex = 0; ucIndex < pkcs11configMAX_NUM_OBJECTS; ucIndex++ ) + { + if( 0 == memcmp( pcLabel, xP11Context.xObjectList.xObjects[ ucIndex ].xLabel, xLabelLength ) ) + { + *pxPalHandle = xP11Context.xObjectList.xObjects[ ucIndex ].xHandle; + *pxAppHandle = ucIndex + 1; /* Zero is not a valid handle, so let's offset by 1. */ + break; + } + } +} + +/** + * @brief This function is not implemented for this port. + * + * C_Login() is only implemented for compatibility with other ports. + * All inputs to this function are ignored, and calling this + * function on this port does not add any security. + * + * @return CKR_OK. + */ +CK_DECLARE_FUNCTION( CK_RV, C_Login )( CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen ) +{ + /* Avoid warnings about unused parameters. */ + ( void ) hSession; + ( void ) userType; + ( void ) pPin; + ( void ) ulPinLen; + + return CKR_OK; +} + +/* Helper function for parsing the templates of device certificates for + * C_CreateObject. */ +CK_RV prvCreateCertificate( CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ + CK_RV xResult = CKR_OK; + CK_BYTE_PTR pxCertificateValue = NULL; + CK_ULONG xCertificateLength = 0; + CK_ATTRIBUTE_PTR pxLabel = NULL; + CK_ATTRIBUTE_PTR pxClass = NULL; + CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE; + CK_CERTIFICATE_TYPE xCertificateType = 0; /* = CKC_X_509; */ + uint32_t ulIndex = 0; + CK_BBOOL xBool = CK_FALSE; + CK_ATTRIBUTE xAttribute; + + /* Search for the pointer to the certificate VALUE. */ + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + switch( xAttribute.type ) + { + case ( CKA_VALUE ): + pxCertificateValue = xAttribute.pValue; + xCertificateLength = xAttribute.ulValueLen; + break; + + case ( CKA_LABEL ): + + if( xAttribute.ulValueLen <= pkcs11configMAX_LABEL_LENGTH ) + { + pxLabel = &pxTemplate[ ulIndex ]; + } + else + { + xResult = CKR_DATA_LEN_RANGE; + } + + break; + + case ( CKA_CERTIFICATE_TYPE ): + memcpy( &xCertificateType, xAttribute.pValue, sizeof( CK_CERTIFICATE_TYPE ) ); + + if( xCertificateType != CKC_X_509 ) + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_TOKEN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only token key object is supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_CLASS ): + pxClass = &pxTemplate[ ulIndex ]; + break; + + case ( CKA_SUBJECT ): + + /* Do nothing. This was already parsed out of the template previously. */ + break; + + default: + xResult = CKR_TEMPLATE_INCONSISTENT; + break; + } + } + + if( ( pxCertificateValue == NULL ) || ( pxLabel == NULL ) ) + { + xResult = CKR_TEMPLATE_INCOMPLETE; + } + + if( xResult == CKR_OK ) + { + xPalHandle = PKCS11PSASaveObject( pxClass, pxLabel, pxCertificateValue, xCertificateLength, NULL ); + + if( xPalHandle == 0 ) /*Invalid handle. */ + { + xResult = CKR_DEVICE_MEMORY; + } + } + + if( xResult == CKR_OK ) + { + /* If adding the object to the list fails, an error will be returned. In this case, remain the + * saved object in PSA as the object list as well as the PSA secure storage will be searched when + * finding an object in C_findobjects. + */ + xResult = prvAddObjectToList( xPalHandle, pxObject, pxLabel->pValue, pxLabel->ulValueLen ); + } + + return xResult; +} + +#define PKCS11_INVALID_KEY_TYPE ( ( CK_KEY_TYPE ) 0xFFFFFFFF ) + +/* Helper to search an attribute for the key type attribute. */ +void prvGetKeyType( CK_KEY_TYPE * pxKeyType, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount ) +{ + uint32_t ulIndex; + CK_ATTRIBUTE xAttribute; + + *pxKeyType = PKCS11_INVALID_KEY_TYPE; + + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + if( xAttribute.type == CKA_KEY_TYPE ) + { + memcpy( pxKeyType, xAttribute.pValue, sizeof( CK_KEY_TYPE ) ); + break; + } + } +} + +/* Helper to search a template for the label attribute. */ +void prvGetLabel( CK_ATTRIBUTE_PTR * ppxLabel, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount ) +{ + CK_ATTRIBUTE xAttribute; + uint32_t ulIndex; + + *ppxLabel = NULL; + + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + if( xAttribute.type == CKA_LABEL ) + { + *ppxLabel = &pxTemplate[ ulIndex ]; + break; + } + } +} + +/* Helper function for checking attribute templates of elliptic curve + * private keys before import with C_CreateObject. */ +CK_RV prvCreateEcPrivateKey( mbedtls_pk_context * pxMbedContext, + CK_ATTRIBUTE_PTR * ppxLabel, + CK_ATTRIBUTE_PTR * ppxClass, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ + CK_RV xResult = CKR_OK; + int lMbedReturn; + CK_BBOOL xBool; + uint32_t ulIndex; + CK_ATTRIBUTE xAttribute; + *ppxLabel = NULL; + *ppxClass = NULL; + + /* Key will be assembled in the mbedTLS key context and then exported to DER for storage. */ + mbedtls_ecp_keypair * pxKeyPair = ( mbedtls_ecp_keypair * ) pxMbedContext->pk_ctx; + + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + switch( xAttribute.type ) + { + case ( CKA_CLASS ): + *ppxClass = &pxTemplate[ ulIndex ]; + break; + + case ( CKA_KEY_TYPE ): + + /* Do nothing. + * Key type and object type were checked previously. */ + break; + + case ( CKA_TOKEN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only token key creation is supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_SIGN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only keys with signing priveledges are supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_LABEL ): + + if( xAttribute.ulValueLen <= pkcs11configMAX_LABEL_LENGTH ) + { + *ppxLabel = &pxTemplate[ ulIndex ]; + } + else + { + xResult = CKR_DATA_LEN_RANGE; + } + + break; + + case ( CKA_EC_PARAMS ): + + if( memcmp( ( CK_BYTE[] ) pkcs11DER_ENCODED_OID_P256, xAttribute.pValue, xAttribute.ulValueLen ) ) + { + PKCS11_PRINT( ( "ERROR: Only elliptic curve P-256 is supported.\r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_VALUE ): + lMbedReturn = mbedtls_mpi_read_binary( &pxKeyPair->d, + xAttribute.pValue, + xAttribute.ulValueLen ); + + if( lMbedReturn != 0 ) + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + default: + xResult = CKR_TEMPLATE_INCONSISTENT; + break; + } + } + + return xResult; +} + +/* Helper function for parsing RSA Private Key attribute templates + * for C_CreateObject. */ +CK_RV prvCreateRsaPrivateKey( mbedtls_pk_context * pxMbedContext, + CK_ATTRIBUTE_PTR * ppxLabel, + CK_ATTRIBUTE_PTR * ppxClass, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ + CK_RV xResult = CKR_OK; + mbedtls_rsa_context * pxRsaContext; + int lMbedReturn = 0; + CK_BBOOL xBool; + uint32_t ulIndex; + CK_ATTRIBUTE xAttribute; + + *ppxLabel = NULL; + *ppxClass = NULL; + pxRsaContext = pxMbedContext->pk_ctx; + mbedtls_rsa_init( pxRsaContext, MBEDTLS_RSA_PKCS_V15, 0 /*ignored.*/ ); + + /* Parse template and collect the relevant parts. */ + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + switch( xAttribute.type ) + { + case ( CKA_CLASS ): + *ppxClass = &pxTemplate[ ulIndex ]; + break; + + case ( CKA_KEY_TYPE ): + + /* Do nothing. + * Key type & object type were checked previously. + */ + break; + + case ( CKA_TOKEN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only token key creation is supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_LABEL ): + + if( xAttribute.ulValueLen <= pkcs11configMAX_LABEL_LENGTH ) + { + *ppxLabel = &pxTemplate[ ulIndex ]; + } + else + { + xResult = CKR_DATA_LEN_RANGE; + } + + break; + + case ( CKA_SIGN ): + memcpy( &xBool, xAttribute.pValue, xAttribute.ulValueLen ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "Only RSA private keys with signing permissions supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + break; + + case ( CKA_MODULUS ): + lMbedReturn = mbedtls_rsa_import_raw( pxRsaContext, + xAttribute.pValue, xAttribute.ulValueLen, /* N */ + NULL, 0, /* P */ + NULL, 0, /* Q */ + NULL, 0, /* D */ + NULL, 0 ); /* E */ + break; + + case ( CKA_PUBLIC_EXPONENT ): + lMbedReturn = mbedtls_rsa_import_raw( pxRsaContext, + NULL, 0, /* N */ + NULL, 0, /* P */ + NULL, 0, /* Q */ + NULL, 0, /* D */ + xAttribute.pValue, xAttribute.ulValueLen ); /* E */ + break; + + case ( CKA_PRIME_1 ): + lMbedReturn = mbedtls_rsa_import_raw( pxRsaContext, + NULL, 0, /* N */ + xAttribute.pValue, xAttribute.ulValueLen, /* P */ + NULL, 0, /* Q */ + NULL, 0, /* D */ + NULL, 0 ); /* E */ + break; + + case ( CKA_PRIME_2 ): + lMbedReturn = mbedtls_rsa_import_raw( pxRsaContext, + NULL, 0, /* N */ + NULL, 0, /* P */ + xAttribute.pValue, xAttribute.ulValueLen, /* Q */ + NULL, 0, /* D */ + NULL, 0 ); /* E */ + break; + + case ( CKA_PRIVATE_EXPONENT ): + lMbedReturn = mbedtls_rsa_import_raw( pxRsaContext, + NULL, 0, /* N */ + NULL, 0, /* P */ + NULL, 0, /* Q */ + xAttribute.pValue, xAttribute.ulValueLen, /* D */ + NULL, 0 ); /* E */ + break; + + case ( CKA_EXPONENT_1 ): + lMbedReturn = mbedtls_mpi_read_binary( &pxRsaContext->DP, xAttribute.pValue, xAttribute.ulValueLen ); + break; + + case ( CKA_EXPONENT_2 ): + lMbedReturn = mbedtls_mpi_read_binary( &pxRsaContext->DQ, xAttribute.pValue, xAttribute.ulValueLen ); + break; + + case ( CKA_COEFFICIENT ): + lMbedReturn = mbedtls_mpi_read_binary( &pxRsaContext->QP, xAttribute.pValue, xAttribute.ulValueLen ); + break; + + default: + PKCS11_PRINT( ( "Unknown attribute found for RSA private key. %d \r\n", xAttribute.type ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + break; + } + + if( lMbedReturn != 0 ) + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + } + + return xResult; +} + +/* Helper function for importing private keys using template + * C_CreateObject. */ +CK_RV prvCreatePrivateKey( CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ +/* + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n (256 bytes for RSA-2048) + * publicExponent INTEGER, -- e (3 or 4 bytes for RSA-2048) + * privateExponent INTEGER, -- d (about 256 bytes for RSA-2048) + * prime1 INTEGER, -- p (128 bytes for RSA-2048) + * prime2 INTEGER, -- q (128 bytes for RSA-2048) + * exponent1 INTEGER, -- d mod (p-1) (128 bytes for RSA-2048) + * exponent2 INTEGER, -- d mod (q-1) (128 bytes for RSA-2048) + * coefficient INTEGER, -- (inverse of q) mod p (128 bytes for RSA-2048) + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + * Besides, when encode the key, some ASN tags are also introduced. + * For RSA-2048, the encoded length should be around 1232 bytes. + */ +#define MAX_PRIVATE_KEY_SIZE 1300 + mbedtls_pk_context xMbedContext; + int lDerKeyLength = 0; + int compare = 0; + CK_BYTE_PTR pxDerKey = NULL; + CK_RV xResult = CKR_OK; + CK_KEY_TYPE xKeyType; + CK_ATTRIBUTE_PTR pxLabel = NULL; + CK_ATTRIBUTE_PTR pxClass = NULL; + CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE; + mbedtls_rsa_context * pxRsaCtx = NULL; + mbedtls_ecp_keypair * pxKeyPair = NULL; + prvGetKeyType( &xKeyType, pxTemplate, ulCount ); + + mbedtls_pk_init( &xMbedContext ); + if( xKeyType == CKK_RSA ) + { + /* mbedtls_rsa_context must be malloc'ed to use with mbedtls_pk_free function. */ + pxRsaCtx = pvPortMalloc( sizeof( mbedtls_rsa_context ) ); + + if( pxRsaCtx != NULL ) + { + xMbedContext.pk_ctx = pxRsaCtx; + xMbedContext.pk_info = &mbedtls_rsa_info; + xResult = prvCreateRsaPrivateKey( &xMbedContext, + &pxLabel, + &pxClass, + pxTemplate, + ulCount, + pxObject ); + } + else + { + xResult = CKR_HOST_MEMORY; + } + } + + #if ( pkcs11configSUPPRESS_ECDSA_MECHANISM != 1 ) + else if( xKeyType == CKK_EC ) /* CKK_EC = CKK_ECDSA. */ + { + /* Key will be assembled in the mbedTLS key context and then exported to DER for storage. */ + prvGetLabel( &pxLabel, pxTemplate, ulCount ); + + /* An mbedTLS key is comprised of 2 pieces of data- an "info" and a "context". + * Since a valid key was not found by prvGetExistingKeyComponent, we are going to initialize + * the structure so that the mbedTLS structures will look the same as they would if a key + * had been found, minus the public key component. */ + + /* If a key had been found by prvGetExistingKeyComponent, the keypair context + * would have been malloc'ed. */ + pxKeyPair = pvPortMalloc( sizeof( mbedtls_ecp_keypair ) ); + + if( pxKeyPair != NULL ) + { + /* Initialize the info. */ + xMbedContext.pk_info = &mbedtls_eckey_info; + + /* Initialize the context. */ + xMbedContext.pk_ctx = pxKeyPair; + mbedtls_ecp_keypair_init( pxKeyPair ); + mbedtls_ecp_group_init( &pxKeyPair->grp ); + /*/ * At this time, only P-256 curves are supported. * / */ + mbedtls_ecp_group_load( &pxKeyPair->grp, MBEDTLS_ECP_DP_SECP256R1 ); + } + else + { + xResult = CKR_HOST_MEMORY; + } + + xResult = prvCreateEcPrivateKey( &xMbedContext, + &pxLabel, + &pxClass, + pxTemplate, + ulCount, + pxObject ); + } + #endif /* if ( pkcs11configSUPPRESS_ECDSA_MECHANISM != 1 ) */ + else + { + xResult = CKR_MECHANISM_INVALID; + } + + /* Convert back to DER and save to memory. */ + if( xResult == CKR_OK ) + { + pxDerKey = pvPortMalloc( MAX_PRIVATE_KEY_SIZE ); + + if( pxDerKey == NULL ) + { + xResult = CKR_HOST_MEMORY; + } + } + + if( xResult == CKR_OK ) + { + lDerKeyLength = mbedtls_pk_write_key_der( &xMbedContext, pxDerKey, MAX_PRIVATE_KEY_SIZE ); + + if( lDerKeyLength < 0 ) + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + /* Do not clean up the mbedTLS key context here as it will be used in psa_save_object. */ + } + + /* Save the object to device NVM. */ + if( xResult == CKR_OK ) + { + xPalHandle = PKCS11PSASaveObject( pxClass, + pxLabel, + pxDerKey + ( MAX_PRIVATE_KEY_SIZE - lDerKeyLength ), + lDerKeyLength, + &xMbedContext ); + + if( xPalHandle == 0 ) + { + xResult = CKR_DEVICE_MEMORY; + } + + mbedtls_pk_free( &xMbedContext ); + + } + + /* Store the PAL handle/label/application handle in lookup. */ + if( xResult == CKR_OK ) + { + xResult = prvAddObjectToList( xPalHandle, pxObject, pxLabel->pValue, pxLabel->ulValueLen ); + } + + if( pxDerKey != NULL ) + { + vPortFree( pxDerKey ); + } + + return xResult; +} + +/* Helper function for importing elliptic curve public keys from + * template using C_CreateObject. */ +CK_RV prvCreateECPublicKey( mbedtls_pk_context * pxMbedContext, + CK_ATTRIBUTE_PTR * ppxLabel, + CK_ATTRIBUTE_PTR *ppxClass, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ + CK_RV xResult = CKR_OK; + int lMbedReturn; + CK_BBOOL xBool; + uint32_t ulIndex; + CK_ATTRIBUTE xAttribute; + *ppxLabel = NULL; + *ppxClass = NULL; + + /* Key will be assembled in the mbedTLS key context and then exported to DER for storage. */ + mbedtls_ecp_keypair * pxKeyPair = ( mbedtls_ecp_keypair * ) pxMbedContext->pk_ctx; + + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + switch( xAttribute.type ) + { + case ( CKA_CLASS ): + *ppxClass = &pxTemplate[ ulIndex ]; + case ( CKA_KEY_TYPE ): + + /* Do nothing. + * Key type and class were checked previously. */ + break; + + case ( CKA_TOKEN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only token key creation is supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_LABEL ): + + if( xAttribute.ulValueLen < pkcs11configMAX_LABEL_LENGTH ) + { + *ppxLabel = &pxTemplate[ ulIndex ]; + } + else + { + xResult = CKR_DATA_LEN_RANGE; + } + + break; + + case ( CKA_VERIFY ): + memcpy( &xBool, xAttribute.pValue, xAttribute.ulValueLen ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "Only EC Public Keys with verify permissions supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_EC_PARAMS ): + + if( memcmp( ( CK_BYTE[] ) pkcs11DER_ENCODED_OID_P256, xAttribute.pValue, xAttribute.ulValueLen ) ) + { + PKCS11_PRINT( ( "ERROR: Only elliptic curve P-256 is supported.\r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_EC_POINT ): + /* The first 2 bytes are for ASN1 type/length encoding. */ + lMbedReturn = mbedtls_ecp_point_read_binary( &pxKeyPair->grp, &pxKeyPair->Q, ( ( uint8_t * ) ( xAttribute.pValue ) + 2 ), ( xAttribute.ulValueLen - 2 ) ); + + if( lMbedReturn != 0 ) + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + default: + PKCS11_PRINT( ( "Unsupported attribute found for EC public key. %d \r\n", xAttribute.type ) ); + xResult = CKR_ATTRIBUTE_TYPE_INVALID; + break; + } + } + + return xResult; +} + +/* Helper function for importing public keys using + * C_CreateObject. */ +CK_RV prvCreatePublicKey( CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n (256 bytes for RSA-2048) + * publicExponent INTEGER -- e (3 or 4 bytes for RSA-2048) + * } + + * Besides, when encoding the key, some ASN tags are also introduced. + */ +#define MAX_PUBLIC_KEY_SIZE 310 + mbedtls_pk_context xMbedContext; + int lDerKeyLength; + CK_BYTE_PTR pxDerKey = NULL; + CK_KEY_TYPE xKeyType; + CK_RV xResult = CKR_OK; + CK_ATTRIBUTE_PTR pxLabel = NULL; + CK_ATTRIBUTE_PTR pxClass = NULL; + CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE; + mbedtls_pk_init( &xMbedContext ); + mbedtls_ecp_keypair * pxKeyPair; + + prvGetKeyType( &xKeyType, pxTemplate, ulCount ); + if( xKeyType == CKK_RSA ) + { + xResult = CKR_ATTRIBUTE_TYPE_INVALID; + } + + #if ( pkcs11configSUPPRESS_ECDSA_MECHANISM != 1 ) + else if( xKeyType == CKK_EC ) /* CKK_EC = CKK_ECDSA. */ + { + prvGetLabel( &pxLabel, pxTemplate, ulCount ); + + /* An mbedTLS key is comprised of 2 pieces of data- an "info" and a "context". + * Since a valid key was not found by prvGetExistingKeyComponent, we are going to initialize + * the structure so that the mbedTLS structures will look the same as they would if a key + * had been found, minus the private key component. */ + + /* If a key had been found by prvGetExistingKeyComponent, the keypair context + * would have been malloc'ed. */ + pxKeyPair = pvPortMalloc( sizeof( mbedtls_ecp_keypair ) ); + + if( pxKeyPair != NULL ) + { + /* Initialize the info. */ + xMbedContext.pk_info = &mbedtls_eckey_info; + + /* Initialize the context. */ + xMbedContext.pk_ctx = pxKeyPair; + mbedtls_ecp_keypair_init( pxKeyPair ); + mbedtls_ecp_group_init( &pxKeyPair->grp ); + /*/ * At this time, only P-256 curves are supported. * / */ + mbedtls_ecp_group_load( &pxKeyPair->grp, MBEDTLS_ECP_DP_SECP256R1 ); + } + else + { + xResult = CKR_HOST_MEMORY; + } + + xResult = prvCreateECPublicKey( &xMbedContext, &pxLabel, &pxClass, pxTemplate, ulCount, pxObject ); + } + #endif /* if ( pkcs11configSUPPRESS_ECDSA_MECHANISM != 1 ) */ + else + { + PKCS11_PRINT( ( "Invalid key type %d \r\n", xKeyType ) ); + xResult = CKR_MECHANISM_INVALID; + } + + if( xResult == CKR_OK ) + { + /* Store the key.*/ + pxDerKey = pvPortMalloc( MAX_PUBLIC_KEY_SIZE ); + + if( pxDerKey == NULL ) + { + xResult = CKR_HOST_MEMORY; + } + } + + if( xResult == CKR_OK ) + { + lDerKeyLength = mbedtls_pk_write_pubkey_der( &xMbedContext, pxDerKey, MAX_PUBLIC_KEY_SIZE ); + + /* Do not clean up the mbedTLS key context here as it will be used in psa_save_object. */ + } + + if( xResult == CKR_OK ) + { + xPalHandle = PKCS11PSASaveObject( pxClass, + pxLabel, + pxDerKey + ( MAX_PUBLIC_KEY_SIZE - lDerKeyLength ), + lDerKeyLength, + &xMbedContext ); + + if( xPalHandle == CK_INVALID_HANDLE ) + { + xResult = CKR_DEVICE_MEMORY; + } + + mbedtls_pk_free( &xMbedContext ); + } + + if( xResult == CKR_OK ) + { + xResult = prvAddObjectToList( xPalHandle, pxObject, pxLabel->pValue, pxLabel->ulValueLen ); + } + + if( pxDerKey != NULL ) + { + vPortFree( pxDerKey ); + } + + return xResult; +} + +CK_RV prvMbedTLS_Initialize( void ) +{ + CK_RV xResult = CKR_OK; + SemaphoreHandle_t xMutex = NULL; + + if( xP11Context.xIsInitialized == CK_TRUE ) + { + xResult = CKR_CRYPTOKI_ALREADY_INITIALIZED; + } + + if( xResult == CKR_OK ) + { + memset( &xP11Context, 0, sizeof( xP11Context ) ); + xMutex = xSemaphoreCreateMutex(); + if( xMutex != NULL ) + { + xP11Context.xObjectList.xMutex = xMutex; + } + else + { + xResult = CKR_FUNCTION_FAILED; + } + } + + if( xResult == CKR_OK ) + { + CRYPTO_Init(); + + /* PSA Crypto library should haven been initialised successfully in secure world. */ + xP11Context.xIsInitialized = CK_TRUE; + } + return xResult; +} + +/** + * @brief Initialize the PKCS #11 module for use. + * + * @note C_Initialize is not thread-safe. + * + * C_Initialize should be called (and allowed to return) before + * any additional PKCS #11 operations are invoked. + * + * In this implementation, all arguments are ignored. + * Thread protection for the rest of PKCS #11 functions + * default to FreeRTOS primitives. + * + * @param[in] pvInitArgs This parameter is ignored. + * + * @return CKR_OK if successful. + * CKR_CRYPTOKI_ALREADY_INITIALIZED if C_Initialize was previously called. + * All other errors indicate that the PKCS #11 module is not ready to be used. + * See PKCS #11 specification + * for more information. + */ +#if !defined( pkcs11configC_INITIALIZE_ALT ) + CK_DEFINE_FUNCTION( CK_RV, C_Initialize )( CK_VOID_PTR pvInitArgs ) + { /*lint !e9072 It's OK to have different parameter name. */ + ( void ) ( pvInitArgs ); + + return prvMbedTLS_Initialize(); + } +#endif /* if !defined( pkcs11configC_INITIALIZE_ALT ) */ + +/** + * @brief Un-initialize the Cryptoki module. + */ +CK_DEFINE_FUNCTION( CK_RV, C_Finalize )( CK_VOID_PTR pvReserved ) +{ + /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = CKR_OK; + + if( NULL != pvReserved ) + { + xResult = CKR_ARGUMENTS_BAD; + } + else + { + if( xP11Context.xIsInitialized == CK_FALSE ) + { + xResult = CKR_CRYPTOKI_NOT_INITIALIZED; + } + else + { + vSemaphoreDelete( xP11Context.xObjectList.xMutex ); + memset( &xP11Context, 0, sizeof( xP11Context ) ); + + /* Close device private key which is a persistent key. Note that here we only close it other than + * destroying it so that the key can be activated by calling psa_open_key then next time it is used. + */ +#ifndef pkcs11configTFM_VERSION_1_0 + xResult = PKCS11PSARemoveObject( (uint8_t *)pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + sizeof( pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ), + FALSE ); + + if( xResult == CKR_OK ) + { + /* Close device public key which is a persistent key. Note that here we only close it other than + * destroying it so that the key can be activated by calling psa_open_key then next time it is used. + */ + xResult = PKCS11PSARemoveObject( (uint8_t *)pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS, + sizeof( pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ), + FALSE ); + } +#endif + } + } + return xResult; +} + +/** + * @brief Query the list of interface function pointers. + */ +CK_DEFINE_FUNCTION( CK_RV, C_GetFunctionList )( CK_FUNCTION_LIST_PTR_PTR ppxFunctionList ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = CKR_OK; + + if( NULL == ppxFunctionList ) + { + xResult = CKR_ARGUMENTS_BAD; + } + else + { + *ppxFunctionList = &prvP11FunctionList; + } + + return xResult; +} + +/** + * @brief Query the list of slots. A single default slot is implemented. + */ +CK_DEFINE_FUNCTION( CK_RV, C_GetSlotList )( CK_BBOOL xTokenPresent, + CK_SLOT_ID_PTR pxSlotList, + CK_ULONG_PTR pulCount ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = CKR_OK; + + /* Since the PSA implementation of PKCS#11 does not depend + * on a physical token, this parameter is ignored. */ + ( void ) ( xTokenPresent ); + + if( PKCS11_MODULE_IS_INITIALIZED != CK_TRUE ) + { + xResult = CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if( NULL == pulCount ) + { + xResult = CKR_ARGUMENTS_BAD; + } + else if( NULL == pxSlotList ) + { + *pulCount = 1; + } + else + { + if( 0u == *pulCount ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + else + { + pxSlotList[ 0 ] = pkcs11SLOT_ID; + *pulCount = 1; + } + } + + return xResult; +} + +/** + * @brief This function is not implemented for this port. + * + * C_GetTokenInfo() is only implemented for compatibility with other ports. + * All inputs to this function are ignored, and calling this + * function on this port does provide any information about + * the PKCS #11 token. + * + * @return CKR_OK. + */ +CK_DECLARE_FUNCTION( CK_RV, C_GetTokenInfo )( CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo ) +{ + /* Avoid compiler warnings about unused variables. */ + ( void ) slotID; + ( void ) pInfo; + + return CKR_OK; +} + +/** + * @brief This function obtains information about a particular + * mechanism possibly supported by a token. + * + * \param[in] xSlotID This parameter is unused in this port. + * \param[in] type The cryptographic capability for which support + * information is being queried. + * \param[out] pInfo Algorithm sizes and flags for the requested + * mechanism, if supported. + * + * @return CKR_OK if the mechanism is supported. Otherwise, CKR_MECHANISM_INVALID. + */ +CK_DECLARE_FUNCTION( CK_RV, C_GetMechanismInfo )( CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo ) +{ + CK_RV xResult = CKR_MECHANISM_INVALID; + struct CryptoMechanisms + { + CK_MECHANISM_TYPE xType; + CK_MECHANISM_INFO xInfo; + } + pxSupportedMechanisms[] = + { + { CKM_RSA_PKCS, { 2048, 2048, CKF_SIGN } }, + { CKM_RSA_X_509, { 2048, 2048, CKF_VERIFY } }, + #if ( pkcs11configSUPPRESS_ECDSA_MECHANISM != 1 ) + { CKM_ECDSA, { 256, 256, CKF_SIGN | CKF_VERIFY } }, + { CKM_EC_KEY_PAIR_GEN, { 256, 256, CKF_GENERATE_KEY_PAIR } }, + #endif + { CKM_SHA256, { 0, 0, CKF_DIGEST } } + }; + uint32_t ulMech = 0; + + /* Look for the requested mechanism in the above table. */ + for( ; ulMech < sizeof( pxSupportedMechanisms ) / sizeof( pxSupportedMechanisms[ 0 ] ); ulMech++ ) + { + if( pxSupportedMechanisms[ ulMech ].xType == type ) + { + /* The mechanism is supported. Copy out the details and break + * out of the loop. */ + memcpy( pInfo, &( pxSupportedMechanisms[ ulMech ].xInfo ), sizeof( CK_MECHANISM_INFO ) ); + xResult = CKR_OK; + break; + } + } + + return xResult; +} + +/** + * @brief This function is not implemented for this port. + * + * C_InitToken() is only implemented for compatibility with other ports. + * All inputs to this function are ignored, and calling this + * function on this port does not add any security. + * + * @return CKR_OK. + */ +CK_DECLARE_FUNCTION( CK_RV, C_InitToken )( CK_SLOT_ID slotID, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, + CK_UTF8CHAR_PTR pLabel ) +{ + /* Avoid compiler warnings about unused variables. */ + ( void ) slotID; + ( void ) pPin; + ( void ) ulPinLen; + ( void ) pLabel; + + return CKR_OK; +} + +/** + * @brief Start a session for a cryptographic command sequence. + */ +CK_DEFINE_FUNCTION( CK_RV, C_OpenSession )( CK_SLOT_ID xSlotID, + CK_FLAGS xFlags, + CK_VOID_PTR pvApplication, + CK_NOTIFY xNotify, + CK_SESSION_HANDLE_PTR pxSession ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = CKR_OK; + P11SessionPtr_t pxSessionObj = NULL; + CK_BBOOL xSessionMemAllocated = CK_FALSE; + CK_BBOOL xSignMutexCreated = CK_FALSE; + CK_BBOOL xVerifyMutexCreated = CK_FALSE; + + ( void ) ( xSlotID ); + ( void ) ( pvApplication ); + ( void ) ( xNotify ); + + /* Check that the PKCS #11 module is initialized. */ + if( PKCS11_MODULE_IS_INITIALIZED != CK_TRUE ) + { + xResult = CKR_CRYPTOKI_NOT_INITIALIZED; + } + + /* Check arguments. */ + if( NULL == pxSession ) + { + xResult = CKR_ARGUMENTS_BAD; + } + + /* For legacy reasons, the CKF_SERIAL_SESSION bit MUST always be set. */ + if( 0 == ( CKF_SERIAL_SESSION & xFlags ) ) + { + xResult = CKR_SESSION_PARALLEL_NOT_SUPPORTED; + } + + /* + * Make space for the context. + */ + if( CKR_OK == xResult ) + { + pxSessionObj = ( P11SessionPtr_t ) pvPortMalloc( sizeof( P11Session_t ) ); /*lint !e9087 Allow casting void* to other types. */ + + if( NULL == pxSessionObj ) + { + xResult = CKR_HOST_MEMORY; + } + else + { + xSessionMemAllocated = CK_TRUE; + } + + /* + * Zero out the session structure. + */ + if( CKR_OK == xResult ) + { + memset( pxSessionObj, 0, sizeof( P11Session_t ) ); + + pxSessionObj->xSignMutex = xSemaphoreCreateMutex(); + + if( NULL == pxSessionObj->xSignMutex ) + { + xResult = CKR_HOST_MEMORY; + } + else + { + xSignMutexCreated = CK_TRUE; + } + + pxSessionObj->xVerifyMutex = xSemaphoreCreateMutex(); + + if( NULL == pxSessionObj->xVerifyMutex ) + { + xResult = CKR_HOST_MEMORY; + } + else + { + xVerifyMutexCreated = CK_TRUE; + } + } + } + + if( CKR_OK == xResult ) + { + /* + * Assign the session. + */ + + pxSessionObj->ulState = + 0u != ( xFlags & CKF_RW_SESSION ) ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION; + pxSessionObj->xOpened = CK_TRUE; + + /* + * Return the session. + */ + + *pxSession = ( CK_SESSION_HANDLE ) pxSessionObj; /*lint !e923 Allow casting pointer to integer type for handle. */ + } + + /* + * Initialize the operation in progress. + */ + if( CKR_OK == xResult ) + { + pxSessionObj->xOperationInProgress = pkcs11NO_OPERATION; + } + + if( CKR_OK != xResult ) + { + if( xSessionMemAllocated == CK_TRUE ) + { + if( xSignMutexCreated == CK_TRUE ) + { + vSemaphoreDelete( pxSessionObj->xSignMutex ); + } + + if( xVerifyMutexCreated == CK_TRUE ) + { + vSemaphoreDelete( pxSessionObj->xVerifyMutex ); + } + + vPortFree( pxSessionObj ); + } + } + + return xResult; +} + +/** + * @brief Terminate a session and release resources. + */ +CK_DEFINE_FUNCTION( CK_RV, C_CloseSession )( CK_SESSION_HANDLE xSession ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + + if( xResult == CKR_OK ) + { + /* + * Tear down the session. + */ + pxSession->uxSignKey = 0; + if( NULL != pxSession->xSignMutex ) + { + vSemaphoreDelete( pxSession->xSignMutex ); + } + pxSession->uxVerifyKey = 0; + if( NULL != pxSession->xVerifyMutex ) + { + vSemaphoreDelete( pxSession->xVerifyMutex ); + } + if( pxSession->pxHashOperationHandle != NULL ) + { + vPortFree( pxSession->pxHashOperationHandle ); + } + vPortFree( pxSession ); + } + else + { + xResult = CKR_SESSION_HANDLE_INVALID; + } + + return xResult; +} + +/* Searches a template for the CKA_CLASS attribute. */ +CK_RV prvGetObjectClass( CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_CLASS * pxClass ) +{ + CK_RV xResult = CKR_TEMPLATE_INCOMPLETE; + uint32_t ulIndex = 0; + + /* Search template for class attribute. */ + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + CK_ATTRIBUTE xAttribute = pxTemplate[ ulIndex ]; + + if( xAttribute.type == CKA_CLASS ) + { + memcpy( pxClass, xAttribute.pValue, sizeof( CK_OBJECT_CLASS ) ); + xResult = CKR_OK; + break; + } + } + + return xResult; +} + +/** + * @brief Create a PKCS #11 certificate, public key, or private key object + * by importing it into device storage. + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pxTemplate List of attributes of the object to + * be created. + * @param[in] ulCount Number of attributes in pxTemplate. + * @param[out] pxObject Pointer to the location where the created + * object's handle will be placed. + * + * + *
Object Type Template Attributes + *
CertificateCKA_CLASS + *
CKA_VALUE + *
CKA_TOKEN + *
CKA_LABEL + *
CKA_CERTIFICATE_TYPE + *
CKA_VALUE + *
EC Private KeyCKA_CLASS + *
CKA_KEY_TYPE + *
CKA_TOKEN + *
CKA_LABEL + *
CKA_SIGN + *
CKA_EC_PARAMS + *
CKA_VALUE + *
EC Public KeyCKA_CLASS + *
CKA_KEY_TYPE + *
CKA_TOKEN + *
CKA_VERIFY + *
CKA_LABEL + *
CKA_EC_PARAMS + *
CKA_EC_POINT + *
RSA Private KeyCKA_CLASS + *
CKA_KEY_TYPE + *
CKA_TOKEN + *
CKA_LABEL + *
CKA_SIGN + *
CKA_MODULUS + *
CKA_PUBLIC_EXPONENT + *
CKA_PRIME_1 + *
CKA_PRIME_2 + *
CKA_PRIVATE_EXPONENT + *
CKA_EXPONENT_1 + *
CKA_EXPONENT_2 + *
CKA_COEFFICIENT + *
+ * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DECLARE_FUNCTION( CK_RV, C_CreateObject )( CK_SESSION_HANDLE xSession, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR pxObject ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + CK_OBJECT_CLASS xClass; + + if( ( NULL == pxTemplate ) || + ( NULL == pxObject ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + + if( xResult == CKR_OK ) + { + xResult = prvGetObjectClass( pxTemplate, ulCount, &xClass ); + } + + if( xResult == CKR_OK ) + { + switch( xClass ) + { + case CKO_CERTIFICATE: + xResult = prvCreateCertificate( pxTemplate, ulCount, pxObject ); + break; + + case CKO_PRIVATE_KEY: + xResult = prvCreatePrivateKey( pxTemplate, ulCount, pxObject ); + break; + + case CKO_PUBLIC_KEY: + xResult = prvCreatePublicKey( pxTemplate, ulCount, pxObject ); + break; + + default: + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + } + + return xResult; +} + +/** + * @brief Removes an object from the module object list (xP11Context.xObjectList) + * + * \warn This does not delete the object from NVM. + * + * @param[in] xAppHandle Application handle of the object to be deleted. + * + */ +CK_RV prvDeleteObjectFromList( CK_OBJECT_HANDLE xAppHandle ) +{ + CK_RV xResult = CKR_OK; + BaseType_t xGotSemaphore = pdFALSE; + int lIndex = xAppHandle - 1; + + if( lIndex >= pkcs11configMAX_NUM_OBJECTS ) + { + xResult = CKR_OBJECT_HANDLE_INVALID; + } + + if( xResult == CKR_OK ) + { + xGotSemaphore = xSemaphoreTake( xP11Context.xObjectList.xMutex, portMAX_DELAY ); + } + + if( ( xGotSemaphore == pdTRUE ) && ( xResult == CKR_OK ) ) + { + if( xP11Context.xObjectList.xObjects[ lIndex ].xHandle != CK_INVALID_HANDLE ) + { + memset( &xP11Context.xObjectList.xObjects[ lIndex ], 0, sizeof( P11Object_t ) ); + } + else + { + xResult = CKR_OBJECT_HANDLE_INVALID; + } + + xSemaphoreGive( xP11Context.xObjectList.xMutex ); + } + else + { + xResult = CKR_CANT_LOCK; + } + + return xResult; +} + +/** + * @brief Free resources attached to an object handle. + */ +CK_DEFINE_FUNCTION( CK_RV, C_DestroyObject )( CK_SESSION_HANDLE xSession, + CK_OBJECT_HANDLE xObject ) +{ + psa_status_t uxStatus = 0; + uint8_t * pcLabel = NULL; + size_t xLabelLength = 0; + CK_OBJECT_HANDLE xPalHandle; + + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + + if( xResult == CKR_OK ) + { + prvFindObjectInListByHandle( xObject, &xPalHandle, &pcLabel, &xLabelLength ); + if( xPalHandle != CK_INVALID_HANDLE ) + { + xResult = PKCS11PSARemoveObject( pcLabel, xLabelLength, TRUE ); + if( xResult == CKR_OK ) + { + xResult = prvDeleteObjectFromList( xObject ); + } + } + } + + return xResult; +} + +/** + * @brief Query the value of the specified cryptographic object attribute. + */ +CK_DEFINE_FUNCTION( CK_RV, C_GetAttributeValue )( CK_SESSION_HANDLE xSession, + CK_OBJECT_HANDLE xObject, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount ) +{ + /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + CK_BBOOL xIsPrivate = CK_TRUE; + CK_ULONG iAttrib; + mbedtls_pk_context xKeyContext = { 0 }; + mbedtls_pk_type_t xKeyType = MBEDTLS_PK_NONE; + mbedtls_ecp_keypair * pxKeyPair; + CK_KEY_TYPE xPkcsKeyType = ( CK_KEY_TYPE ) ~0; + CK_OBJECT_CLASS xClass; + uint8_t * pxObjectValue = NULL; + uint8_t ucP256Oid[] = pkcs11DER_ENCODED_OID_P256; + int lMbedTLSResult = 0; + CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE; + size_t xSize; + psa_status_t uxStatus; + mbedtls_ecp_group ecp_group; + mbedtls_ecp_point ecp_point; + unsigned char ucGetData[pkcs11OBJECT_MAX_SIZE]; + uint8_t * pcLabel = NULL; + size_t ulLength = pkcs11OBJECT_MAX_SIZE; + psa_algorithm_t key_algorithm; + + if( xResult == CKR_OK ) + { + if( ( NULL == pxTemplate ) || ( 0 == ulCount ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + if( xResult == CKR_OK ) + { + /* + * Find the object in P11context firstly. + */ + prvFindObjectInListByHandle( xObject, &xPalHandle, &pcLabel, &xSize ); /*pcLabel and xSize are ignored. */ + + if( xPalHandle != CK_INVALID_HANDLE ) + { + xResult = PKCS11PSAGetObjectValue( xPalHandle, ucGetData, &ulLength, &xIsPrivate ); + if( xResult == CKR_OK ) + { + pxObjectValue = ucGetData; + } + } + else + { + xResult = CKR_OBJECT_HANDLE_INVALID; + } + } + + if( xResult == CKR_OK ) + { + for( iAttrib = 0; iAttrib < ulCount && CKR_OK == xResult; iAttrib++ ) + { + switch( pxTemplate[ iAttrib ].type ) + { + case CKA_CLASS: + + if( pxTemplate[ iAttrib ].pValue == NULL ) + { + pxTemplate[ iAttrib ].ulValueLen = sizeof( CK_OBJECT_CLASS ); + } + else + { + if( pxTemplate[ iAttrib ].ulValueLen >= sizeof( CK_OBJECT_CLASS ) ) + { + switch (( P11ObjectHandles_t )xPalHandle ) + { + case eAwsDevicePrivateKey: + xClass = CKO_PRIVATE_KEY; + break; + + case eAwsDevicePublicKey: + case eAwsCodeVerifyingKey: + xClass = CKO_PUBLIC_KEY; + break; + + case eAwsJitpCertificate: + case eAwsRootCertificate: + case eAwsDeviceCertificate: + xClass = CKO_CERTIFICATE; + break; + + default: + xResult = CKR_OBJECT_HANDLE_INVALID; + break; + } + memcpy( pxTemplate[ iAttrib ].pValue, &xClass, sizeof( CK_OBJECT_CLASS ) ); + } + else + { + xResult = CKR_BUFFER_TOO_SMALL; + } + } + + break; + + case CKA_VALUE: + + if( xIsPrivate == CK_TRUE ) + { + pxTemplate[ iAttrib ].ulValueLen = CK_UNAVAILABLE_INFORMATION; + xResult = CKR_ATTRIBUTE_SENSITIVE; + } + else + { + if( pxTemplate[ iAttrib ].pValue == NULL ) + { + pxTemplate[ iAttrib ].ulValueLen = ulLength; + } + else if( pxTemplate[ iAttrib ].ulValueLen < ulLength ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + else + { + memcpy( pxTemplate[ iAttrib ].pValue, pxObjectValue, ulLength ); + } + } + + break; + + case CKA_KEY_TYPE: + + if( pxTemplate[ iAttrib ].pValue == NULL ) + { + pxTemplate[ iAttrib ].ulValueLen = sizeof( CK_KEY_TYPE ); + } + else if( pxTemplate[ iAttrib ].ulValueLen < sizeof( CK_KEY_TYPE ) ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + else + { + psa_key_handle_t ulKeyHandle = 0; + xResult = PKCS11PSAGetKeyHandle( pcLabel, xSize, &ulKeyHandle ); + + /* Get the key policy from which the key type can be derived. */ + if( xResult == CKR_OK ) + { + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + uxStatus = psa_get_key_attributes( ulKeyHandle, &key_attributes ); + if ( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + key_algorithm = psa_get_key_algorithm( &key_attributes ); + psa_reset_key_attributes( &key_attributes ); + } + } + if( xResult == CKR_OK ) + { + if( PSA_ALG_IS_ECDSA( key_algorithm ) ) + { + xPkcsKeyType = CKK_EC; + } + else if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( key_algorithm ) || + PSA_ALG_IS_RSA_PSS( key_algorithm ) ) + { + xPkcsKeyType = CKK_RSA; + } + else + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + } + if( xResult == CKR_OK ) + { + memcpy( pxTemplate[ iAttrib ].pValue, &xPkcsKeyType, sizeof( CK_KEY_TYPE ) ); + } + } + + break; + + case CKA_PRIVATE_EXPONENT: + + xResult = CKR_ATTRIBUTE_SENSITIVE; + + break; + + case CKA_EC_PARAMS: + + pxTemplate[ iAttrib ].ulValueLen = sizeof( ucP256Oid ); + + if( pxTemplate[ iAttrib ].pValue != NULL ) + { + if( pxTemplate[ iAttrib ].ulValueLen < sizeof( ucP256Oid ) ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + else + { + memcpy( pxTemplate[ iAttrib ].pValue, ucP256Oid, sizeof( ucP256Oid ) ); + } + } + + break; + + case CKA_EC_POINT: + + if( pxTemplate[ iAttrib ].pValue == NULL ) + { + pxTemplate[ iAttrib ].ulValueLen = 67; + } + else + { + if( pxTemplate[ iAttrib ].ulValueLen < sizeof( ecp_point ) ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + else + { + pxTemplate[ iAttrib ].ulValueLen = ulLength + 2; + *(( CK_BYTE *)(pxTemplate[ iAttrib ].pValue)) = 0x04; + *(( CK_BYTE *)(pxTemplate[ iAttrib ].pValue) + 1) = ulLength; + memcpy( ( CK_BYTE *)(pxTemplate[ iAttrib ].pValue) + 2, pxObjectValue, ulLength ); + } + } + + break; + + default: + xResult = CKR_ATTRIBUTE_TYPE_INVALID; + } + } + + /* Free the buffer where object was stored. */ + PKCS11PSAGetObjectValueCleanup( pxObjectValue, ulLength ); + + /* Free the mbedTLS structure used to parse the key. */ + mbedtls_pk_free( &xKeyContext ); + } + + return xResult; +} + +/** + * @brief Initializes a search for an object by its label. + * + * \sa C_FindObjects() and C_FindObjectsFinal() which must be called + * after C_FindObjectsInit(). + * + * \note FindObjects parameters are shared by a session. Calling + * C_FindObjectsInit(), C_FindObjects(), and C_FindObjectsFinal() with the + * same session across different tasks may lead to unexpected results. + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pxTemplate Pointer to a template which specifies + * the object attributes to match. + * In this port, the only searchable attribute + * is object label. All other attributes will + * be ignored. + * @param[in] ulCount The number of attributes in pxTemplate. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DECLARE_FUNCTION( CK_RV, C_FindObjectsInit )( CK_SESSION_HANDLE xSession, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulCount ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + CK_BYTE * pxFindObjectLabel = NULL; + uint32_t ulIndex; + CK_ATTRIBUTE xAttribute; + + if( NULL == pxTemplate ) + { + xResult = CKR_ARGUMENTS_BAD; + } + + if( ( ulCount != 1 ) && ( ulCount != 2 ) ) + { + xResult = CKR_ARGUMENTS_BAD; + PKCS11_PRINT( ( "ERROR: Find objects does not support searching by %d attributes. \r\n", ulCount ) ); + } + + if( xResult == CKR_OK ) + { + if( pxSession->pxFindObjectLabel != NULL ) + { + xResult = CKR_OPERATION_ACTIVE; + PKCS11_PRINT( ( "ERROR: Find object operation already in progress. \r\n" ) ); + } + } + + /* Malloc space to save template information. */ + if( xResult == CKR_OK ) + { + pxFindObjectLabel = pvPortMalloc( pxTemplate->ulValueLen + 1 ); /* Add 1 to guarantee null termination for PAL. */ + + if( pxFindObjectLabel != NULL ) + { + pxSession->pxFindObjectLabel = pxFindObjectLabel; + memset( pxFindObjectLabel, 0, pxTemplate->ulValueLen + 1 ); + } + else + { + xResult = CKR_HOST_MEMORY; + } + } + + /* Search template for label. + * NOTE: This port only supports looking up objects by CKA_LABEL and all + * other search attributes are ignored. */ + if( xResult == CKR_OK ) + { + xResult = CKR_TEMPLATE_INCOMPLETE; + + for( ulIndex = 0; ulIndex < ulCount; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + if( xAttribute.type == CKA_LABEL ) + { + memcpy( pxSession->pxFindObjectLabel, xAttribute.pValue, xAttribute.ulValueLen ); + xResult = CKR_OK; + } + else + { + PKCS11_WARNING_PRINT( ( "WARNING: Search parameters other than label are ignored.\r\n" ) ); + } + } + } + + /* Clean up memory if there was an error parsing the template. */ + if( xResult != CKR_OK ) + { + if( pxFindObjectLabel != NULL ) + { + vPortFree( pxFindObjectLabel ); + pxSession->pxFindObjectLabel = NULL; + } + } + + return xResult; +} + +/** + * @brief Helper function - Find a key object. + * + * @param[in] pxSession Points to PKCS #11 session. + * + * @param[in] xKeyId PSA persistent key ID. + * + * @param[in] xPalHandle PSA pkcs#11 key handle. + * + * @param[out] pxObject Points to the handle of the object to + * be found. + * @param[out] pulObjectCount The actual number of objects that are + * found. In this port, if an object is found + * this value will be 1, otherwise if the + * object is not found, it will be set to 0. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +static CK_RV FindKeyObjects ( P11SessionPtr_t pxSession, + psa_key_id_t xKeyId, + CK_OBJECT_HANDLE xPalHandle, + CK_OBJECT_HANDLE_PTR pxObject, + CK_ULONG_PTR pulObjectCount ) +{ + CK_RV xResult; + psa_key_handle_t uxPsaDeviceKeyHandle = 0; + CK_OBJECT_HANDLE uxObjectHandle = 0; + psa_status_t uxStatus = PSA_SUCCESS; + + /* Check with PKCS#11 context if the object was previously stored */ + xResult = PKCS11PSAGetKeyHandle( pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ), + &uxPsaDeviceKeyHandle ); + if ( xResult != CKR_OK ) + { + xResult = CKR_OK; + + /* Check with PSA if the object is stored as persistent key. */ + uxStatus = psa_open_key( xKeyId, &uxPsaDeviceKeyHandle ); + + if ( uxStatus == PSA_SUCCESS ) + { + /* Import the key into the PKCS#11 context. */ + PKCS11PSAContextImportObject( pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ), + uxPsaDeviceKeyHandle ); + } +#ifndef pkcs11configTFM_VERSION_1_0 + else if ( uxStatus != PSA_ERROR_DOES_NOT_EXIST ) +#else + else if ( uxStatus != PSA_ERROR_DOES_NOT_EXIST && uxStatus != PSA_ERROR_NOT_SUPPORTED ) +#endif + + { + PKCS11_WARNING_PRINT( ( "WARNING: Opening key (0x%x) fails (0x%x). \n", xKeyId, uxStatus ) ); + xResult = CKR_FUNCTION_FAILED; + } + } + + if ( xResult == CKR_OK && uxStatus == PSA_SUCCESS ) + { + /* Add key handle to application object list. */ + xResult = prvAddObjectToList( xPalHandle, + &uxObjectHandle, + pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ) ); + if ( xResult == CKR_OK ) + { + *pxObject = uxObjectHandle; + *pulObjectCount = 1; + } + } + return xResult; +} + + +/** + * @brief Find an object. + * + * \sa C_FindObjectsInit() which must be called before calling C_FindObjects() + * and C_FindObjectsFinal(), which must be called after. + * + * \note FindObjects parameters are shared by a session. Calling + * C_FindObjectsInit(), C_FindObjects(), and C_FindObjectsFinal() with the + * same session across different tasks may lead to unexpected results. + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[out] pxObject Points to the handle of the object to + * be found. + * @param[in] ulMaxObjectCount The size of the pxObject object handle + * array. In this port, this value should + * always be set to 1, as searching for + * multiple objects is not supported. + * @param[out] pulObjectCount The actual number of objects that are + * found. In this port, if an object is found + * this value will be 1, otherwise if the + * object is not found, it will be set to 0. + * + * \note In the event that an object does not exist, CKR_OK will be returned, but + * pulObjectCount will be set to 0. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DECLARE_FUNCTION( CK_RV, C_FindObjects )( CK_SESSION_HANDLE xSession, + CK_OBJECT_HANDLE_PTR pxObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + + BaseType_t xDone = pdFALSE; + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + + CK_BYTE_PTR pcObjectValue = NULL; + uint32_t xObjectLength = 0; + CK_BYTE xByte = 0; + CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE; + uint32_t ulIndex; + CK_OBJECT_HANDLE uxObjectHandle = 0; + psa_status_t uxStatus; + + /* + * Check parameters. + */ + if( ( NULL == pxObject ) || + ( NULL == pulObjectCount ) ) + { + xResult = CKR_ARGUMENTS_BAD; + xDone = pdTRUE; + } + + if( xResult == CKR_OK ) + { + if( pxSession->pxFindObjectLabel == NULL ) + { + xResult = CKR_OPERATION_NOT_INITIALIZED; + xDone = pdTRUE; + } + + if( 0u == ulMaxObjectCount ) + { + xResult = CKR_ARGUMENTS_BAD; + xDone = pdTRUE; + } + + if( 1u != ulMaxObjectCount ) + { + PKCS11_WARNING_PRINT( ( "WARN: Searching for more than 1 object not supported. \r\n" ) ); + } + } + + if( ( pdFALSE == xDone ) ) + { + /* Try to find the object in module's list first. If not found, then try to find it from secure world. */ + prvFindObjectInListByLabel( pxSession->pxFindObjectLabel, strlen( ( const char * ) pxSession->pxFindObjectLabel ), &xPalHandle, pxObject ); + + if( *pxObject != CK_INVALID_HANDLE ) + { + *pulObjectCount = 1; + } + else + { + if( strcmp( ( const char * )pxSession->pxFindObjectLabel, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) == 0 ) + { + xResult = FindKeyObjects( pxSession, + PSA_DEVICE_PRIVATE_KEY_ID, + eAwsDevicePrivateKey, + pxObject, + pulObjectCount ); + } + else if( strcmp( ( const char * )pxSession->pxFindObjectLabel, + pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) == 0 ) + { + xResult = FindKeyObjects( pxSession, + PSA_DEVICE_PUBLIC_KEY_ID, + eAwsDevicePublicKey, + pxObject, + pulObjectCount ); + } + else if( strcmp( ( const char * )pxSession->pxFindObjectLabel, + pkcs11configLABEL_CODE_VERIFICATION_KEY ) == 0 ) + { + xResult = FindKeyObjects( pxSession, + PSA_CODE_VERIFICATION_KEY_ID, + eAwsCodeVerifyingKey, + pxObject, + pulObjectCount ); + } + else if( strcmp( ( const char * )pxSession->pxFindObjectLabel, + pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS ) == 0 ) + { + /* Get the metadata for the device certificated uid. + * If succeed, then the certificate exists. + */ + struct psa_storage_info_t info = {0}; + + /* Get info for write once UID */ + uxStatus = psa_ps_get_info( PSA_DEVICE_CERTIFICATE_UID, &info ); + if( uxStatus == PSA_SUCCESS ) + { + /* Add the opened key to xP11Context. */ + xResult = prvAddObjectToList( eAwsDeviceCertificate, + &uxObjectHandle, + pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ) ); + + if( xResult == CKR_OK ) + { + /* Import the key into the pkcs#11 PSA context. */ + PKCS11PSAContextImportObject( pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ), + pkcs11OBJECT_HANDLE_NA ); + + /* The device certificate is found. */ + *pxObject = uxObjectHandle; + *pulObjectCount = 1; + } + } + else if( uxStatus != PSA_ERROR_DOES_NOT_EXIST ) + { + PKCS11_WARNING_PRINT( ( "psa ps getting device certificate fails. \r\n" ) ); + xResult = CKR_FUNCTION_FAILED; + } + } + else if( strcmp( ( const char * )pxSession->pxFindObjectLabel, + pkcs11configLABEL_ROOT_CERTIFICATE ) == 0 ) + { + /* Get the metadata for the root certificate uid. + * If succeed, then the certificate exists. + */ + struct psa_storage_info_t info = {0}; + + /* Get info for write once UID */ + uxStatus = psa_ps_get_info( PSA_ROOT_CERTIFICATE_UID, &info ); + if( uxStatus == PSA_SUCCESS ) + { + /* Add the certificate to xP11Context. */ + xResult = prvAddObjectToList( eAwsRootCertificate, + &uxObjectHandle, + pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ) ); + + if( xResult == CKR_OK ) + { + /* Import the certificate into the pkcs#11 PSA context. */ + PKCS11PSAContextImportObject( pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ), + pkcs11OBJECT_HANDLE_NA ); + + /* The root certificate is found. */ + *pxObject = uxObjectHandle; + *pulObjectCount = 1; + } + } + else if( uxStatus != PSA_ERROR_DOES_NOT_EXIST ) + { + PKCS11_WARNING_PRINT( ( "psa ps getting root certificate fails. \r\n" ) ); + xResult = CKR_FUNCTION_FAILED; + } + } + else if( strcmp( ( const char * )pxSession->pxFindObjectLabel, + pkcs11configLABEL_JITP_CERTIFICATE ) == 0 ) + { + /* Get the metadata for the jitp certificate uid. + * If succeed, then the certificate exists. + */ + struct psa_storage_info_t info = {0}; + + /* Get info for write once UID */ + uxStatus = psa_ps_get_info( PSA_JITP_CERTIFICATE_UID, &info ); + if( uxStatus == PSA_SUCCESS ) + { + /* Add the certificate to xP11Context. */ + xResult = prvAddObjectToList( eAwsJitpCertificate, + &uxObjectHandle, + pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ) ); + + if( xResult == CKR_OK ) + { + /* Import the certificate into the pkcs#11 PSA context. */ + PKCS11PSAContextImportObject( pxSession->pxFindObjectLabel, + strlen( ( const char * ) pxSession->pxFindObjectLabel ), + pkcs11OBJECT_HANDLE_NA ); + + /* The jitp certificate is found. */ + *pxObject = uxObjectHandle; + *pulObjectCount = 1; + } + } + else if( uxStatus != PSA_ERROR_DOES_NOT_EXIST ) + { + PKCS11_WARNING_PRINT( ( "psa ps getting JITP certificate fails. \r\n" ) ); + xResult = CKR_FUNCTION_FAILED; + } + } + else + { + PKCS11_WARNING_PRINT( ( "WARNING: Object not supported (%s). \r\n", pxSession->pxFindObjectLabel ) ); + } + } + + if ( *pulObjectCount == 0 ) + { + PKCS11_WARNING_PRINT( ( "WARN: Object with label '%s' not found. \r\n", ( char * ) pxSession->pxFindObjectLabel ) ); + } + } + return xResult; +} + +/** + * @brief Completes an object search operation. + * + * \sa C_FindObjectsInit(), C_FindObjects() which must be called before + * calling C_FindObjectsFinal(). + * + * \note FindObjects parameters are shared by a session. Calling + * C_FindObjectsInit(), C_FindObjects(), and C_FindObjectsFinal() with the + * same session across different tasks may lead to unexpected results. + * + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DECLARE_FUNCTION( CK_RV, C_FindObjectsFinal )( CK_SESSION_HANDLE xSession ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + + /* + * Check parameters. + */ + if( xResult == CKR_OK ) + { + if( pxSession->pxFindObjectLabel == NULL ) + { + xResult = CKR_OPERATION_NOT_INITIALIZED; + } + } + + if( xResult == CKR_OK ) + { + /* + * Clean-up find objects state. + */ + vPortFree( pxSession->pxFindObjectLabel ); + pxSession->pxFindObjectLabel = NULL; + } + + return xResult; +} + +CK_DEFINE_FUNCTION( CK_RV, C_DigestInit )( CK_SESSION_HANDLE xSession, + CK_MECHANISM_PTR pMechanism ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + psa_hash_operation_t* pxHandle = NULL; + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + psa_status_t uxStatus; + + if( xResult == CKR_OK ) + { + if( pMechanism == NULL ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + + if(( xResult == CKR_OK ) && ( pMechanism->mechanism != CKM_SHA256 )) + { + xResult = CKR_MECHANISM_INVALID; + } + + if( xResult == CKR_OK ) + { + pxHandle = ( psa_hash_operation_t * )pvPortMalloc( sizeof( psa_hash_operation_t ) ); + if( pxHandle == NULL ) + { + xResult = CKR_HOST_MEMORY; + } + } + + /* + * Initialize the requested hash type + */ + if ( xResult == CKR_OK ) + { + *pxHandle = psa_hash_operation_init(); + + /* + * Setup the hash object for the desired hash. + * Currently only the SHA_256 algorithm is supported. + */ + uxStatus = psa_hash_setup( pxHandle, PSA_ALG_SHA_256 ); + if ( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + pxSession->xOperationInProgress = pMechanism->mechanism; + pxSession->pxHashOperationHandle = pxHandle; + } + } + + return xResult; +} + +CK_DEFINE_FUNCTION( CK_RV, C_DigestUpdate )( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + psa_status_t uxStatus; + + if( xResult == CKR_OK ) + { + if( pPart == NULL ) + { + PKCS11_PRINT( ( "ERROR: Null digest data provided. \r\n" ) ); + xResult = CKR_ARGUMENTS_BAD; + } + } + + if( xResult == CKR_OK ) + { + if( ( pxSession->xOperationInProgress != CKM_SHA256 ) || + ( pxSession->pxHashOperationHandle == NULL ) ) + { + xResult = CKR_OPERATION_NOT_INITIALIZED; + } + } + + if( xResult == CKR_OK ) + { + uxStatus = psa_hash_update( pxSession->pxHashOperationHandle, pPart, ulPartLen ); + if( uxStatus != PSA_SUCCESS ) + { + uxStatus = psa_hash_abort( pxSession->pxHashOperationHandle ); + if( uxStatus != PSA_SUCCESS ) + { + PKCS11_PRINT( ( "ERROR: psa_hash_abort error. \r\n" ) ); + } + vPortFree( pxSession->pxHashOperationHandle ); + pxSession->pxHashOperationHandle = NULL; + pxSession->xOperationInProgress = pkcs11NO_OPERATION; + xResult = CKR_FUNCTION_FAILED; + } + } + + return xResult; +} + +CK_DEFINE_FUNCTION( CK_RV, C_DigestFinal )( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen ) +{ + psa_status_t uxStatus; + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + + if( xResult == CKR_OK ) + { + if( pulDigestLen == NULL ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + + if( xResult == CKR_OK ) + { + if( pxSession->xOperationInProgress != CKM_SHA256 ) + { + xResult = CKR_OPERATION_NOT_INITIALIZED; + pxSession->xOperationInProgress = pkcs11NO_OPERATION; + } + } + + if( xResult == CKR_OK ) + { + if( pDigest == NULL ) + { + /* Supply the required buffer size. */ + *pulDigestLen = pkcs11SHA256_DIGEST_LENGTH; + } + else + { + if( *pulDigestLen < pkcs11SHA256_DIGEST_LENGTH ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + else + { + uxStatus = psa_hash_finish( pxSession->pxHashOperationHandle, pDigest, *pulDigestLen, ( size_t * )pulDigestLen ); + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + pxSession->xOperationInProgress = pkcs11NO_OPERATION; + vPortFree( pxSession->pxHashOperationHandle ); + pxSession->pxHashOperationHandle = NULL; + } + } + } + + return xResult; +} + +/** + * @brief Begin creating a digital signature. + * + * \sa C_Sign() completes signatures initiated by C_SignInit(). + * + * \note C_Sign() parameters are shared by a session. Calling + * C_SignInit() & C_Sign() with the same session across different + * tasks may lead to unexpected results. + * + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pxMechanism Mechanism used to sign. + * This port supports the following mechanisms: + * - CKM_RSA_PKCS for RSA signatures + * - CKM_ECDSA for elliptic curve signatures + * Note that neither of these mechanisms perform + * hash operations. + * @param[in] xKey The handle of the private key to be used for + * signature. Key must be compatible with the + * mechanism chosen by pxMechanism. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DEFINE_FUNCTION( CK_RV, C_SignInit )( CK_SESSION_HANDLE xSession, + CK_MECHANISM_PTR pxMechanism, + CK_OBJECT_HANDLE xKey ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + CK_OBJECT_HANDLE xPalHandle; + uint8_t * pcLabel = NULL; + size_t xLabelLength = 0; + psa_status_t uxStatus; + psa_key_handle_t uxKeyHandle; + + /*lint !e9072 It's OK to have different parameter name. */ + P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession ); + + if( xResult == CKR_OK ) + { + if( NULL == pxMechanism ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + + /* Retrieve key value from storage. */ + if( xResult == CKR_OK ) + { + prvFindObjectInListByHandle( xKey, + &xPalHandle, + &pcLabel, + &xLabelLength ); + } + + if( xResult == CKR_OK ) + { + if( xPalHandle == CK_INVALID_HANDLE ) + { + xResult = CKR_KEY_HANDLE_INVALID; + } + } + + if( xResult == CKR_OK ) + { + if( pdTRUE == xSemaphoreTake( pxSession->xSignMutex, portMAX_DELAY ) ) + { + + /* + * Only the device private key and code sign key can be used + * to make a signature. + */ + if ( xPalHandle == eAwsDevicePrivateKey ) + { + xResult = PKCS11PSAGetKeyHandle( pcLabel, xLabelLength, &uxKeyHandle ); + if ( xResult == CKR_OK ) + { + pxSession->uxSignKey = uxKeyHandle; + + /* Get the key's algorithm. */ + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t key_algorithm = 0; + uxStatus = psa_get_key_attributes( uxKeyHandle, &key_attributes ); + if ( uxStatus == PSA_SUCCESS ) + { + key_algorithm = psa_get_key_algorithm( &key_attributes ); + pxSession->xSignAlgorithm = key_algorithm; + psa_reset_key_attributes( &key_attributes ); + } + else + { + xResult = CKR_FUNCTION_FAILED; + } + } + else + { + xResult = CKR_FUNCTION_FAILED; + } + } + else + { + pxSession->uxSignKey = 0; + xResult = CKR_KEY_HANDLE_INVALID; + } + xSemaphoreGive( pxSession->xSignMutex ); + } + else + { + xResult = CKR_CANT_LOCK; + } + } + + /* Check that the mechanism and key type are compatible, supported. */ + if( xResult == CKR_OK ) + { + if( pxMechanism->mechanism == CKM_RSA_PKCS ) + { + if( ( !( PSA_ALG_IS_RSA_PKCS1V15_SIGN( pxSession->xSignAlgorithm ) ) ) && + ( !( PSA_ALG_IS_RSA_PSS( pxSession->xSignAlgorithm ) ) ) ) + { + PKCS11_PRINT( ( "ERROR: Signing key type (%d) does not match RSA mechanism \r\n", pxSession->xSignAlgorithm ) ); + xResult = CKR_KEY_TYPE_INCONSISTENT; + } + } + else if( pxMechanism->mechanism == CKM_ECDSA ) + { + if( !PSA_ALG_IS_ECDSA( pxSession->xSignAlgorithm ) ) + { + PKCS11_PRINT( ( "ERROR: Signing key type (%d) does not match ECDSA mechanism \r\n", pxSession->xSignAlgorithm ) ); + xResult = CKR_KEY_TYPE_INCONSISTENT; + } + } + else + { + PKCS11_PRINT( ( "ERROR: Unsupported mechanism type %d \r\n", pxMechanism->mechanism ) ); + xResult = CKR_MECHANISM_INVALID; + } + } + + if( xResult == CKR_OK ) + { + pxSession->xSignMechanism = pxMechanism->mechanism; + } + + return xResult; +} + +/** + * @brief Performs a digital signature operation. + * + * \sa C_SignInit() initiates signatures signature creation. + * + * \note C_Sign() parameters are shared by a session. Calling + * C_SignInit() & C_Sign() with the same session across different + * tasks may lead to unexpected results. + * + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pucData Data to be signed. + * Note: Some applications may require this data to + * be hashed before passing to C_Sign(). + * @param[in] ulDataLen Length of pucData, in bytes. + * @param[out] pucSignature Buffer where signature will be placed. + * Caller is responsible for allocating memory. + * Providing NULL for this input will cause + * pulSignatureLen to be updated for length of + * buffer required. + * @param[in,out] pulSignatureLen Length of pucSignature buffer. + * If pucSignature is non-NULL, pulSignatureLen is + * updated to contain the actual signature length. + * If pucSignature is NULL, pulSignatureLen is + * updated to the buffer length required for signature + * data. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DEFINE_FUNCTION( CK_RV, C_Sign )( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR pucData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pucSignature, + CK_ULONG_PTR pulSignatureLen ) +{ /*lint !e9072 It's OK to have different parameter name. */ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSessionObj = prvSessionPointerFromHandle( xSession ); + CK_ULONG xSignatureLength = 0; + CK_ULONG xExpectedInputLength = 0; + int lMbedTLSResult; + psa_status_t uxStatus; + CK_BYTE_PTR pucDataToBeSigned = pucData; + CK_LONG ulDataLengthToBeSigned = ulDataLen; + + if( CKR_OK == xResult ) + { + if( ( NULL == pulSignatureLen ) || ( NULL == pucData ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + + if( CKR_OK == xResult ) + { + /* Update the signature length. */ + + if( pxSessionObj->xSignMechanism == CKM_RSA_PKCS ) + { + xSignatureLength = pkcs11RSA_2048_SIGNATURE_LENGTH; + xExpectedInputLength = pkcs11RSA_SIGNATURE_INPUT_LENGTH; + + /* Remove the padding of SHA256 Algorithm Identifier Sequence. */ + pucDataToBeSigned = pucData + pkcs11DER_ENCODED_OID_P256_LEGNTH; + ulDataLengthToBeSigned = ulDataLengthToBeSigned - pkcs11DER_ENCODED_OID_P256_LEGNTH; + + } + else if( pxSessionObj->xSignMechanism == CKM_ECDSA ) + { + xSignatureLength = pkcs11ECDSA_P256_SIGNATURE_LENGTH; + xExpectedInputLength = pkcs11SHA256_DIGEST_LENGTH; + } + else + { + xResult = CKR_OPERATION_NOT_INITIALIZED; + } + } + + if( xResult == CKR_OK ) + { + /* Calling application is trying to determine length needed for signature buffer. */ + if( NULL != pucSignature ) + { + /* Check that the signature buffer is long enough. */ + if( *pulSignatureLen < xSignatureLength ) + { + xResult = CKR_BUFFER_TOO_SMALL; + } + + /* Check that input data to be signed is the expected length. */ + if( CKR_OK == xResult ) + { + if( xExpectedInputLength != ulDataLen ) + { + xResult = CKR_DATA_LEN_RANGE; + } + } + + /* Sign the data.*/ + if( CKR_OK == xResult ) + { + if( pdTRUE == xSemaphoreTake( pxSessionObj->xSignMutex, portMAX_DELAY ) ) + { + if ( pxSessionObj->uxSignKey == 0 ) + { + xResult = CKR_KEY_HANDLE_INVALID; + } + else + { + uxStatus = psa_sign_hash( pxSessionObj->uxSignKey, + pxSessionObj->xSignAlgorithm, + ( const uint8_t * )pucDataToBeSigned, + ( size_t )ulDataLengthToBeSigned, + ( uint8_t * )pucSignature, + ( size_t )*pulSignatureLen, + ( size_t * )pulSignatureLen ); + + if( uxStatus != PSA_SUCCESS ) + { + PKCS11_PRINT( ( "mbedTLS sign failed with error %d \r\n", lMbedTLSResult ) ); + xResult = CKR_FUNCTION_FAILED; + } + } + + xSemaphoreGive( pxSessionObj->xSignMutex ); + } + else + { + xResult = CKR_CANT_LOCK; + } + } + } + } + + /* Complete the operation in the context. */ + if( xResult != CKR_BUFFER_TOO_SMALL ) + { + pxSessionObj->xSignMechanism = pkcs11NO_OPERATION; + } + + return xResult; +} + +/** + * @brief Begin a digital signature verification. + * + * \sa C_Verify() completes verifications initiated by C_VerifyInit(). + * + * \note C_Verify() parameters are shared by a session. Calling + * C_VerifyInit() & C_Verify() with the same session across different + * tasks may lead to unexpected results. + * + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pxMechanism Mechanism used to verify signature. + * This port supports the following mechanisms: + * - CKM_RSA_X_509 for RSA verifications + * - CKM_ECDSA for elliptic curve verifications + * @param[in] xKey The handle of the public key to be used for + * verification. Key must be compatible with the + * mechanism chosen by pxMechanism. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DEFINE_FUNCTION( CK_RV, C_VerifyInit )( CK_SESSION_HANDLE xSession, + CK_MECHANISM_PTR pxMechanism, + CK_OBJECT_HANDLE xKey ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSession; + CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE; + uint8_t * pcLabel = NULL; + size_t xLabelLength = 0; + psa_status_t uxStatus; + psa_key_handle_t uxKeyHandle; + + pxSession = prvSessionPointerFromHandle( xSession ); + + if( xResult == CKR_OK ) + { + if( NULL == pxMechanism ) + { + PKCS11_PRINT( ( "ERROR: Null verification mechanism provided. \r\n" ) ); + xResult = CKR_ARGUMENTS_BAD; + } + } + + /* Retrieve key value from storage. */ + if( xResult == CKR_OK ) + { + prvFindObjectInListByHandle( xKey, + &xPalHandle, + &pcLabel, + &xLabelLength ); + + if( xPalHandle == CK_INVALID_HANDLE ) + { + pxSession->uxSignKey = 0; + xResult = CKR_KEY_HANDLE_INVALID; + } + } + + if( xResult == CKR_OK ) + { + if( pdTRUE == xSemaphoreTake( pxSession->xVerifyMutex, portMAX_DELAY ) ) + { + xResult = PKCS11PSAGetKeyHandle( pcLabel, xLabelLength, &uxKeyHandle ); + if( xResult == CKR_OK ) + { + pxSession->uxVerifyKey = uxKeyHandle; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t key_algorithm = 0; + uxStatus = psa_get_key_attributes( uxKeyHandle, &key_attributes ); + if ( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + key_algorithm = psa_get_key_algorithm( &key_attributes ); + pxSession->xVerifyAlgorithm = key_algorithm; + psa_reset_key_attributes( &key_attributes ); + } + } + else + { + pxSession->uxVerifyKey = 0; + xResult = CKR_KEY_HANDLE_INVALID; + } + + xSemaphoreGive( pxSession->xVerifyMutex ); + } + else + { + xResult = CKR_CANT_LOCK; + } + } + + /* Check that the mechanism and key type are compatible, supported. */ + if( xResult == CKR_OK ) + { + if( pxMechanism->mechanism == CKM_RSA_X_509 ) + { + if( ( !( PSA_ALG_IS_RSA_PKCS1V15_SIGN( pxSession->xSignAlgorithm ) ) ) && + ( !( PSA_ALG_IS_RSA_PSS( pxSession->xSignAlgorithm ) ) ) ) + { + PKCS11_PRINT( ( "ERROR: Verification key type (%d) does not match RSA mechanism \r\n", pxSession->xSignAlgorithm ) ); + xResult = CKR_KEY_TYPE_INCONSISTENT; + } + } + else if( pxMechanism->mechanism == CKM_ECDSA ) + { + if( !PSA_ALG_IS_ECDSA( pxSession->xSignAlgorithm ) ) + { + PKCS11_PRINT( ( "ERROR: Verification key type (%d) does not match ECDSA mechanism \r\n", pxSession->xSignAlgorithm ) ); + xResult = CKR_KEY_TYPE_INCONSISTENT; + } + } + else + { + PKCS11_PRINT( ( "ERROR: Unsupported mechanism type %d \r\n", pxMechanism->mechanism ) ); + xResult = CKR_MECHANISM_INVALID; + } + } + + if( xResult == CKR_OK ) + { + pxSession->xVerifyMechanism = pxMechanism->mechanism; + } + + return xResult; +} + +/** + * @brief Verifies a digital signature. + * + * \note C_VerifyInit() must have been called previously. + * + * \note C_Verify() parameters are shared by a session. Calling + * C_VerifyInit() & C_Verify() with the same session across different + * tasks may lead to unexpected results. + * + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pucData Data who's signature is to be verified. + * Note: In this implementation, this is generally + * expected to be the hash of the data. + * @param[in] ulDataLen Length of pucData. + * @param[in] pucSignature The signature to be verified. + * @param[in] ulSignatureLength Length of pucSignature in bytes. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DEFINE_FUNCTION( CK_RV, C_Verify )( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR pucData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pucSignature, + CK_ULONG ulSignatureLen ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + P11SessionPtr_t pxSessionObj; + int lMbedTLSResult; + psa_status_t uxStatus; + + pxSessionObj = prvSessionPointerFromHandle( xSession ); /*lint !e9072 It's OK to have different parameter name. */ + + if( xResult == CKR_OK ) + { + /* Check parameters. */ + if( ( NULL == pucData ) || + ( NULL == pucSignature ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + + /* Check that the signature and data are the expected length. + * These PKCS #11 mechanism expect data to be pre-hashed/formatted. */ + if( xResult == CKR_OK ) + { + if( pxSessionObj->xVerifyMechanism == CKM_RSA_X_509 ) + { + if( ulDataLen != pkcs11RSA_2048_SIGNATURE_LENGTH ) + { + xResult = CKR_DATA_LEN_RANGE; + } + + if( ulSignatureLen != pkcs11RSA_2048_SIGNATURE_LENGTH ) + { + xResult = CKR_SIGNATURE_LEN_RANGE; + } + } + else if( pxSessionObj->xVerifyMechanism == CKM_ECDSA ) + { + if( ulDataLen != pkcs11SHA256_DIGEST_LENGTH ) + { + xResult = CKR_DATA_LEN_RANGE; + } + + if( ulSignatureLen != pkcs11ECDSA_P256_SIGNATURE_LENGTH ) + { + xResult = CKR_SIGNATURE_LEN_RANGE; + } + } + else + { + xResult = CKR_OPERATION_NOT_INITIALIZED; + } + } + + if( xResult == CKR_OK ) + { + if( pdTRUE == xSemaphoreTake( pxSessionObj->xVerifyMutex, portMAX_DELAY ) ) + { + /* Verify the signature. If a public key is present, use it. */ + if ( pxSessionObj->uxVerifyKey == 0 ) + { + xResult = CKR_KEY_HANDLE_INVALID; + } + else + { + uxStatus = psa_verify_hash( pxSessionObj->uxVerifyKey, + pxSessionObj->xVerifyAlgorithm, + ( const uint8_t * )pucData, + ( size_t )ulDataLen, + ( const uint8_t * )pucSignature, + ( size_t )ulSignatureLen ); + + if( uxStatus == PSA_SUCCESS ) + { + xResult = CKR_OK; + } + + /* + * In PSA_ERROR_BUFFER_TOO_SMALL and PSA_ERROR_INVALID_SIGNATURE case, + * return invalid signature. + */ + else if( ( uxStatus == PSA_ERROR_INVALID_SIGNATURE ) || + ( uxStatus == PSA_ERROR_BUFFER_TOO_SMALL ) ) + { + xResult = CKR_SIGNATURE_INVALID; + } + else + { + xResult = CKR_FUNCTION_FAILED; + } + } + xSemaphoreGive( pxSessionObj->xVerifyMutex ); + } + else + { + xResult = CKR_CANT_LOCK; + } + } + + /* Return the signature verification result. */ + return xResult; +} + +/* Checks that the private key template provided for C_GenerateKeyPair + * contains all necessary attributes, and does not contain any invalid + * attributes. */ +CK_RV prvCheckGenerateKeyPairPrivateTemplate( CK_ATTRIBUTE_PTR * ppxLabel, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulTemplateLength ) +{ + CK_ATTRIBUTE xAttribute; + CK_RV xResult = CKR_OK; + CK_BBOOL xBool; + CK_ULONG xTemp; + CK_ULONG xIndex; + uint32_t xAttributeMap = 0; + uint32_t xRequiredAttributeMap = ( LABEL_IN_TEMPLATE | PRIVATE_IN_TEMPLATE | SIGN_IN_TEMPLATE ); + + for( xIndex = 0; xIndex < ulTemplateLength; xIndex++ ) + { + xAttribute = pxTemplate[ xIndex ]; + + switch( xAttribute.type ) + { + case ( CKA_LABEL ): + *ppxLabel = &pxTemplate[ xIndex ]; + xAttributeMap |= LABEL_IN_TEMPLATE; + break; + + case ( CKA_TOKEN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only token key generation is supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + case ( CKA_KEY_TYPE ): + memcpy( &xTemp, xAttribute.pValue, sizeof( CK_ULONG ) ); + + if( xTemp != CKK_EC ) + { + PKCS11_PRINT( ( "ERROR: Only EC key pair generation is supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + break; + + case ( CKA_PRIVATE ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Generating private keys that are not marked private is not supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + xAttributeMap |= PRIVATE_IN_TEMPLATE; + break; + + case ( CKA_SIGN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Generating private keys that cannot sign is not supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + xAttributeMap |= SIGN_IN_TEMPLATE; + break; + + default: + xResult = CKR_TEMPLATE_INCONSISTENT; + break; + } + } + + if( ( xAttributeMap & xRequiredAttributeMap ) != xRequiredAttributeMap ) + { + xResult = CKR_TEMPLATE_INCOMPLETE; + } + + return xResult; +} + +/* Checks that the public key template provided for C_GenerateKeyPair + * contains all necessary attributes, and does not contain any invalid + * attributes. */ +CK_RV prvCheckGenerateKeyPairPublicTemplate( CK_ATTRIBUTE_PTR * ppxLabel, + CK_ATTRIBUTE_PTR pxTemplate, + CK_ULONG ulTemplateLength ) +{ + CK_ATTRIBUTE xAttribute; + CK_RV xResult = CKR_OK; + CK_BBOOL xBool; + CK_KEY_TYPE xKeyType; + CK_BYTE xEcParams[] = pkcs11DER_ENCODED_OID_P256; + int lCompare; + CK_ULONG ulIndex; + uint32_t xAttributeMap = 0; + uint32_t xRequiredAttributeMap = ( LABEL_IN_TEMPLATE | EC_PARAMS_IN_TEMPLATE | VERIFY_IN_TEMPLATE ); + + for( ulIndex = 0; ulIndex < ulTemplateLength; ulIndex++ ) + { + xAttribute = pxTemplate[ ulIndex ]; + + switch( xAttribute.type ) + { + case ( CKA_LABEL ): + + *ppxLabel = &pxTemplate[ ulIndex ]; + xAttributeMap |= LABEL_IN_TEMPLATE; + break; + + case ( CKA_KEY_TYPE ): + memcpy( &xKeyType, xAttribute.pValue, sizeof( CK_KEY_TYPE ) ); + + if( xKeyType != CKK_EC ) + { + PKCS11_PRINT( ( "ERROR: Only EC key pair generation is supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + break; + + case ( CKA_EC_PARAMS ): + lCompare = memcmp( xEcParams, xAttribute.pValue, sizeof( xEcParams ) ); + + if( lCompare != 0 ) + { + PKCS11_PRINT( ( "ERROR: Only P-256 key generation is supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + xAttributeMap |= EC_PARAMS_IN_TEMPLATE; + break; + + case ( CKA_VERIFY ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Generating public keys that cannot verify is not supported. \r\n" ) ); + xResult = CKR_TEMPLATE_INCONSISTENT; + } + + xAttributeMap |= VERIFY_IN_TEMPLATE; + break; + + case ( CKA_TOKEN ): + memcpy( &xBool, xAttribute.pValue, sizeof( CK_BBOOL ) ); + + if( xBool != CK_TRUE ) + { + PKCS11_PRINT( ( "ERROR: Only token key generation is supported. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + break; + + default: + xResult = CKR_TEMPLATE_INCONSISTENT; + break; + } + } + + if( ( xAttributeMap & xRequiredAttributeMap ) != xRequiredAttributeMap ) + { + xResult = CKR_TEMPLATE_INCOMPLETE; + } + + return xResult; +} + +/** + * @brief Generate a new public-private key pair. + * + * This port only supports generating elliptic curve P-256 + * key pairs. + * + * @param[in] xSession Handle of a valid PKCS #11 session. + * @param[in] pxMechanism Pointer to a mechanism. At this time, + * CKM_EC_KEY_PAIR_GEN is the only supported mechanism. + * @param[in] pxPublicKeyTemplate Pointer to a list of attributes that the generated + * public key should possess. + * Public key template must have the following attributes: + * - CKA_LABEL + * - Label should be no longer than #pkcs11configMAX_LABEL_LENGTH + * and must be supported by port's PKCS #11 PAL. + * - CKA_EC_PARAMS + * - Must equal pkcs11DER_ENCODED_OID_P256. + * Only P-256 keys are supported. + * - CKA_VERIFY + * - Must be set to true. Only public keys used + * for verification are supported. + * Public key templates may have the following attributes: + * - CKA_KEY_TYPE + * - Must be set to CKK_EC. Only elliptic curve key + * generation is supported. + * - CKA_TOKEN + * - Must be set to CK_TRUE. + * @param[in] ulPublicKeyAttributeCount Number of attributes in pxPublicKeyTemplate. + * @param[in] pxPrivateKeyTemplate Pointer to a list of attributes that the generated + * private key should possess. + * Private key template must have the following attributes: + * - CKA_LABEL + * - Label should be no longer than #pkcs11configMAX_LABEL_LENGTH + * and must be supported by port's PKCS #11 PAL. + * - CKA_PRIVATE + * - Must be set to true. + * - CKA_SIGN + * - Must be set to true. Only private keys used + * for signing are supported. + * Private key template may have the following attributes: + * - CKA_KEY_TYPE + * - Must be set to CKK_EC. Only elliptic curve key + * generation is supported. + * - CKA_TOKEN + * - Must be set to CK_TRUE. + * + * @param[in] ulPrivateKeyAttributeCount Number of attributes in pxPrivateKeyTemplate. + * @param[out] pxPublicKey Pointer to the handle of the public key to be created. + * @param[out] pxPrivateKey Pointer to the handle of the private key to be created. + * + * \note Not all attributes specified by the PKCS #11 standard are supported. + * \note CKA_LOCAL attribute is not supported. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DEFINE_FUNCTION( CK_RV, C_GenerateKeyPair )( CK_SESSION_HANDLE xSession, + CK_MECHANISM_PTR pxMechanism, + CK_ATTRIBUTE_PTR pxPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pxPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR pxPublicKey, + CK_OBJECT_HANDLE_PTR pxPrivateKey ) +{ + CK_RV xResult = PKCS11_SESSION_VALID_AND_MODULE_INITIALIZED( xSession ); + psa_status_t uxStatus; + psa_key_attributes_t private_key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t public_key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t key_handle_private; + psa_key_handle_t key_handle_public; + psa_key_type_t uxKeyType; + psa_algorithm_t uxAlgorithm; + CK_ATTRIBUTE_PTR pxPrivateLabel = NULL; + CK_ATTRIBUTE_PTR pxPublicLabel = NULL; + uint8_t * pUncompressedECPoint = pvPortMalloc( pkcs11KEY_ECPOINT_LENGTH ); + size_t uxPublicKeyLength; + + if( pUncompressedECPoint == NULL ) + { + xResult = CKR_HOST_MEMORY; + } + + #if ( pkcs11configSUPPRESS_ECDSA_MECHANISM == 1 ) + if( xResult == CKR_OK ) + { + xResult = CKR_MECHANISM_INVALID; + } + #endif + + if( xResult == CKR_OK ) + { + if( ( pxPublicKeyTemplate == NULL ) || + ( pxPrivateKeyTemplate == NULL ) || + ( pxPublicKey == NULL ) || + ( pxPrivateKey == NULL ) || + ( pxMechanism == NULL ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + + if( xResult == CKR_OK ) + { + if( CKM_EC_KEY_PAIR_GEN != pxMechanism->mechanism ) + { + xResult = CKR_MECHANISM_PARAM_INVALID; + } + } + + if( xResult == CKR_OK ) + { + xResult = prvCheckGenerateKeyPairPrivateTemplate( &pxPrivateLabel, + pxPrivateKeyTemplate, + ulPrivateKeyAttributeCount ); + } + + if( xResult == CKR_OK ) + { + xResult = prvCheckGenerateKeyPairPublicTemplate( &pxPublicLabel, + pxPublicKeyTemplate, + ulPublicKeyAttributeCount ); + } + + if( xResult == CKR_OK ) + { + uxAlgorithm = PSA_ALG_ECDSA( PSA_ALG_SHA_256 ); + uxKeyType = PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ); + if( strcmp( pxPrivateLabel->pValue, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) == 0 ) + { + /* If this is the device private key, then create it as a persistent key. */ +#ifndef pkcs11configTFM_VERSION_1_0 + psa_set_key_id( &private_key_attributes, PSA_DEVICE_PRIVATE_KEY_ID ); +#endif + } + psa_set_key_usage_flags( &private_key_attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &private_key_attributes, uxAlgorithm ); + + /* + * Please refer https://tools.ietf.org/html/rfc8422 + * NISTP256 is equivalent to SECP256r1. + * To keep consistent with mbedtls based implementation, set the key + * type as ECC_KEYPAIR(SECP256R1). + * Generate key pair with the private key handle. + */ + psa_set_key_type( &private_key_attributes, uxKeyType ); + psa_set_key_bits( &private_key_attributes, ( size_t )256 ); + uxStatus = psa_generate_key( &private_key_attributes, &key_handle_private ); + + if ( uxStatus == PSA_SUCCESS ) + { + /* + * Export the public key from the generated key pair. + * Policy is not checked when exporting a public key. + */ + uxStatus = psa_export_public_key( key_handle_private, + pUncompressedECPoint, + pkcs11KEY_ECPOINT_LENGTH, + &uxPublicKeyLength ); + + } + if ( uxStatus == PSA_SUCCESS ) + { + uxKeyType = PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ); + uxAlgorithm = PSA_ALG_ECDSA( PSA_ALG_SHA_256 ); + if( strcmp( pxPublicLabel->pValue, + pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) == 0 ) + { + /* If this is the device public key, then create it as a persistent key. */ +#ifndef pkcs11configTFM_VERSION_1_0 + psa_set_key_id( &public_key_attributes, PSA_DEVICE_PUBLIC_KEY_ID ); +#endif + } + psa_set_key_usage_flags( &public_key_attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &public_key_attributes, uxAlgorithm ); + psa_set_key_type( &public_key_attributes, uxKeyType ); + + /* Import the public key with data exported by psa_export_public_key. */ + uxStatus = psa_import_key( &public_key_attributes, + pUncompressedECPoint, + uxPublicKeyLength, + &key_handle_public ); + } + if ( uxStatus == PSA_SUCCESS ) + { + if( strcmp( pxPrivateLabel->pValue, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) == 0 ) + { + /* Import the object into pkcs#11 PSA context. */ + PKCS11PSAContextImportObject( pxPrivateLabel->pValue, + strlen( ( const char * ) pxPrivateLabel->pValue ), + key_handle_private ); + xResult = prvAddObjectToList( eAwsDevicePrivateKey, pxPrivateKey, pxPrivateLabel->pValue, pxPrivateLabel->ulValueLen ); + } + else + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + if( xResult == CKR_OK ) + { + if( strcmp( pxPublicLabel->pValue, + pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) == 0 ) + { + /* Import the object into pkcs#11 PSA context. */ + PKCS11PSAContextImportObject( pxPublicLabel->pValue, + strlen( ( const char * ) pxPublicLabel->pValue ), + key_handle_public ); + xResult = prvAddObjectToList( eAwsDevicePublicKey, pxPublicKey, pxPublicLabel->pValue, pxPublicLabel->ulValueLen ); + } + else + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + } + } + else + { + xResult = CKR_FUNCTION_FAILED; + } + } + return xResult; +} + +/** + * @brief Generate cryptographically random bytes. + * + * @param xSession[in] Handle of a valid PKCS #11 session. + * @param pucRandomData[out] Pointer to location that random data will be placed. + * It is the responsiblity of the application to allocate + * this memory. + * @param ulRandomLength[in] Length of data (in bytes) to be generated. + * + * @return CKR_OK if successful. + * Else, see PKCS #11 specification + * for more information. + */ +CK_DEFINE_FUNCTION( CK_RV, C_GenerateRandom )( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR pucRandomData, + CK_ULONG ulRandomLen ) +{ + CK_RV xResult = CKR_OK; + psa_status_t uxStatus; + + /* Avoid warnings about unused parameters. */ + ( void ) xSession; + + if( ( NULL == pucRandomData ) || + ( ulRandomLen == 0 ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + else + { + uxStatus = psa_generate_random( pucRandomData, ( size_t )ulRandomLen ); + if ( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + } + + return xResult; +} diff --git a/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.c b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.c new file mode 100644 index 0000000..f5382c1 --- /dev/null +++ b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2006-2020, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This file is derivative of amazon-freertos\libraries\3rdparty\mbedtls\library\ + * pkparse.c(amazon-freertos commit 74875b1d2) + */ + +/** + * @file iot_pkcs11_psa_input_format.c + * @brief Functions to get the PSA API format input. + */ + +#include +#include "iot_pkcs11_psa_input_format.h" + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * Get the uncompressed representation defined by SEC1 §2.3.3 + * as the content of an ECPoint. + */ +int get_public_key_ECPoint( const unsigned char *key, + size_t keylen, + unsigned char **startaddr, + size_t *length ) +{ + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *p = (unsigned char *) key; + const unsigned char *end = key + keylen; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /** + * Get the start address of public key and its length. + */ + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + *startaddr = p; + *length = end - p; + } + return 0; +} diff --git a/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.h b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.h new file mode 100644 index 0000000..3bf18b3 --- /dev/null +++ b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_input_format.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2006-2020, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This file is derivative of amazon-freertos\libraries\3rdparty\mbedtls\library\ + * pkparse.c(amazon-freertos commit 74875b1d2) + */ + +#ifndef __IOT_PKCS11_PSA_INPUT_FORMAT_H__ +#define __IOT_PKCS11_PSA_INPUT_FORMAT_H__ + +/* mbedTLS includes. */ +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/pk_internal.h" +#include "mbedtls/oid.h" + +#define pkcs11DER_ENCODED_OID_P256_LEGNTH 19 + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ); + +/* + * Get the uncompressed representation defined by SEC1 §2.3.3 + * as the content of an ECPoint. + */ +int get_public_key_ECPoint( const unsigned char *key, + size_t keylen, + unsigned char **startaddr, + size_t *length ); + +#endif /* ifndef __IOT_PKCS11_PSA_INPUT_FORMAT_H__ */ diff --git a/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.c b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.c new file mode 100644 index 0000000..458831e --- /dev/null +++ b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.c @@ -0,0 +1,918 @@ +/* + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2019-2020 Arm Limited. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * This file is derivative of amazon-freertos\vendors\st\boards\stm32l475_discovery\ + * ports\pkcs11\iot_pkcs11_pal.c(amazon-freertos commit 74875b1d2) + */ + +/** + * @file iot_pkcs11_psa_object_management.c + * @brief Functions of managing the objects stored in TF-M. + */ + +#include +#include "iot_pkcs11_psa_object_management.h" +#include "iot_pkcs11_psa_input_format.h" + +extern int convert_pem_to_der( const unsigned char * pucInput, size_t xLen, + unsigned char * pucOutput, size_t * pxOlen ); + +/* + * This is the context of the PKCS#11 PSA object. It is placed in a section. + * named "tasks_share". If MPU is enabled, tasks that call PKCS#11 APIs should + * be configured to have access to this region. + */ +P11KeyConfig_t P11KeyConfig __attribute__(( section( "tasks_share" ) )); + +/** +* @brief Helper function to convert MBedtls ECP group to PSA ECC group ID +* +* @param[in] grpid MBedtls ECP group ID. +* +* @return PSA ECC group ID. +*/ + +static psa_ecc_family_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid ) +{ + switch( grpid ) + { + case MBEDTLS_ECP_DP_SECP192R1: + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP224R1: + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP256R1: + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP384R1: + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP521R1: + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_BP256R1: + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP384R1: + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP512R1: + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_CURVE25519: + return( PSA_ECC_FAMILY_MONTGOMERY ); + case MBEDTLS_ECP_DP_SECP192K1: + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP224K1: + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP256K1: + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_CURVE448: + return( PSA_ECC_FAMILY_MONTGOMERY ); + default: + return( 0 ); + } +} + +/** +* @brief Writes a file to local storage. +* +* Port-specific file write for crytographic information. +* +* @param[in] pxClass Class of the object to be saved. +* @param[in] pxLabel Label of the object to be saved. +* @param[in] pucData Data buffer to be written to file +* @param[in] ulDataSize Size (in bytes) of data to be saved. +* @param[in] pvContext Context of the key. +* +* @return The file handle of the object that was stored. +*/ +CK_OBJECT_HANDLE PKCS11PSASaveObject( CK_ATTRIBUTE_PTR pxClass, + CK_ATTRIBUTE_PTR pxLabel, + uint8_t * pucData, + uint32_t ulDataSize, + mbedtls_pk_context *pvContext ) +{ + CK_OBJECT_HANDLE xHandle = eInvalidHandle; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + CK_ULONG uxKeyType; + psa_key_handle_t uxKeyHandle; + psa_algorithm_t uxAlgorithm; + CK_RV xBytesWritten = 0; + CK_RV xReturn; + psa_status_t uxStatus = PSA_SUCCESS; + mbedtls_ecp_group_id curve_id; + const mbedtls_ecp_keypair *ec; + unsigned char cPrivateKeyRaw[EC_PRIVATE_KEY_MAX_LENGTH]; + size_t xPrivateKeyRawSize = 0; + unsigned char *pcPublicKeyUncompressedData = NULL; + size_t xPublicKeySizeUncompressed = 0; + uint8_t * pucKeyData = NULL; + uint32_t ulKeyDataSize = 0; + mbedtls_pk_type_t uxPrivateKeyTypePKCS11 = 0; + + if( ulDataSize <= pkcs11OBJECT_MAX_SIZE ) + { + /* + * write client certificate. + */ + if( ( *( ( uint32_t * )pxClass->pValue ) == CKO_CERTIFICATE ) && + ( strcmp( pxLabel->pValue, + pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS ) == 0 ) ) + { + uxStatus = psa_ps_set( PSA_DEVICE_CERTIFICATE_UID, + ulDataSize, + pucData, + ( psa_storage_create_flags_t ) PSA_STORAGE_FLAG_NONE ); + if( uxStatus == PSA_SUCCESS ) + { + xHandle = eAwsDeviceCertificate; + + /* Import the object into P11KeyConfig context. */ + PKCS11PSAContextImportObject( pxLabel->pValue, + strlen( ( const char * ) pxLabel->pValue ), + pkcs11OBJECT_HANDLE_NA ); + } + } + + /* + * write Jitp certificate. + */ + else if( ( *( ( uint32_t * )pxClass->pValue ) == CKO_CERTIFICATE ) && + ( strcmp( pxLabel->pValue, + pkcs11configLABEL_JITP_CERTIFICATE ) == 0 ) ) + { + uxStatus = psa_ps_set( PSA_JITP_CERTIFICATE_UID, + ulDataSize, + pucData, + ( psa_storage_create_flags_t ) PSA_STORAGE_FLAG_NONE ); + + if( uxStatus == PSA_SUCCESS ) + { + xHandle = eAwsJitpCertificate; + + /* Import the object into P11KeyConfig context. */ + PKCS11PSAContextImportObject( pxLabel->pValue, + strlen( ( const char * ) pxLabel->pValue ), + pkcs11OBJECT_HANDLE_NA ); + } + } + + /* + * write Root certificate. + */ + else if( ( *( ( uint32_t * )pxClass->pValue ) == CKO_CERTIFICATE ) && + ( strcmp( pxLabel->pValue, + pkcs11configLABEL_ROOT_CERTIFICATE ) == 0 ) ) + { + uxStatus = psa_ps_set( PSA_ROOT_CERTIFICATE_UID, + ulDataSize, + pucData, + ( psa_storage_create_flags_t ) PSA_STORAGE_FLAG_NONE ); + + if( uxStatus == PSA_SUCCESS ) + { + xHandle = eAwsRootCertificate; + + /* Import the object into P11KeyConfig context. */ + PKCS11PSAContextImportObject( pxLabel->pValue, + strlen( ( const char * ) pxLabel->pValue ), + pkcs11OBJECT_HANDLE_NA ); + } + } + + /* + * Store device private key by crypto service of PSA. + */ + + else if( ( *( ( uint32_t * )pxClass->pValue ) == CKO_PRIVATE_KEY ) && + ( strcmp( pxLabel->pValue, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) == 0 ) ) + { + /* + * Device private key is only used to make a signature, + * only support RSA alg, only support MBEDTLS_RSA_PKCS_V15 + * padding mode, only support SHA256 md alg. + */ + uxPrivateKeyTypePKCS11 = mbedtls_pk_get_type( pvContext ); + switch ( uxPrivateKeyTypePKCS11 ) + { + case MBEDTLS_PK_RSA: + uxKeyType = PSA_KEY_TYPE_RSA_KEY_PAIR; + pucKeyData = pucData; + ulKeyDataSize = ulDataSize; + switch ( ( ( mbedtls_rsa_context * ) ( pvContext->pk_ctx ) )->padding ) + { + case MBEDTLS_RSA_PKCS_V15: + uxAlgorithm = PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ); + break; + + case MBEDTLS_RSA_PKCS_V21: + uxAlgorithm = PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ); + break; + + default: + uxAlgorithm = 0; + uxStatus = PSA_ERROR_INVALID_ARGUMENT; + break; + } + break; + + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECDSA: + ec = (mbedtls_ecp_keypair *) (pvContext->pk_ctx ); + curve_id = mbedtls_ecp_curve_info_from_grp_id( ec->grp.id )->grp_id; + uxKeyType = PSA_KEY_TYPE_ECC_KEY_PAIR(mbedtls_ecc_group_to_psa(curve_id)); + uxAlgorithm = PSA_ALG_ECDSA( PSA_ALG_SHA_256 ); + xPrivateKeyRawSize = ( ec->grp.nbits + 7 ) / 8; + if( 0 != mbedtls_mpi_write_binary( &ec->d, + cPrivateKeyRaw, + xPrivateKeyRawSize ) ) + { + uxStatus = PSA_ERROR_GENERIC_ERROR; + } + pucKeyData = cPrivateKeyRaw; + ulKeyDataSize = xPrivateKeyRawSize; + break; + default: + uxAlgorithm = 0; + uxKeyType = 0; + uxStatus = PSA_ERROR_INVALID_ARGUMENT; + break; + } + if ( uxStatus == PSA_SUCCESS ) + { + /* Device private key is saved as persistent key. */ +#ifndef pkcs11configTFM_VERSION_1_0 + psa_set_key_id( &key_attributes, PSA_DEVICE_PRIVATE_KEY_ID ); +#endif + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &key_attributes, uxAlgorithm ); + psa_set_key_type( &key_attributes, uxKeyType ); + uxStatus = psa_import_key( &key_attributes, + ( const uint8_t * )pucKeyData, + ulKeyDataSize, + &uxKeyHandle ); + } + if ( uxStatus == PSA_SUCCESS ) + { + xHandle = eAwsDevicePrivateKey; + + /* Import the object into P11KeyConfig context. */ + PKCS11PSAContextImportObject( pxLabel->pValue, + strlen( ( const char * ) pxLabel->pValue ), + uxKeyHandle ); + } + } + else if( ( *( ( uint32_t * )pxClass->pValue ) == CKO_PUBLIC_KEY ) && + ( strcmp( pxLabel->pValue, + pkcs11configLABEL_CODE_VERIFICATION_KEY ) == 0 ) ) + { + /* + * Code verify key is only used to make a verify, + * only SHA256 md alg. + */ + switch ( mbedtls_pk_get_type( pvContext ) ) + { + case MBEDTLS_PK_RSA: + /** + * The RSA private key should contain the public key. So it should not go here. + */ + uxStatus = PSA_ERROR_INVALID_ARGUMENT; + break; + + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECDSA: + ec = (mbedtls_ecp_keypair *) (pvContext->pk_ctx ); + curve_id = mbedtls_ecp_curve_info_from_grp_id( ec->grp.id )->grp_id; + uxKeyType = PSA_KEY_TYPE_ECC_PUBLIC_KEY(mbedtls_ecc_group_to_psa(curve_id)); + uxAlgorithm = PSA_ALG_ECDSA( PSA_ALG_SHA_256 ); + if( 0 !=get_public_key_ECPoint( pucData, + ulDataSize, + &pcPublicKeyUncompressedData, + &xPublicKeySizeUncompressed ) ) + { + uxStatus = PSA_ERROR_GENERIC_ERROR; + } + + pucKeyData = pcPublicKeyUncompressedData; + ulKeyDataSize = xPublicKeySizeUncompressed; + break; + default: + uxAlgorithm = 0; + uxStatus = PSA_ERROR_INVALID_ARGUMENT; + break; + } + if ( uxStatus == PSA_SUCCESS ) + { + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &key_attributes, uxAlgorithm ); + psa_set_key_type( &key_attributes, uxKeyType ); + uxStatus = psa_import_key( &key_attributes, + ( const uint8_t * )pucKeyData, + ulKeyDataSize, + &uxKeyHandle ); + } + if ( uxStatus == PSA_SUCCESS ) + { + xHandle = eAwsCodeVerifyingKey; + + /* Import the object into P11KeyConfig context. */ + PKCS11PSAContextImportObject( pxLabel->pValue, + strlen( ( const char * ) pxLabel->pValue ), + uxKeyHandle ); + } + } + else if( ( *( ( uint32_t * )pxClass->pValue ) == CKO_PUBLIC_KEY ) && + ( strcmp( pxLabel->pValue, + pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) == 0 ) ) + { + /* + * Code verify key is only used to make a verify, + * only SHA256 md alg. + */ + switch ( mbedtls_pk_get_type( pvContext ) ) + { + case MBEDTLS_PK_RSA: + uxStatus = PSA_ERROR_INVALID_ARGUMENT; + break; + + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECDSA: + ec = (mbedtls_ecp_keypair *) (pvContext->pk_ctx ); + curve_id = mbedtls_ecp_curve_info_from_grp_id( ec->grp.id )->grp_id; + uxKeyType = PSA_KEY_TYPE_ECC_PUBLIC_KEY(mbedtls_ecc_group_to_psa(curve_id)); + uxAlgorithm = PSA_ALG_ECDSA( PSA_ALG_SHA_256 ); + if( 0 !=get_public_key_ECPoint( pucData, + ulDataSize, + &pcPublicKeyUncompressedData, + &xPublicKeySizeUncompressed ) ) + { + uxStatus = PSA_ERROR_GENERIC_ERROR; + } + pucKeyData = pcPublicKeyUncompressedData; + ulKeyDataSize = xPublicKeySizeUncompressed; + break; + default: + uxStatus = PSA_ERROR_INVALID_ARGUMENT; + uxAlgorithm = 0; + break; + } + if( uxStatus == PSA_SUCCESS ) + { + /* Device public key is saved as persistent key. */ +#ifndef pkcs11configTFM_VERSION_1_0 + psa_set_key_id( &key_attributes, PSA_DEVICE_PUBLIC_KEY_ID ); +#endif + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &key_attributes, uxAlgorithm ); + psa_set_key_type( &key_attributes, uxKeyType ); + uxStatus = psa_import_key( &key_attributes, + ( const uint8_t * )pucKeyData, + ulKeyDataSize, + &uxKeyHandle ); + + } + if ( uxStatus == PSA_SUCCESS ) + { + xHandle = eAwsDevicePublicKey; + + /* Import the object into P11KeyConfig context. */ + PKCS11PSAContextImportObject( pxLabel->pValue, + strlen( ( const char * ) pxLabel->pValue ), + uxKeyHandle ); + } + } + } + + return xHandle; +} + +/** +* @brief Helper function to get value of a certificate from PSA secure storage +* +* @param[in] uid The uid value. +* @param[out] pucData Pointer to buffer for file data. +* @param[out] pulDataSize Size (in bytes) of data located in file. +* @param[out] pIsPrivate Boolean indicating if value is private (CK_TRUE) +* or exportable (CK_FALSE) +* +* @return CKR_OK if operation was successful. CKR_KEY_HANDLE_INVALID if +* no such object handle was found, CKR_DEVICE_MEMORY if memory for +* buffer could not be allocated, CKR_FUNCTION_FAILED for device driver +* error. +*/ +static CK_RV PSAGetCertificateValue( psa_storage_uid_t uid, + uint8_t * pucData, + size_t * pulDataSize, + CK_BBOOL * pIsPrivate ) +{ + CK_RV ulReturn = CKR_OBJECT_HANDLE_INVALID; + size_t ulDataSize = *pulDataSize; + psa_status_t uxStatus; + uint8_t * pucBuffer; + size_t ulReadDataLen = 0; + struct psa_storage_info_t info = {0}; + + /* Get the size of the data associated with the certificate UID firstly. */ + uxStatus = psa_ps_get_info( uid, &info ); + + if ( uxStatus == PSA_SUCCESS ) + { + /* Allocate buffer for object value */ + pucBuffer = pvPortMalloc( info.size ); + + if ( pucBuffer != NULL ) + { + /* Get the object value */ + uxStatus = psa_ps_get( uid, 0, info.size, pucBuffer, &ulReadDataLen ); + if ( uxStatus == PSA_SUCCESS ) + { + /* Convert the certificate from PEM to DER format */ + if ( convert_pem_to_der( pucBuffer, ulReadDataLen, pucData, &ulDataSize ) != 0 ) + { + /* Not PEM format, use as it is. */ + ulDataSize = ulReadDataLen; + memcpy( pucData, pucBuffer, ulDataSize ); + } + + *pulDataSize = ulDataSize; + *pIsPrivate = CK_FALSE; + ulReturn = CKR_OK; + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + vPortFree( pucBuffer ); + } + else + { + ulReturn = CKR_DEVICE_MEMORY; + } + } + return ulReturn; +} + +/** +* @brief Gets the value of an object in storage, by handle. +* +* Port-specific file access for cryptographic information. +* +* This call dynamically allocates the buffer which object value +* data is copied into. PKCS11PSAGetObjectValueCleanup() +* should be called after each use to free the dynamically allocated +* buffer. +* +* @sa PKCS11PSAGetObjectValueCleanup +* +* @param[in] pcFileName The name of the file to be read. +* @param[out] pucData Pointer to buffer for file data. +* @param[out] pulDataSize Size (in bytes) of data located in file. +* @param[out] pIsPrivate Boolean indicating if value is private (CK_TRUE) +* or exportable (CK_FALSE) +* +* @return CKR_OK if operation was successful. CKR_KEY_HANDLE_INVALID if +* no such object handle was found, CKR_DEVICE_MEMORY if memory for +* buffer could not be allocated, CKR_FUNCTION_FAILED for device driver +* error. +*/ +CK_RV PKCS11PSAGetObjectValue( CK_OBJECT_HANDLE xHandle, + uint8_t * pucData, + size_t * pulDataSize, + CK_BBOOL * pIsPrivate ) +{ + CK_RV ulReturn = CKR_OBJECT_HANDLE_INVALID; + psa_status_t uxStatus; + psa_key_type_t key_type; + size_t key_bits; + size_t buffer_size; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* + * Read client certificate. + */ + if( xHandle == eAwsDeviceCertificate ) + { + /* + * return reference and size only if certificates are present in the device. + */ + if( P11KeyConfig.xDeviceCertificateMark == pdTRUE ) + { + ulReturn = PSAGetCertificateValue(PSA_DEVICE_CERTIFICATE_UID, pucData, pulDataSize, pIsPrivate); + } + } + + /* + * Read Jitp certificate. + */ + if( xHandle == eAwsJitpCertificate ) + { + /* + * return reference and size only if certificates are present in the device. + */ + if( P11KeyConfig.xJitpCertificateMark == pdTRUE ) + { + ulReturn = PSAGetCertificateValue(PSA_JITP_CERTIFICATE_UID, pucData, pulDataSize, pIsPrivate); + } + } + + /* + * Read Root certificate. + */ + if( xHandle == eAwsRootCertificate ) + { + /* + * return reference and size only if certificates are present in the device. + */ + if( P11KeyConfig.xRootCertificateMark == pdTRUE ) + { + ulReturn = PSAGetCertificateValue(PSA_ROOT_CERTIFICATE_UID, pucData, pulDataSize, pIsPrivate); + } + } + + /* + * Read client key. + */ + else if( xHandle == eAwsDevicePrivateKey ) + { + /* + * return reference and size only if key is present in the device and is not private + */ + if( P11KeyConfig.xDevicePrivateKeyMark == pdTRUE ) + { + uxStatus = psa_get_key_attributes( P11KeyConfig.uxDevicePrivateKey, &attributes ); + if( uxStatus == PSA_SUCCESS ) + { + key_type = psa_get_key_type( &attributes ); + key_bits = psa_get_key_bits( &attributes ); + buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ); + uxStatus = psa_export_key( P11KeyConfig.uxDevicePrivateKey, pucData, buffer_size, pulDataSize ); + if ( uxStatus == PSA_ERROR_NOT_PERMITTED ) + { + *pIsPrivate = CK_TRUE; + ulReturn = CKR_OK; + } + else if ( uxStatus == PSA_SUCCESS ) + { + *pIsPrivate = CK_FALSE; + ulReturn = CKR_OK; + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + } + } + + else if( xHandle == eAwsDevicePublicKey ) + { + /* + * return reference and size only if key is present in the device and is not private + */ + if( P11KeyConfig.xDevicePublicKeyMark == pdTRUE ) + { + uxStatus = psa_get_key_attributes( P11KeyConfig.uxDevicePublicKey, &attributes ); + if( uxStatus == PSA_SUCCESS ) + { + key_type = psa_get_key_type( &attributes ); + key_bits = psa_get_key_bits( &attributes ); + buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ); + uxStatus = psa_export_key( P11KeyConfig.uxDevicePublicKey, pucData, buffer_size, pulDataSize ); + if ( uxStatus == PSA_ERROR_NOT_PERMITTED ) + { + *pIsPrivate = CK_TRUE; + ulReturn = CKR_OK; + } + else if ( uxStatus == PSA_SUCCESS ) + { + *pIsPrivate = CK_FALSE; + ulReturn = CKR_OK; + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + } + } + + else if( xHandle == eAwsCodeVerifyingKey ) + { + /* + * return reference and size only if key is present in the device and is not private + */ + if( P11KeyConfig.xCodeVerifyKeyMark == pdTRUE ) + { + uxStatus = psa_get_key_attributes( P11KeyConfig.uxCodeVerifyKey, &attributes ); + if( uxStatus == PSA_SUCCESS ) + { + key_type = psa_get_key_type( &attributes ); + key_bits = psa_get_key_bits( &attributes ); + buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ); + uxStatus = psa_export_key( P11KeyConfig.uxCodeVerifyKey, pucData, buffer_size, pulDataSize ); + if ( uxStatus == PSA_ERROR_NOT_PERMITTED ) + { + *pIsPrivate = CK_TRUE; + ulReturn = CKR_OK; + } + else if ( uxStatus == PSA_SUCCESS ) + { + *pIsPrivate = CK_FALSE; + ulReturn = CKR_OK; + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + } + else + { + ulReturn = CKR_FUNCTION_FAILED; + } + } + } + + return ulReturn; +} + +/** +* @brief Cleanup after PKCS11PSAGetObjectValue(). +* +* @param[in] pucData The buffer to free. +* (*ppucData from PKCS11PSAGetObjectValue()) +* @param[in] ulDataSize The length of the buffer to free. +* (*pulDataSize from PKCS11PSAGetObjectValue()) +*/ +void PKCS11PSAGetObjectValueCleanup( uint8_t * pucData, + uint32_t ulDataSize ) +{ + /* Unused parameters. */ + ( void ) pucData; + ( void ) ulDataSize; + + /* Since no buffer was allocated on heap, there is no cleanup + * to be done. */ +} + +/** +* @brief Import an object into P11KeyConfig. +* +* @param[in] pLableValue The lable of the object. +* +* @param[in] ulLableLen The length of the object label. +* +* @param[in] uxKeyHandle The key handle. +* +*/ +void PKCS11PSAContextImportObject( CK_VOID_PTR pLableValue, + CK_LONG ulLableLen, + psa_key_handle_t uxKeyHandle ) +{ + if( strcmp( pLableValue, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) == 0 ) + { + P11KeyConfig.uxDevicePrivateKey = uxKeyHandle; + + /*change key present mark'*/ + P11KeyConfig.xDevicePrivateKeyMark = pdTRUE; + } + else if( strcmp( pLableValue, + pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) == 0 ) + { + P11KeyConfig.uxDevicePublicKey = uxKeyHandle; + + /*change key present mark'*/ + P11KeyConfig.xDevicePublicKeyMark = pdTRUE; + } + else if( strcmp( pLableValue, + pkcs11configLABEL_CODE_VERIFICATION_KEY ) == 0 ) + { + P11KeyConfig.uxCodeVerifyKey = uxKeyHandle; + + /*change key present mark'*/ + P11KeyConfig.xCodeVerifyKeyMark = pdTRUE; + } + else if( strcmp( pLableValue, + pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS ) == 0 ) + { + /*change certificate present mark'*/ + P11KeyConfig.xDeviceCertificateMark = pdTRUE; + } + else if( strcmp( pLableValue, + pkcs11configLABEL_JITP_CERTIFICATE ) == 0 ) + { + /*change certificate present mark'*/ + P11KeyConfig.xJitpCertificateMark = pdTRUE; + } + else if( strcmp( pLableValue, + pkcs11configLABEL_ROOT_CERTIFICATE ) == 0 ) + { + /*change certificate present mark'*/ + P11KeyConfig.xRootCertificateMark = pdTRUE; + } + else + { + /* Do nothing. */ + } +} + +/** +* @brief Close or remove an object from PSA and update P11KeyConfig accordingly. +* +* @param[in] pLableValue The lable of the object. +* +* @param[in] ulLableLen The length of the object label. +* +* @param[in] permanent Destroy the key or just close the key. +* +*/ +CK_RV PKCS11PSARemoveObject(uint8_t * pcLable, size_t xLabelLength, bool permanent) +{ + CK_RV xResult = CKR_OK; + psa_status_t uxStatus; + + if( memcmp( pcLable, pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, xLabelLength ) == 0 ) + { + if( P11KeyConfig.xDevicePrivateKeyMark == pdTRUE ) + { + if( permanent ) + { + uxStatus = psa_destroy_key( P11KeyConfig.uxDevicePrivateKey ); + } + else + { + uxStatus = psa_close_key( P11KeyConfig.uxDevicePrivateKey ); + } + + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + P11KeyConfig.uxDevicePrivateKey = 0; + P11KeyConfig.xDevicePrivateKeyMark = pdFALSE; + } + } + } + else if( memcmp( pcLable, pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS, xLabelLength ) == 0 ) + { + if( P11KeyConfig.xDevicePublicKeyMark == pdTRUE ) + { + if( permanent ) + { + uxStatus = psa_destroy_key( P11KeyConfig.uxDevicePublicKey ); + } + else + { + uxStatus = psa_close_key( P11KeyConfig.uxDevicePublicKey ); + } + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + P11KeyConfig.uxDevicePublicKey = 0; + P11KeyConfig.xDevicePublicKeyMark = pdFALSE; + } + } + } + else if( memcmp( pcLable, pkcs11configLABEL_CODE_VERIFICATION_KEY, xLabelLength ) == 0 ) + { + if( P11KeyConfig.xCodeVerifyKeyMark == pdTRUE ) + { + if( permanent ) + { + uxStatus = psa_destroy_key( P11KeyConfig.uxCodeVerifyKey ); + } + else + { + uxStatus = psa_close_key( P11KeyConfig.uxCodeVerifyKey ); + } + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + P11KeyConfig.uxCodeVerifyKey = 0; + P11KeyConfig.xCodeVerifyKeyMark = pdFALSE; + } + } + } + else if( memcmp( pcLable, pkcs11configLABEL_ROOT_CERTIFICATE, xLabelLength ) == 0 ) + { + if( P11KeyConfig.xRootCertificateMark == pdTRUE ) + { + uxStatus = psa_ps_remove( PSA_ROOT_CERTIFICATE_UID ); + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + P11KeyConfig.xRootCertificateMark = pdFALSE; + } + } + } + else if( memcmp( pcLable, pkcs11configLABEL_JITP_CERTIFICATE, xLabelLength ) == 0 ) + { + if( P11KeyConfig.xJitpCertificateMark == pdTRUE ) + { + uxStatus = psa_ps_remove( PSA_JITP_CERTIFICATE_UID ); + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + P11KeyConfig.xJitpCertificateMark = pdFALSE; + } + } + } + else if( memcmp( pcLable, pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS, xLabelLength ) == 0 ) + { + if( P11KeyConfig.xDeviceCertificateMark == pdTRUE ) + { + uxStatus = psa_ps_remove( PSA_DEVICE_CERTIFICATE_UID ); + if( uxStatus != PSA_SUCCESS ) + { + xResult = CKR_FUNCTION_FAILED; + } + else + { + P11KeyConfig.xDeviceCertificateMark = pdFALSE; + } + } + } + else + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + return xResult; +} + +/** +* @brief Get the PSA key handle by the object label. +* +* @param[in] pLableValue The lable of the object. +* +* @param[in] ulLableLen The length of the object label. +* +* @param[in] uxKeyHandle The returned key handle. +* +*/ +CK_RV PKCS11PSAGetKeyHandle( uint8_t * pcLable, size_t xLabelLength, psa_key_handle_t * uxKeyHandle ) +{ + CK_RV xResult = CKR_OK; + + if(( memcmp( pcLable, pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, xLabelLength ) == 0 ) && + ( P11KeyConfig.xDevicePrivateKeyMark == pdTRUE )) + { + *uxKeyHandle = P11KeyConfig.uxDevicePrivateKey; + } + else if(( memcmp( pcLable, pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS, xLabelLength ) == 0 ) && + ( P11KeyConfig.xDevicePublicKeyMark == pdTRUE )) + + { + *uxKeyHandle = P11KeyConfig.uxDevicePublicKey; + } + else if(( memcmp( pcLable, pkcs11configLABEL_CODE_VERIFICATION_KEY, xLabelLength ) == 0 ) && + ( P11KeyConfig.xCodeVerifyKeyMark == pdTRUE )) + { + *uxKeyHandle = P11KeyConfig.uxCodeVerifyKey; + } + else + { + xResult = CKR_ARGUMENTS_BAD; + *uxKeyHandle = 0; + } + + return xResult; +} diff --git a/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.h b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.h new file mode 100644 index 0000000..f83baca --- /dev/null +++ b/bsp/aws_libraries/abstractions/pkcs11/psa/iot_pkcs11_psa_object_management.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2019-2020 Arm Limited. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * This file is derivative of amazon-freertos\vendors\st\boards\stm32l475_discovery\ + * ports\pkcs11\iot_pkcs11_pal.c(amazon-freertos commit 74875b1d2) + */ + +#ifndef __IOT_PKCS11_PSA_OBJECT_MANAGEMENT_H__ +#define __IOT_PKCS11_PSA_OBJECT_MANAGEMENT_H__ + +#include +#include + +/* PKCS#11 includes. */ +#include "core_pkcs11_config.h" +#include "core_pkcs11.h" + +/* PSA includes. */ +#include "psa/crypto.h" +#include "psa/protected_storage.h" + +/* mbedTLS includes. */ +#include "mbedtls/pk.h" + +/* + * Define the key ID of the device keys which will be saved as + * persistent keys in TF-M. + */ +#ifndef PSA_DEVICE_PRIVATE_KEY_ID +#define PSA_DEVICE_PRIVATE_KEY_ID ( ( psa_key_id_t )0x01 ) +#endif + +#ifndef PSA_DEVICE_PUBLIC_KEY_ID +#define PSA_DEVICE_PUBLIC_KEY_ID ( ( psa_key_id_t )0x10 ) +#endif + +#ifndef PSA_CODE_VERIFICATION_KEY_ID +#define PSA_CODE_VERIFICATION_KEY_ID ( ( psa_key_id_t )0x11 ) +#endif + +/* UID that indicates the device certificate data in PSA protected storage service. */ +#ifndef PSA_DEVICE_CERTIFICATE_UID +#define PSA_DEVICE_CERTIFICATE_UID ( ( psa_storage_uid_t )5 ) +#endif + +/* UID that indicates the jitp certificate data in PSA protected storage service. */ +#ifndef PSA_JITP_CERTIFICATE_UID +#define PSA_JITP_CERTIFICATE_UID ( ( psa_storage_uid_t )6 ) +#endif + +/* UID that indicates the root certificate data in PSA protected storage service. */ +#ifndef PSA_ROOT_CERTIFICATE_UID +#define PSA_ROOT_CERTIFICATE_UID ( ( psa_storage_uid_t )7 ) +#endif + +/** + * @brief Object definitions. + */ +#define pkcs11OBJECT_MAX_SIZE ( 1300 ) + +/** + * @brief The oject handle field is N/A/ + */ +#define pkcs11OBJECT_HANDLE_NA ( 0x0000 ) + +/** + * The max length(in byte) of the privateKey field of the ECPrivateKey format + * defined by RFC 5915. + */ +#define EC_PRIVATE_KEY_MAX_LENGTH ( 40ul ) + +typedef enum eObjectHandles +{ + eInvalidHandle = 0, /* From PKCS #11 spec: 0 is never a valid object handle.*/ + eAwsDevicePrivateKey = 1, + eAwsDevicePublicKey, + eAwsDeviceCertificate, + eAwsCodeVerifyingKey, + eAwsJitpCertificate, + eAwsRootCertificate +}P11ObjectHandles_t; + +/** + * @brief Structure for certificates/keys storage. + */ +typedef struct +{ + psa_key_handle_t uxDevicePrivateKey; /* Device private key handle that returned by PSA crypto service. */ + psa_key_handle_t uxDevicePublicKey; /* Device public key handle that returned by PSA crypto service. */ + psa_key_handle_t uxCodeVerifyKey; /* Key handle of the key that used by over-the-air update code to verify an incoming signed image. */ + BaseType_t xDeviceCertificateMark; + BaseType_t xDevicePrivateKeyMark; + BaseType_t xDevicePublicKeyMark; + BaseType_t xCodeVerifyKeyMark; + BaseType_t xJitpCertificateMark; + BaseType_t xRootCertificateMark; +} P11KeyConfig_t; + +/** +* @brief Writes a file to local storage. +* +* Port-specific file write for crytographic information. +* +* @param[in] pxClass Class of the object to be saved. +* @param[in] pxLabel Label of the object to be saved. +* @param[in] pucData Data buffer to be written to file +* @param[in] ulDataSize Size (in bytes) of data to be saved. +* @param[in] pvContext Context of the key. +* +* @return The file handle of the object that was stored. +*/ +CK_OBJECT_HANDLE PKCS11PSASaveObject( CK_ATTRIBUTE_PTR pxClass, + CK_ATTRIBUTE_PTR pxLabel, + uint8_t * pucData, + uint32_t ulDataSize, + mbedtls_pk_context *pvContext ); + +/** +* @brief Gets the value of an object in storage, by handle. +* +* Port-specific file access for cryptographic information. +* +* This call dynamically allocates the buffer which object value +* data is copied into. PKCS11PSAGetObjectValueCleanup() +* should be called after each use to free the dynamically allocated +* buffer. +* +* @sa PKCS11PSAGetObjectValueCleanup +* +* @param[in] pcFileName The name of the file to be read. +* @param[out] ppucData Pointer to buffer for file data. +* @param[out] pulDataSize Size (in bytes) of data located in file. +* @param[out] pIsPrivate Boolean indicating if value is private (CK_TRUE) +* or exportable (CK_FALSE) +* +* @return CKR_OK if operation was successful. CKR_KEY_HANDLE_INVALID if +* no such object handle was found, CKR_DEVICE_MEMORY if memory for +* buffer could not be allocated, CKR_FUNCTION_FAILED for device driver +* error. +*/ +CK_RV PKCS11PSAGetObjectValue( CK_OBJECT_HANDLE xHandle, + uint8_t * ppucData, + size_t * pulDataSize, + CK_BBOOL * pIsPrivate ); + +/** +* @brief Cleanup after PKCS11PSAGetObjectValue(). +* +* @param[in] pucData The buffer to free. +* (*ppucData from PKCS11PSAGetObjectValue()) +* @param[in] ulDataSize The length of the buffer to free. +* (*pulDataSize from PKCS11PSAGetObjectValue()) +*/ +void PKCS11PSAGetObjectValueCleanup( uint8_t * pucData, uint32_t ulDataSize ); + +/** +* @brief Import an object into P11KeyConfig. +* +* @param[in] pLableValue The lable of the object. +* +* @param[in] ulLableLen The length of the object label. +* +* @param[in] uxKeyHandle The key handle. +* +*/ +void PKCS11PSAContextImportObject( CK_VOID_PTR pLableValue, + CK_LONG ulLableLen, + psa_key_handle_t uxKeyHandle ); + +/** +* @brief Close or remove an object from PSA and update P11KeyConfig accordingly. +* +* @param[in] pLableValue The lable of the object. +* +* @param[in] ulLableLen The length of the object label. +* +* @param[in] permanent Destroy the key or just close the key. +* +*/ +CK_RV PKCS11PSARemoveObject(uint8_t * pcLable, size_t xLabelLength, bool permanent); + +/** +* @brief Get the PSA key handle by the object label. +* +* @param[in] pLableValue The lable of the object. +* +* @param[in] ulLableLen The length of the object label. +* +* @param[in] uxKeyHandle The returned key handle. +* +*/ +CK_RV PKCS11PSAGetKeyHandle( uint8_t * pcLable, size_t xLabelLength, psa_key_handle_t * uxKeyHandle ); + +#endif /* __IOT_PKCS11_PSA_OBJECT_MANAGEMENT_H__ */ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network.h b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network.h new file mode 100644 index 0000000..ad41fc8 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network.h @@ -0,0 +1,343 @@ +/* + * FreeRTOS Platform V1.1.3 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_network.h + * @brief Abstraction of network functions used by libraries in this SDK. + */ + +#ifndef IOT_NETWORK_H_ +#define IOT_NETWORK_H_ + +/* Standard includes. */ +#include +#include +#include + +/** + * @ingroup platform_datatypes_enums + * @brief Return codes for [network functions](@ref platform_network_functions). + */ +typedef enum IotNetworkError +{ + IOT_NETWORK_SUCCESS = 0, /**< Function successfully completed. */ + IOT_NETWORK_FAILURE, /**< Generic failure not covered by other values. */ + IOT_NETWORK_BAD_PARAMETER, /**< At least one parameter was invalid. */ + IOT_NETWORK_NO_MEMORY, /**< Memory allocation failed. */ + IOT_NETWORK_SYSTEM_ERROR /**< An error occurred when calling a system API. */ +} IotNetworkError_t; + +/** + * @page platform_network_functions Networking + * @brief Functions of the network abstraction component. + * + * The network abstraction component does not declare functions, but uses function + * pointers instead. This allows multiple network stacks to be used at the same time. + * Libraries that require the network will request an #IotNetworkInterface_t + * parameter. The members of the #IotNetworkInterface_t will be called whenever + * the library interacts with the network. + * + * The following function pointers are associated with an #IotNetworkInterface_t. + * Together, they represent a network stack. + * - @function_name{platform_network_function_create} + * @function_brief{platform_network_function_create} + * - @function_name{platform_network_function_setreceivecallback} + * @function_brief{platform_network_function_setreceivecallback} + * - @function_name{platform_network_function_send} + * @function_brief{platform_network_function_send} + * - @function_name{platform_network_function_receive} + * @function_brief{platform_network_function_receive} + * - @function_name{platform_network_function_receiveupto} + * @function_brief{platform_network_function_receiveupto} + * - @function_name{platform_network_function_close} + * @function_brief{platform_network_function_close} + * - @function_name{platform_network_function_destroy} + * @function_brief{platform_network_function_destroy} + * - @function_name{platform_network_function_receivecallback} + * @function_brief{platform_network_function_receivecallback} + */ + +/** + * @function_page{IotNetworkInterface_t::create,platform_network,create} + * @function_snippet{platform_network,create,this} + * @copydoc IotNetworkInterface_t::create + * @function_page{IotNetworkInterface_t::setReceiveCallback,platform_network,setreceivecallback} + * @function_snippet{platform_network,setreceivecallback,this} + * @copydoc IotNetworkInterface_t::setReceiveCallback + * @function_page{IotNetworkInterface_t::send,platform_network,send} + * @function_snippet{platform_network,send,this} + * @copydoc IotNetworkInterface_t::send + * @function_page{IotNetworkInterface_t::receive,platform_network,receive} + * @function_snippet{platform_network,receive,this} + * @copydoc IotNetworkInterface_t::receive + * @function_page{IotNetworkInterface_t::receiveUpto,platform_network,receiveupto} + * @function_snippet{platform_network,receiveupto,this} + * @copydoc IotNetworkInterface_t::receiveUpto + * @function_page{IotNetworkInterface_t::close,platform_network,close} + * @function_snippet{platform_network,close,this} + * @copydoc IotNetworkInterface_t::close + * @function_page{IotNetworkInterface_t::destroy,platform_network,destroy} + * @function_snippet{platform_network,destroy,this} + * @copydoc IotNetworkInterface_t::destroy + * @function_page{IotNetworkReceiveCallback_t,platform_network,receivecallback} + * @function_snippet{platform_network,receivecallback,this} + * @copydoc IotNetworkReceiveCallback_t + */ + +/** + * @brief Provide an asynchronous notification of incoming network data. + * + * A function with this signature may be set with @ref platform_network_function_setreceivecallback + * to be invoked when data is available on the network. + * + * @param[in] pConnection The connection on which data is available, defined by + * the network stack. + * @param[in] pContext The third argument passed to @ref platform_network_function_setreceivecallback. + */ +/* @[declare_platform_network_receivecallback] */ +typedef void ( * IotNetworkReceiveCallback_t )( void * pConnection, + void * pContext ); +/* @[declare_platform_network_receivecallback] */ + +/** + * @ingroup platform_datatypes_paramstructs + * @brief Represents the functions of a network stack. + * + * Functions that match these signatures should be implemented against a system's + * network stack. See the `platform` directory for existing implementations. + */ +typedef struct IotNetworkInterface +{ + /** + * @brief Create a new network connection. + * + * This function allocates resources and establishes a new network connection. + * @param[in] pConnectionInfo Represents information needed to set up the + * new connection, defined by the network stack. + * @param[in] pCredentialInfo Represents information needed to secure the + * new connection, defined by the network stack. + * @param[out] pConnection Set to represent a new connection, defined by the + * network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + */ + /* @[declare_platform_network_create] */ + IotNetworkError_t ( * create )( void * pConnectionInfo, + void * pCredentialInfo, + void ** pConnection ); + /* @[declare_platform_network_create] */ + + /** + * @brief Register an @ref platform_network_function_receivecallback. + * + * Sets an @ref platform_network_function_receivecallback to be called + * asynchronously when data arrives on the network. The network stack + * should invoke this function "as if" it were the thread routine of a + * detached thread. + * + * Each network connection may only have one receive callback at any time. + * @ref platform_network_function_close is expected to remove any active + * receive callbacks. + * + * @param[in] pConnection The connection to associate with the receive callback. + * @param[in] receiveCallback The function to invoke for incoming network data. + * @param[in] pContext A value to pass as the first parameter to the receive callback. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @see platform_network_function_receivecallback + */ + /* @[declare_platform_network_setreceivecallback] */ + IotNetworkError_t ( * setReceiveCallback )( void * pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ); + /* @[declare_platform_network_setreceivecallback] */ + + /** + * @brief Send data over a return connection. + * + * Attempts to transmit `messageLength` bytes of `pMessage` across the + * connection represented by `pConnection`. Returns the number of bytes + * actually sent, `0` on failure. + * + * @param[in] pConnection The connection used to send data, defined by the + * network stack. + * @param[in] pMessage The message to send. + * @param[in] messageLength The length of `pMessage`. + * + * @return The number of bytes successfully sent, `0` on failure. + */ + /* @[declare_platform_network_send] */ + size_t ( * send )( void * pConnection, + const uint8_t * pMessage, + size_t messageLength ); + /* @[declare_platform_network_send] */ + + /** + * @brief Block and wait for incoming network data. + * + * Wait for a message of size `bytesRequested` to arrive on the network and + * place it in `pBuffer`. + * + * @param[in] pConnection The connection to wait on, defined by the network + * stack. + * @param[out] pBuffer Where to place the incoming network data. This buffer + * must be at least `bytesRequested` in size. + * @param[in] bytesRequested How many bytes to wait for. `pBuffer` must be at + * least this size. + * + * @return The number of bytes successfully received. This MUST be + * `bytesRequested` when successful. Any other value may indicate an error. + */ + /* @[declare_platform_network_receive] */ + size_t ( * receive )( void * pConnection, + uint8_t * pBuffer, + size_t bytesRequested ); + /* @[declare_platform_network_receive] */ + + /** + * @brief Read incoming data available in the network buffers. + * + * Reads bytes available in the network buffers into `pBuffer`. + * - If there is less data available than requested, it will return + * the available number of bytes. + * - If there is more data available than requested, it will fill the + * whole `pBuffer`. + * - If there is no data available, it will return 0. + * + * @param[in] pConnection The connection to receive data on, defined by + * the network stack. + * @param[out] pBuffer The buffer to place the incoming network data. + * @param[in] bufferSize The size of `pBuffer`. + * + * @return The number of bytes successfully received. + */ + /* @[declare_platform_network_receiveupto] */ + size_t ( * receiveUpto )( void * pConnection, + uint8_t * pBuffer, + size_t bufferSize ); + /* @[declare_platform_network_receiveupto] */ + + /** + * @brief Close a network connection. + * + * This function closes the connection, but does not release the resources + * used by the connection. This allows calls to other networking functions + * to return an error and handle a closed connection without the risk of + * crashing. Once it can be guaranteed that `pConnection` will no longer be + * used, the connection can be destroyed with @ref platform_network_function_destroy. + * + * In addition to closing the connection, this function SHOULD also remove + * any active [receive callback](@ref platform_network_function_receivecallback). + * + * @param[in] pConnection The network connection to close, defined by the + * network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @note It MUST be safe to call this function on an already-closed connection. + */ + /* @[declare_platform_network_close] */ + IotNetworkError_t ( * close )( void * pConnection ); + /* @[declare_platform_network_close] */ + + /** + * @brief Free resources used by a network connection. + * + * This function releases the resources of a closed connection. It MUST be + * called after @ref platform_network_function_close. + * + * @param[in] pConnection The network connection to destroy, defined by + * the network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @attention No function MAY be called on the network connection after + * calling this function. This function MUST be safe to call from a + * [receive callback](@ref platform_network_function_receivecallback). + */ + /* @[declare_platform_network_destroy] */ + IotNetworkError_t ( * destroy )( void * pConnection ); + /* @[declare_platform_network_destroy] */ +} IotNetworkInterface_t; + +/** + * @ingroup platform_datatypes_paramstructs + * @brief Information on the remote server for connection setup. + * + * May be passed to #IotNetworkInterface_t.create as `pConnectionInfo`. This + * structure contains commonly-used parameters, but may be replaced with an + * alternative. + */ +typedef struct IotNetworkServerInfo +{ + const char * pHostName; /**< @brief Server host name. Must be NULL-terminated. */ + uint16_t port; /**< @brief Server port in host-order. */ +} IotNetworkServerInfo_t; + +/** + * @ingroup platform_datatypes_paramstructs + * @brief Contains the credentials necessary for connection setup. + * + * May be passed to #IotNetworkInterface_t.create as `pCredentialInfo`. This + * structure contains commonly-used parameters, but may be replaced with an + * alternative. + */ +typedef struct IotNetworkCredentials +{ + /** + * @brief Set this to a non-NULL value to use ALPN. + * + * This string must be NULL-terminated. + * + * See [this link] + * (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/) + * for more information. + */ + const char * pAlpnProtos; + + /** + * @brief Set this to a non-zero value to use TLS max fragment length + * negotiation (TLS MFLN). + * + * @note The network stack may have a minimum value for this parameter and + * may return an error if this parameter is too small. + */ + size_t maxFragmentLength; + + /** + * @brief Disable server name indication (SNI) for a TLS session. + */ + bool disableSni; + + const char * pRootCa; /**< @brief String representing a trusted server root certificate. */ + size_t rootCaSize; /**< @brief Size associated with #IotNetworkCredentials_t.pRootCa. */ + const char * pClientCert; /**< @brief String representing the client certificate. */ + size_t clientCertSize; /**< @brief Size associated with #IotNetworkCredentials_t.pClientCert. */ + const char * pPrivateKey; /**< @brief String representing the client certificate's private key. */ + size_t privateKeySize; /**< @brief Size associated with #IotNetworkCredentials_t.pPrivateKey. */ +} IotNetworkCredentials_t; + +#endif /* ifndef IOT_NETWORK_H_ */ diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/JSON_Validate_harness.c b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_ble.h similarity index 63% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/JSON_Validate_harness.c rename to bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_ble.h index 5746281..dcb294a 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/proofs/JSON_Validate/JSON_Validate_harness.c +++ b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_ble.h @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * FreeRTOS Platform V1.1.2 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -18,31 +18,33 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org */ /** - * @file JSON_Validate_harness.c - * @brief Implements the proof harness for the JSON_Validate function. + * @file iot_network_BLE.h + * @brief Declares the network stack functions specified in aws_iot_network.h for + * Bluetooth Low Energy. */ -#include -#include "core_json_annex.h" - -void harness() -{ - char * buf = NULL; - size_t max; - JSONStatus_t ret; +#ifndef _IOT_NETWORK_BLE_H_ +#define _IOT_NETWORK_BLE_H_ - /* max is the buffer length which must not exceed unwindings. */ - __CPROVER_assume( max < CBMC_MAX_BUFSIZE ); +/* Standard includes. */ +#include +#include "platform/iot_network.h" - if( nondet_bool() ) - { - buf = malloc( max ); - } +/** + * @brief Provides a pointer to an #IotNetworkInterface_t that uses the functions + * declared in this file. + */ +#define IOT_NETWORK_INTERFACE_BLE ( &( IotNetworkBle ) ) - ret = JSON_Validate( buf, max ); +/** + * @brief Declaration of network interface for BLE. + */ +extern const IotNetworkInterface_t IotNetworkBle; - __CPROVER_assert( jsonValidateEnum( ret ), "The return value is a subset of JSONStatus_t." ); -} +#endif /* ifndef _IOT_NETWORK_BLE_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_freertos.h b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_freertos.h new file mode 100644 index 0000000..9df0f3c --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_network_freertos.h @@ -0,0 +1,183 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_network_freertos.h + * @brief Declares the network stack functions specified in aws_iot_network.h for + * FreeRTOS Secure Sockets. + */ + +#ifndef _IOT_NETWORK_AFR_H_ +#define _IOT_NETWORK_AFR_H_ + +/* Standard includes. */ +#include + +/* Platform network include. */ +#include "platform/iot_network.h" + +/* FreeRTOS Secure Sockets include. */ +#include "iot_secure_sockets.h" + +/* Credentials include. */ +#include "aws_clientcredential.h" +#include "aws_clientcredential_keys.h" + +/** + * @brief Provides a default value for an #IotNetworkConnectionAfr_t. + * + * All instances of #IotNetworkConnectionAfr_t should be initialized with + * this constant. + * + * @warning Failing to initialize an #IotNetworkConnectionAfr_t with this + * initializer may result in undefined behavior! + * @note This initializer may change at any time in future versions, but its + * name will remain the same. + */ +#define IOT_NETWORK_CONNECTION_AFR_INITIALIZER { 0 } + +/** + * @brief Generic initializer for an #IotNetworkServerInfo_t. + * + * @note This initializer may change at any time in future versions, but its + * name will remain the same. + */ +#define IOT_NETWORK_SERVER_INFO_AFR_INITIALIZER { 0 } + +/** + * @brief Initialize an #IotNetworkServerInfo_t for use with AWS IoT. + * + * @note This initializer may change at any time in future versions, but its + * name will remain the same. + */ +#define AWS_IOT_NETWORK_SERVER_INFO_AFR_INITIALIZER \ + { \ + .pHostName = clientcredentialMQTT_BROKER_ENDPOINT, \ + .port = clientcredentialMQTT_BROKER_PORT \ + } + +/** + * @brief Generic initializer for an #IotNetworkCredentials_t. + * + * @note This initializer may change at any time in future versions, but its + * name will remain the same. + */ +#define IOT_NETWORK_CREDENTIALS_AFR_INITIALIZER { 0 } + +/** + * @brief Initialize an #IotNetworkCredentials_t for use with AWS IoT. + * + * @note This initializer may change at any time in future versions, but its + * name will remain the same. + */ +#define AWS_IOT_NETWORK_CREDENTIALS_AFR_INITIALIZER \ + { \ + .pAlpnProtos = socketsAWS_IOT_ALPN_MQTT, \ + .maxFragmentLength = 0, \ + .disableSni = false, \ + .pRootCa = NULL, \ + .rootCaSize = 0, \ + .pClientCert = keyCLIENT_CERTIFICATE_PEM, \ + .clientCertSize = sizeof( keyCLIENT_CERTIFICATE_PEM ), \ + .pPrivateKey = keyCLIENT_PRIVATE_KEY_PEM, \ + .privateKeySize = sizeof( keyCLIENT_PRIVATE_KEY_PEM ) \ + } + +/** + * @brief Provides a pointer to an #IotNetworkInterface_t that uses the functions + * declared in this file. + */ +#define IOT_NETWORK_INTERFACE_AFR ( &( IotNetworkAfr ) ) + +/** + * @brief Represents a network connection that uses FreeRTOS Secure Sockets. + * + * This is an incomplete type. In application code, only pointers to this type + * should be used. + */ +typedef void IotNetworkConnectionAfr_t; + +/** + * @brief An implementation of #IotNetworkInterface_t::create for FreeRTOS + * Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_Create( void * pConnectionInfo, + void * pCredentialInfo, + void ** const pConnection ); + +/** + * @brief An implementation of #IotNetworkInterface_t::setReceiveCallback for + * FreeRTOS Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_SetReceiveCallback( void * pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ); + +/** + * @brief An implementation of #IotNetworkInterface_t::send for FreeRTOS + * Secure Sockets. + */ +size_t IotNetworkAfr_Send( void * pConnection, + const uint8_t * pMessage, + size_t messageLength ); + +/** + * @brief An implementation of #IotNetworkInterface_t::receive for FreeRTOS + * Secure Sockets. + */ +size_t IotNetworkAfr_Receive( void * pConnection, + uint8_t * pBuffer, + size_t bytesRequested ); + +/** + * @brief An implementation of #IotNetworkInterface_t::receiveUpto for FreeRTOS + * Secure Sockets. + */ +size_t IotNetworkAfr_ReceiveUpto( void * pConnection, + uint8_t * pBuffer, + size_t bufferSize ); + +/** + * @brief An implementation of #IotNetworkInterface_t::close for FreeRTOS + * Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_Close( void * pConnection ); + +/** + * @brief An implementation of #IotNetworkInterface_t::destroy for FreeRTOS + * Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_Destroy( void * pConnection ); + +/** + * @cond DOXYGEN_IGNORE + * Doxygen should ignore this section. + * + * Declaration of a network interface struct using the functions in this file. + */ +extern const IotNetworkInterface_t IotNetworkAfr; +/** @endcond */ + +#endif /* ifndef _IOT_NETWORK_AFR_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_platform_types_freertos.h b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_platform_types_freertos.h new file mode 100644 index 0000000..0dd8bab --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/include/platform/iot_platform_types_freertos.h @@ -0,0 +1,84 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_platform_types_posix.h + * @brief Definitions of platform layer types on POSIX systems. + */ + +#ifndef _IOT_PLATFORM_TYPES_AFR_H_ +#define _IOT_PLATFORM_TYPES_AFR_H_ + +#include "timers.h" + +typedef struct iot_mutex_internal +{ + StaticSemaphore_t xMutex; /**< FreeRTOS mutex. */ + BaseType_t recursive; /**< Type; used for indicating if this is reentrant or normal. */ +} iot_mutex_internal_t; + +/** + * @brief The native mutex type on AFR systems. + */ +typedef iot_mutex_internal_t _IotSystemMutex_t; + +typedef struct iot_sem_internal +{ + StaticSemaphore_t xSemaphore; /**< FreeRTOS semaphore. */ +} iot_sem_internal_t; + +/** + * @brief The native semaphore type on AFR systems. + */ +typedef iot_sem_internal_t _IotSystemSemaphore_t; + +/** + * @brief Holds information about an active detached thread so that we can + * delete the FreeRTOS task when it completes + */ +typedef struct threadInfo +{ + void * pArgument; /**< @brief Argument to `threadRoutine`. */ + void ( * threadRoutine )( void * ); /**< @brief Thread function to run. */ +} threadInfo_t; + +/** + * @brief Holds information about an active timer. + */ +typedef struct timerInfo +{ + TimerHandle_t timer; /**< @brief Underlying timer. */ + void ( * threadRoutine )( void * ); /**< @brief Thread function to run on timer expiration. */ + void * pArgument; /**< @brief First argument to threadRoutine. */ + StaticTimer_t xTimerBuffer; /**< Memory that holds the FreeRTOS timer. */ + TickType_t xTimerPeriod; /**< Period of this timer. */ +} timerInfo_t; + +/** + * @brief Represents an #IotTimer_t on AFR systems. + */ +typedef timerInfo_t _IotSystemTimer_t; + +#endif /* ifndef _IOT_PLATFORM_TYPES_POSIX_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/iot_clock_freertos.c b/bsp/aws_libraries/abstractions/platform/freertos/iot_clock_freertos.c new file mode 100644 index 0000000..ab2f3c7 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/iot_clock_freertos.c @@ -0,0 +1,224 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_clock_freertos.c + * @brief Implementation of the functions in iot_clock.h for FreeRTOS systems. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include + +/* Platform clock include. */ +#include "platform/iot_platform_types_freertos.h" +#include "platform/iot_clock.h" +#include "task.h" + +/* Configure logs for the functions in this file. */ +#ifdef IOT_LOG_LEVEL_PLATFORM + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM +#else + #ifdef IOT_LOG_LEVEL_GLOBAL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL + #else + #define LIBRARY_LOG_LEVEL IOT_LOG_NONE + #endif +#endif + +#define LIBRARY_LOG_NAME ( "CLOCK" ) +#include "iot_logging_setup.h" + +/*-----------------------------------------------------------*/ + +/* + * Time conversion constants. + */ +#define _MILLISECONDS_PER_SECOND ( 1000 ) /**< @brief Milliseconds per second. */ +#define _MILLISECONDS_PER_TICK ( _MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) /**< Milliseconds per FreeRTOS tick. */ + +/*-----------------------------------------------------------*/ + +/* Private Callback function for timer expiry, delegate work to a Task to free + * up the timer task for managing other timers */ +static void prvTimerCallback( TimerHandle_t xTimerHandle ) +{ + _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pvTimerGetTimerID( xTimerHandle ); + + /* The value of the timer ID, set in timer_create, should not be NULL. */ + configASSERT( pxTimer != NULL ); + + /* Restart the timer if it is periodic. */ + if( pxTimer->xTimerPeriod > 0 ) + { + xTimerChangePeriod( xTimerHandle, pxTimer->xTimerPeriod, 0 ); + } + + /* Call timer Callback from this task */ + pxTimer->threadRoutine( ( void * ) pxTimer->pArgument ); +} + +/*-----------------------------------------------------------*/ + +bool IotClock_GetTimestring( char * pBuffer, + size_t bufferSize, + size_t * pTimestringLength ) +{ + uint64_t milliSeconds = IotClock_GetTimeMs(); + int timestringLength = 0; + + configASSERT( pBuffer != NULL ); + configASSERT( pTimestringLength != NULL ); + + /* Convert the localTime struct to a string. */ + timestringLength = snprintf( pBuffer, bufferSize, "%llu", milliSeconds ); + + /* Check for error from no string */ + if( timestringLength == 0 ) + { + return false; + } + + /* Set the output parameter. */ + *pTimestringLength = timestringLength; + + return true; +} + +/*-----------------------------------------------------------*/ + +uint64_t IotClock_GetTimeMs( void ) +{ + TimeOut_t xCurrentTime = { 0 }; + + /* This must be unsigned because the behavior of signed integer overflow is undefined. */ + uint64_t ullTickCount = 0ULL; + + /* Get the current tick count and overflow count. vTaskSetTimeOutState() + * is used to get these values because they are both static in tasks.c. */ + vTaskSetTimeOutState( &xCurrentTime ); + + /* Adjust the tick count for the number of times a TickType_t has overflowed. */ + ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << ( sizeof( TickType_t ) * 8 ); + + /* Add the current tick count. */ + ullTickCount += xCurrentTime.xTimeOnEntering; + + /* Return the ticks converted to Milliseconds */ + return ullTickCount * _MILLISECONDS_PER_TICK; +} +/*-----------------------------------------------------------*/ + +void IotClock_SleepMs( uint32_t sleepTimeMs ) +{ + vTaskDelay( pdMS_TO_TICKS( sleepTimeMs ) ); +} + +/*-----------------------------------------------------------*/ + +bool IotClock_TimerCreate( IotTimer_t * pNewTimer, + IotThreadRoutine_t expirationRoutine, + void * pArgument ) +{ + _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pNewTimer; + + configASSERT( pNewTimer != NULL ); + configASSERT( expirationRoutine != NULL ); + + IotLogDebug( "Creating new timer %p.", pNewTimer ); + + /* Set the timer expiration routine, argument and period */ + pxTimer->threadRoutine = expirationRoutine; + pxTimer->pArgument = pArgument; + pxTimer->xTimerPeriod = 0; + + /* Create a new FreeRTOS timer. This call will not fail because the + * memory for it has already been allocated, so the output parameter is + * also set. */ + pxTimer->timer = ( TimerHandle_t ) xTimerCreateStatic( "timer", /* Timer name. */ + portMAX_DELAY, /* Initial timer period. Timers are created disarmed. */ + pdFALSE, /* Don't auto-reload timer. */ + ( void * ) pxTimer, /* Timer id. */ + prvTimerCallback, /* Timer expiration callback. */ + &pxTimer->xTimerBuffer ); /* Pre-allocated memory for timer. */ + + return true; +} + +/*-----------------------------------------------------------*/ + +void IotClock_TimerDestroy( IotTimer_t * pTimer ) +{ + _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer; + + configASSERT( pTimerInfo != NULL ); + configASSERT( pTimerInfo->timer != NULL ); + + IotLogDebug( "Destroying timer %p.", pTimer ); + + if( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE ) + { + /* Stop the FreeRTOS timer. Because the timer is statically allocated, no call + * to xTimerDelete is necessary. The timer is stopped so that it's not referenced + * anywhere. xTimerStop will not fail when it has unlimited block time. */ + ( void ) xTimerStop( pTimerInfo->timer, portMAX_DELAY ); + + /* Wait until the timer stop command is processed. */ + while( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE ) + { + vTaskDelay( 1 ); + } + } +} + +/*-----------------------------------------------------------*/ + +bool IotClock_TimerArm( IotTimer_t * pTimer, + uint32_t relativeTimeoutMs, + uint32_t periodMs ) +{ + _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer; + + configASSERT( pTimerInfo != NULL ); + + TimerHandle_t xTimerHandle = pTimerInfo->timer; + + IotLogDebug( "Arming timer %p with timeout %llu and period %llu.", + pTimer, + relativeTimeoutMs, + periodMs ); + + /* Set the timer period in ticks */ + pTimerInfo->xTimerPeriod = pdMS_TO_TICKS( periodMs ); + + /* Set the timer to expire after relativeTimeoutMs, and restart it. */ + ( void ) xTimerChangePeriod( xTimerHandle, pdMS_TO_TICKS( relativeTimeoutMs ), portMAX_DELAY ); + + return true; +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/iot_metrics.c b/bsp/aws_libraries/abstractions/platform/freertos/iot_metrics.c new file mode 100644 index 0000000..f83ae57 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/iot_metrics.c @@ -0,0 +1,230 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/* + * The implementation is FreeRTOS specific. It depends on aws_secure_sockets library. + */ + +/* Define _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE to prevent secure sockets functions + * from redefining in iot_secure_sockets_wrapper_metrics.h */ +#define _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include + +/* Metrics include. */ +#include "platform/iot_metrics.h" + +/* Platform threads include. */ +#include "platform/iot_threads.h" + +/* Secure sockets include. */ +#include "iot_secure_sockets.h" + +#undef _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE + +#if AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED == 1 + +/** + * @brief Used to match metrics connection records by network connection. + * + * @param[in] pConnectionLink Pointer to a metrics connection record's link element. + * @param[in] pContext The network connection to match. + * + * @return `true` if the given metrics connection record matches the given + * network connection; `false` otherwise. + */ + static bool _connectionMatch( const IotLink_t * pConnectionLink, + void * pContext ); + + static void _metricsAddTcpConnection( Socket_t xSocket, + SocketsSockaddr_t * pxAddress ); + +/*------------------- Global Variables ------------------------*/ + +/** + * @brief Holds a list of active TCP connections. + */ + static IotListDouble_t _connectionList = IOT_LIST_DOUBLE_INITIALIZER; + +/** + * @brief Protects #_connectionList from concurrent access. + */ + static IotMutex_t _connectionListMutex; + +/*-----------------------------------------------------------*/ + + static bool _connectionMatch( const IotLink_t * pConnectionLink, + void * pContext ) + { + /* Retrieve the pointer the the TCP connection record. The given link + * pointer is never NULL. */ + IotMetricsTcpConnection_t * pTcpConnection = IotLink_Container( IotMetricsTcpConnection_t, + pConnectionLink, + link ); + + return( pTcpConnection->pNetworkContext == pContext ); + } + +/*-----------------------------------------------------------*/ + + bool IotMetrics_Init( void ) + { + IotListDouble_Create( &_connectionList ); + + return IotMutex_Create( &_connectionListMutex, false ); + } + +/*-----------------------------------------------------------*/ + + void IotMetrics_Cleanup( void ) + { + IotMutex_Destroy( &_connectionListMutex ); + } + +/*-----------------------------------------------------------*/ + + void IotMetrics_GetTcpConnections( void * pContext, + void ( * metricsCallback )( void *, const IotListDouble_t * ) ) + { + /* Provide the connection list. Ensure that it is not modified elsewhere by + * locking the connection list mutex. */ + IotMutex_Lock( &_connectionListMutex ); + metricsCallback( pContext, &_connectionList ); + IotMutex_Unlock( &_connectionListMutex ); + } + +/*-----------------------------------------------------------*/ + + static void _metricsAddTcpConnection( Socket_t xSocket, + SocketsSockaddr_t * pxAddress ) + { + IotMetricsTcpConnection_t * pTcpConnection = NULL; + void * pSocketContext = ( void * ) xSocket; + + IotMutex_Lock( &_connectionListMutex ); + + /* Only add if it doesn't exist in the _connectionList. */ + if( IotListDouble_FindFirstMatch( &_connectionList, + NULL, + _connectionMatch, + pSocketContext ) == NULL ) + { + /* Allocate memory for a new metrics connection. */ + pTcpConnection = IotMetrics_MallocTcpConnection( sizeof( IotMetricsTcpConnection_t ) ); + + if( pTcpConnection != NULL ) + { + ( void ) memset( pTcpConnection, 0x00, sizeof( IotMetricsTcpConnection_t ) ); + + pTcpConnection->pNetworkContext = pSocketContext; + + /* Convert IP to string. */ + SOCKETS_inet_ntoa( pxAddress->ulAddress, pTcpConnection->pRemoteAddress ); + + /* Formatting. */ + sprintf( pTcpConnection->pRemoteAddress + strlen( pTcpConnection->pRemoteAddress ), ":%d", SOCKETS_ntohs( pxAddress->usPort ) ); + + pTcpConnection->addressLength = strlen( pTcpConnection->pRemoteAddress ); + + /* Insert to the list. */ + IotListDouble_InsertTail( &_connectionList, &( pTcpConnection->link ) ); + } + } + + IotMutex_Unlock( &_connectionListMutex ); + } + +/*-----------------------------------------------------------*/ + + static void _metricsRemoveTcpConnection( Socket_t xSocket ) + { + IotMutex_Lock( &_connectionListMutex ); + + IotLink_t * pFoundConnectionLink = IotListDouble_RemoveFirstMatch( &_connectionList, + NULL, + _connectionMatch, + ( void * ) xSocket ); + + if( pFoundConnectionLink != NULL ) + { + IotMetricsTcpConnection_t * pFoundTcpConnection = IotLink_Container( IotMetricsTcpConnection_t, pFoundConnectionLink, link ); + + IotMetrics_FreeTcpConnection( pFoundTcpConnection ); + } + + IotMutex_Unlock( &_connectionListMutex ); + } + +/*-----------------------------------------------------------*/ + + BaseType_t Sockets_MetricsInit( void ) + { + BaseType_t result = SOCKETS_Init(); + + if( result == pdTRUE ) + { + result = IotMetrics_Init() ? pdTRUE : pdFALSE; + } + + return result; + } + +/*-----------------------------------------------------------*/ + + int32_t Sockets_MetricsConnect( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ) + { + int32_t result = SOCKETS_Connect( xSocket, pxAddress, xAddressLength ); + + if( result == SOCKETS_ERROR_NONE ) + { + _metricsAddTcpConnection( xSocket, pxAddress ); + } + + return result; + } + +/*-----------------------------------------------------------*/ + + int32_t Sockets_MetricsShutdown( Socket_t xSocket, + uint32_t ulHow ) + { + int32_t result = SOCKETS_Shutdown( xSocket, ulHow ); + + if( result == SOCKETS_ERROR_NONE ) + { + _metricsRemoveTcpConnection( xSocket ); + } + + return result; + } + +#endif /* ifdef AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED */ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/iot_network_freertos.c b/bsp/aws_libraries/abstractions/platform/freertos/iot_network_freertos.c new file mode 100644 index 0000000..61b4255 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/iot_network_freertos.c @@ -0,0 +1,716 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_network_freertos.c + * @brief Implementation of the network-related functions from iot_network_freertos.h + * for FreeRTOS secure sockets. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include + +/* FreeRTOS includes. */ +#include "semphr.h" +#include "event_groups.h" + +/* Error handling include. */ +#include "private/iot_error.h" + +/* FreeRTOS network include. */ +#include "platform/iot_network_freertos.h" + +/* Configure logs for the functions in this file. */ +#ifdef IOT_LOG_LEVEL_NETWORK + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_NETWORK +#else + #ifdef IOT_LOG_LEVEL_GLOBAL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL + #else + #define LIBRARY_LOG_LEVEL IOT_LOG_NONE + #endif +#endif + +#define LIBRARY_LOG_NAME ( "NET" ) +#include "iot_logging_setup.h" + +/* Provide a default value for the number of milliseconds for a socket poll. + * This is a temporary workaround to deal with the lack of poll(). */ +#ifndef IOT_NETWORK_SOCKET_POLL_MS + #define IOT_NETWORK_SOCKET_POLL_MS ( 1000 ) +#endif + +/** + * @brief The event group bit to set when a connection's socket is shut down. + */ +#define _FLAG_SHUTDOWN ( 1 ) + +/** + * @brief The event group bit to set when a connection's receive task exits. + */ +#define _FLAG_RECEIVE_TASK_EXITED ( 2 ) + +/** + * @brief The event group bit to set when the connection is destroyed from the + * receive task. + */ +#define _FLAG_RECEIVE_TASK_CONNECTION_DESTROYED ( 4 ) + +/*-----------------------------------------------------------*/ + +typedef struct _networkConnection +{ + Socket_t socket; /**< @brief FreeRTOS Secure Sockets handle. */ + StaticSemaphore_t socketMutex; /**< @brief Prevents concurrent threads from sending on a socket. */ + StaticEventGroup_t connectionFlags; /**< @brief Synchronizes with the receive task. */ + TaskHandle_t receiveTask; /**< @brief Handle of the receive task, if any. */ + IotNetworkReceiveCallback_t receiveCallback; /**< @brief Network receive callback, if any. */ + void * pReceiveContext; /**< @brief The context for the receive callback. */ + bool bufferedByteValid; /**< @brief Used to determine if the buffered byte is valid. */ + uint8_t bufferedByte; /**< @brief A single byte buffered from a receive, since FreeRTOS Secure Sockets does not have poll(). */ +} _networkConnection_t; + +/*-----------------------------------------------------------*/ + +/** + * @brief An #IotNetworkInterface_t that uses the functions in this file. + */ +const IotNetworkInterface_t IotNetworkAfr = +{ + .create = IotNetworkAfr_Create, + .setReceiveCallback = IotNetworkAfr_SetReceiveCallback, + .send = IotNetworkAfr_Send, + .receive = IotNetworkAfr_Receive, + .receiveUpto = IotNetworkAfr_ReceiveUpto, + .close = IotNetworkAfr_Close, + .destroy = IotNetworkAfr_Destroy +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Destroys a network connection. + * + * @param[in] pNetworkConnection The connection to destroy. + */ +static void _destroyConnection( _networkConnection_t * pNetworkConnection ) +{ + /* Call Secure Sockets close function to free resources. */ + int32_t socketStatus = SOCKETS_Close( pNetworkConnection->socket ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogWarn( "Failed to destroy connection." ); + } + + /* Free the network connection. */ + vPortFree( pNetworkConnection ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Task routine that waits on incoming network data. + * + * @param[in] pArgument The network connection. + */ +static void _networkReceiveTask( void * pArgument ) +{ + bool destroyConnection = false; + int32_t socketStatus = 0; + EventBits_t connectionFlags = 0; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = pArgument; + + while( true ) + { + /* No buffered byte should be in the connection. */ + configASSERT( pNetworkConnection->bufferedByteValid == false ); + + /* Block and wait for 1 byte of data. This simulates the behavior of poll(). + * THIS IS A TEMPORARY WORKAROUND AND DOES NOT PROVIDE THREAD-SAFETY AGAINST + * MULTIPLE CALLS OF RECEIVE. */ + do + { + socketStatus = SOCKETS_Recv( pNetworkConnection->socket, + &( pNetworkConnection->bufferedByte ), + 1, + 0 ); + + connectionFlags = xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ); + + if( ( connectionFlags & _FLAG_SHUTDOWN ) == _FLAG_SHUTDOWN ) + { + socketStatus = SOCKETS_ECLOSED; + } + + /* Check for timeout. Some ports return 0, some return EWOULDBLOCK. */ + } while( ( socketStatus == 0 ) || ( socketStatus == SOCKETS_EWOULDBLOCK ) ); + + if( socketStatus <= 0 ) + { + break; + } + + pNetworkConnection->bufferedByteValid = true; + + /* The network receive task is created ONLY when the receive callback is set. Thus, assert + * check that the callback is valid. */ + configASSERT( pNetworkConnection->receiveCallback != NULL ); + + /* Invoke the network callback. */ + pNetworkConnection->receiveCallback( pNetworkConnection, + pNetworkConnection->pReceiveContext ); + + /* Check if the connection was destroyed by the receive callback. This + * does not need to be thread-safe because the destroy connection function + * may only be called once (per its API doc). */ + connectionFlags = xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ); + + /* Break out of receive task loop if connection is closed or destroyed. */ + if( ( connectionFlags & _FLAG_RECEIVE_TASK_CONNECTION_DESTROYED ) == _FLAG_RECEIVE_TASK_CONNECTION_DESTROYED ) + { + destroyConnection = true; + break; + } + else if( ( connectionFlags & _FLAG_SHUTDOWN ) == _FLAG_SHUTDOWN ) + { + break; + } + } + + IotLogDebug( "Network receive task terminating." ); + + /* If necessary, destroy the network connection before exiting. */ + if( destroyConnection == true ) + { + _destroyConnection( pNetworkConnection ); + } + else + { + /* Set the flag to indicate that the receive task has exited. */ + ( void ) xEventGroupSetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_RECEIVE_TASK_EXITED ); + } + + vTaskDelete( NULL ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Set up a secured TLS connection. + * + * @param[in] pAfrCredentials Credentials for the secured connection. + * @param[in] tcpSocket An initialized socket to secure. + * @param[in] pHostName Remote server name for SNI. + * @param[in] hostnameLength The length of `pHostName`. + * + * @return #IOT_NETWORK_SUCCESS or #IOT_NETWORK_SYSTEM_ERROR. + */ +static IotNetworkError_t _tlsSetup( const IotNetworkCredentials_t * pAfrCredentials, + Socket_t tcpSocket, + const char * pHostName, + size_t hostnameLength ) +{ + IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS ); + int32_t socketStatus = SOCKETS_ERROR_NONE; + + /* ALPN options for AWS IoT. */ + const char * ppcALPNProtos[] = { socketsAWS_IOT_ALPN_MQTT }; + + /* Set secured option. */ + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_REQUIRE_TLS, + NULL, + 0 ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set secured option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + /* Set ALPN option. */ + if( pAfrCredentials->pAlpnProtos != NULL ) + { + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_ALPN_PROTOCOLS, + ppcALPNProtos, + sizeof( ppcALPNProtos ) / sizeof( ppcALPNProtos[ 0 ] ) ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set ALPN option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + } + + /* Set SNI option. */ + if( pAfrCredentials->disableSni == false ) + { + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_SERVER_NAME_INDICATION, + pHostName, + hostnameLength + 1 ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set SNI option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + } + + /* Set custom server certificate. */ + if( pAfrCredentials->pRootCa != NULL ) + { + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE, + pAfrCredentials->pRootCa, + pAfrCredentials->rootCaSize ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set server certificate option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + } + + IOT_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_Create( void * pConnectionInfo, + void * pCredentialInfo, + void ** pConnection ) +{ + IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS ); + Socket_t tcpSocket = SOCKETS_INVALID_SOCKET; + int32_t socketStatus = SOCKETS_ERROR_NONE; + SocketsSockaddr_t serverAddress = { 0 }; + EventGroupHandle_t pConnectionFlags = NULL; + SemaphoreHandle_t pConnectionMutex = NULL; + const TickType_t receiveTimeout = pdMS_TO_TICKS( IOT_NETWORK_SOCKET_POLL_MS ); + _networkConnection_t * pNewNetworkConnection = NULL; + + /* Cast function parameters to correct types. */ + const IotNetworkServerInfo_t * pServerInfo = pConnectionInfo; + const IotNetworkCredentials_t * pAfrCredentials = pCredentialInfo; + _networkConnection_t ** pNetworkConnection = ( _networkConnection_t ** ) pConnection; + + /* Check host name length against the maximum length allowed by Secure + * Sockets. */ + const size_t hostnameLength = strlen( pServerInfo->pHostName ); + + if( hostnameLength > ( size_t ) securesocketsMAX_DNS_NAME_LENGTH ) + { + IotLogError( "Host name length exceeds %d, which is the maximum allowed.", + securesocketsMAX_DNS_NAME_LENGTH ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_BAD_PARAMETER ); + } + + pNewNetworkConnection = pvPortMalloc( sizeof( _networkConnection_t ) ); + + if( pNewNetworkConnection == NULL ) + { + IotLogError( "Failed to allocate memory for new network connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_NO_MEMORY ); + } + + /* Clear the connection information. */ + ( void ) memset( pNewNetworkConnection, 0x00, sizeof( _networkConnection_t ) ); + + /* Create a new TCP socket. */ + tcpSocket = SOCKETS_Socket( SOCKETS_AF_INET, + SOCKETS_SOCK_STREAM, + SOCKETS_IPPROTO_TCP ); + + if( tcpSocket == SOCKETS_INVALID_SOCKET ) + { + IotLogError( "Failed to create new socket." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + /* Set up connection encryption if credentials are provided. */ + if( pAfrCredentials != NULL ) + { + status = _tlsSetup( pAfrCredentials, tcpSocket, pServerInfo->pHostName, hostnameLength ); + + if( status != IOT_NETWORK_SUCCESS ) + { + IOT_GOTO_CLEANUP(); + } + } + + /* Establish connection. */ + serverAddress.ucSocketDomain = SOCKETS_AF_INET; + serverAddress.usPort = SOCKETS_htons( pServerInfo->port ); + serverAddress.ulAddress = SOCKETS_GetHostByName( pServerInfo->pHostName ); + + /* Check for errors from DNS lookup. */ + if( serverAddress.ulAddress == 0 ) + { + IotLogError( "Failed to resolve %s.", pServerInfo->pHostName ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + socketStatus = SOCKETS_Connect( tcpSocket, + &serverAddress, + sizeof( SocketsSockaddr_t ) ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to establish new connection. Socket status: %d.", socketStatus ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + /* Set a long timeout for receive. */ + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_RCVTIMEO, + &receiveTimeout, + sizeof( TickType_t ) ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set socket receive timeout. Socket status %d.", socketStatus ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + IOT_FUNCTION_CLEANUP_BEGIN(); + + /* Clean up on failure. */ + if( status != IOT_NETWORK_SUCCESS ) + { + if( tcpSocket != SOCKETS_INVALID_SOCKET ) + { + SOCKETS_Close( tcpSocket ); + } + + /* Clear the connection information. */ + if( pNewNetworkConnection != NULL ) + { + vPortFree( pNewNetworkConnection ); + } + } + else + { + /* Set the socket. */ + pNewNetworkConnection->socket = tcpSocket; + + /* Create the connection event flags and mutex. */ + pConnectionFlags = xEventGroupCreateStatic( &( pNewNetworkConnection->connectionFlags ) ); + pConnectionMutex = xSemaphoreCreateMutexStatic( &( pNewNetworkConnection->socketMutex ) ); + + /* Static event flags and mutex creation should never fail. The handles + * should point inside the connection object. */ + configASSERT( pConnectionFlags == ( EventGroupHandle_t ) &( pNewNetworkConnection->connectionFlags ) ); + configASSERT( pConnectionMutex == ( SemaphoreHandle_t ) &( pNewNetworkConnection->socketMutex ) ); + + /* Set the output parameter. */ + *pNetworkConnection = pNewNetworkConnection; + } + + IOT_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_SetReceiveCallback( void * pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ) +{ + IotNetworkError_t status = IOT_NETWORK_SUCCESS; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Set the receive callback and context. */ + pNetworkConnection->receiveCallback = receiveCallback; + pNetworkConnection->pReceiveContext = pContext; + + /* No flags should be set. */ + configASSERT( xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ) == 0 ); + + /* Create task that waits for incoming data. */ + if( xTaskCreate( _networkReceiveTask, + "NetRecv", + IOT_NETWORK_RECEIVE_TASK_STACK_SIZE, + pNetworkConnection, + IOT_NETWORK_RECEIVE_TASK_PRIORITY, + &( pNetworkConnection->receiveTask ) ) != pdPASS ) + { + IotLogError( "Failed to create network receive task." ); + + status = IOT_NETWORK_SYSTEM_ERROR; + } + + return status; +} + +/*-----------------------------------------------------------*/ + +size_t IotNetworkAfr_Send( void * pConnection, + const uint8_t * pMessage, + size_t messageLength ) +{ + size_t bytesSent = 0U, bytesRemaining = messageLength; + int32_t socketStatus = SOCKETS_ERROR_NONE; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Only one thread at a time may send on the connection. Lock the socket + * mutex to prevent other threads from sending. */ + if( xSemaphoreTake( ( QueueHandle_t ) &( pNetworkConnection->socketMutex ), + portMAX_DELAY ) == pdTRUE ) + { + while( bytesRemaining > 0U ) + { + socketStatus = SOCKETS_Send( pNetworkConnection->socket, + pMessage, + bytesRemaining, + 0 ); + + if( socketStatus > 0 ) + { + bytesSent += ( size_t ) socketStatus; + pMessage += ( size_t ) socketStatus; + bytesRemaining -= ( size_t ) socketStatus; + configASSERT( bytesSent + bytesRemaining == messageLength ); + } + else + { + IotLogError( "Error %ld while sending data.", ( long int ) socketStatus ); + break; + } + } + + xSemaphoreGive( ( QueueHandle_t ) &( pNetworkConnection->socketMutex ) ); + } + + return bytesSent; +} + +/*-----------------------------------------------------------*/ + +size_t IotNetworkAfr_Receive( void * pConnection, + uint8_t * pBuffer, + size_t bytesRequested ) +{ + int32_t socketStatus = 0; + size_t bytesReceived = 0, bytesRemaining = bytesRequested; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Caller should never request zero bytes. */ + configASSERT( bytesRequested > 0 ); + + /* Write the buffered byte. THIS IS A TEMPORARY WORKAROUND AND ASSUMES THIS + * FUNCTION IS ALWAYS CALLED FROM THE RECEIVE CALLBACK. */ + if( pNetworkConnection->bufferedByteValid == true ) + { + *pBuffer = pNetworkConnection->bufferedByte; + bytesReceived = 1; + bytesRemaining--; + pNetworkConnection->bufferedByteValid = false; + } + + /* Block and wait for incoming data. */ + while( bytesRemaining > 0 ) + { + socketStatus = SOCKETS_Recv( pNetworkConnection->socket, + pBuffer + bytesReceived, + bytesRemaining, + 0 ); + + if( socketStatus == SOCKETS_EWOULDBLOCK ) + { + /* The return value EWOULDBLOCK means no data was received within + * the socket timeout. Ignore it and try again. */ + continue; + } + else if( socketStatus < 0 ) + { + IotLogError( "Error %ld while receiving data.", ( long int ) socketStatus ); + break; + } + else + { + bytesReceived += ( size_t ) socketStatus; + bytesRemaining -= ( size_t ) socketStatus; + + configASSERT( bytesReceived + bytesRemaining == bytesRequested ); + } + } + + if( bytesReceived < bytesRequested ) + { + IotLogWarn( "Receive requested %lu bytes, but %lu bytes received instead.", + ( unsigned long ) bytesRequested, + ( unsigned long ) bytesReceived ); + } + else + { + IotLogDebug( "Successfully received %lu bytes.", + ( unsigned long ) bytesRequested ); + } + + return bytesReceived; +} + +/*-----------------------------------------------------------*/ + +size_t IotNetworkAfr_ReceiveUpto( void * pConnection, + uint8_t * pBuffer, + size_t bufferSize ) +{ + int32_t socketStatus = 0; + size_t bytesReceived = 0; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Caller should never pass a zero-length buffer. */ + configASSERT( bufferSize > 0 ); + + /* Write the buffered byte. THIS IS A TEMPORARY WORKAROUND AND ASSUMES THIS + * FUNCTION IS ALWAYS CALLED FROM THE RECEIVE CALLBACK. */ + if( pNetworkConnection->bufferedByteValid == true ) + { + *pBuffer = pNetworkConnection->bufferedByte; + bytesReceived = 1; + pNetworkConnection->bufferedByteValid = false; + } + + if( bufferSize - bytesReceived > 0 ) + { + /* Block and wait for incoming data. */ + socketStatus = SOCKETS_Recv( pNetworkConnection->socket, + pBuffer + bytesReceived, + bufferSize - bytesReceived, + 0 ); + + if( socketStatus <= 0 ) + { + IotLogError( "Error %ld while receiving data.", ( long int ) socketStatus ); + } + else + { + bytesReceived += ( size_t ) socketStatus; + } + } + + IotLogDebug( "Received %lu bytes.", + ( unsigned long ) bytesReceived ); + + return bytesReceived; +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_Close( void * pConnection ) +{ + int32_t socketStatus = SOCKETS_ERROR_NONE; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Set the shutdown flag so that the network receive task can stop polling. */ + ( void ) xEventGroupSetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_SHUTDOWN ); + + /* If this function is not called from the receive task, wait for the receive task to exit. */ + if( ( pNetworkConnection->receiveTask != NULL ) && ( xTaskGetCurrentTaskHandle() != pNetworkConnection->receiveTask ) ) + { + /* Wait for the network receive task to exit so that the socket can be shutdown safely + * without causing the socket to block forever if there are pending reads or writes + * from other tasks. Do not clear the flag as IotNetworkAfr_Destroy checks it. */ + ( void ) xEventGroupWaitBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_RECEIVE_TASK_EXITED, + pdFALSE, + pdTRUE, + portMAX_DELAY ); + } + + /* Call Secure Sockets shutdown function to close connection. */ + socketStatus = SOCKETS_Shutdown( pNetworkConnection->socket, + SOCKETS_SHUT_RDWR ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogWarn( "Failed to close connection." ); + } + + return IOT_NETWORK_SUCCESS; +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_Destroy( void * pConnection ) +{ + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Check if this function is being called from the receive task. */ + if( xTaskGetCurrentTaskHandle() == pNetworkConnection->receiveTask ) + { + /* Set the flag specifying that the connection is destroyed. */ + ( void ) xEventGroupSetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_RECEIVE_TASK_CONNECTION_DESTROYED ); + } + else + { + /* As this function should be called ONLY called after the connection is closed, + * the receive task should have already exited. */ + if( pNetworkConnection->receiveCallback != NULL ) + { + EventBits_t connectionFlags; + connectionFlags = xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ); + + configASSERT( ( connectionFlags & _FLAG_RECEIVE_TASK_EXITED ) == _FLAG_RECEIVE_TASK_EXITED ); + + /* Suppress compiler warning of unused connectionFlags variable when + * configASSERT() is disabled. */ + ( void ) connectionFlags; + } + + _destroyConnection( pNetworkConnection ); + } + + return IOT_NETWORK_SUCCESS; +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/abstractions/platform/freertos/iot_threads_freertos.c b/bsp/aws_libraries/abstractions/platform/freertos/iot_threads_freertos.c new file mode 100644 index 0000000..3d1c95e --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/freertos/iot_threads_freertos.c @@ -0,0 +1,364 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_threads_freertos.c + * @brief Implementation of the functions in iot_threads.h for POSIX systems. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +#include "semphr.h" + +/* Platform threads include. */ +#include "platform/iot_platform_types_freertos.h" +#include "platform/iot_threads.h" +#include "types/iot_platform_types.h" + +/* Configure logs for the functions in this file. */ +#ifdef IOT_LOG_LEVEL_PLATFORM + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM +#else + #ifdef IOT_LOG_LEVEL_GLOBAL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL + #else + #define LIBRARY_LOG_LEVEL IOT_LOG_NONE + #endif +#endif + +#define LIBRARY_LOG_NAME ( "THREAD" ) +#include "iot_logging_setup.h" + +/* + * Provide default values for undefined memory allocation functions based on + * the usage of dynamic memory allocation. + */ +#ifndef IotThreads_Malloc + #include "FreeRTOS.h" + +/** + * @brief Memory allocation. This function should have the same signature + * as [malloc](http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html). + */ + #define IotThreads_Malloc pvPortMalloc +#endif +#ifndef IotThreads_Free + #include "FreeRTOS.h" + +/** + * @brief Free memory. This function should have the same signature as + * [free](http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html). + */ + #define IotThreads_Free pvPortFree +#endif + +/*-----------------------------------------------------------*/ + +static void _threadRoutineWrapper( void * pArgument ) +{ + threadInfo_t * pThreadInfo = ( threadInfo_t * ) pArgument; + + /* Run the thread routine. */ + pThreadInfo->threadRoutine( pThreadInfo->pArgument ); + IotThreads_Free( pThreadInfo ); + + vTaskDelete( NULL ); +} + +/*-----------------------------------------------------------*/ + +bool Iot_CreateDetachedThread( IotThreadRoutine_t threadRoutine, + void * pArgument, + int32_t priority, + size_t stackSize ) +{ + bool status = true; + + configASSERT( threadRoutine != NULL ); + + IotLogDebug( "Creating new thread." ); + threadInfo_t * pThreadInfo = IotThreads_Malloc( sizeof( threadInfo_t ) ); + + if( pThreadInfo == NULL ) + { + IotLogDebug( "Unable to allocate memory for threadRoutine %p.", threadRoutine ); + status = false; + } + + /* Create the FreeRTOS task that will run the thread. */ + if( status ) + { + pThreadInfo->threadRoutine = threadRoutine; + pThreadInfo->pArgument = pArgument; + + if( xTaskCreate( _threadRoutineWrapper, + "iot_thread", + ( configSTACK_DEPTH_TYPE ) stackSize, + pThreadInfo, + priority, + NULL ) != pdPASS ) + { + /* Task creation failed. */ + IotLogWarn( "Failed to create thread." ); + IotThreads_Free( pThreadInfo ); + status = false; + } + } + + return status; +} + +/*-----------------------------------------------------------*/ + +bool IotMutex_Create( IotMutex_t * pNewMutex, + bool recursive ) +{ + _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pNewMutex; + + configASSERT( internalMutex != NULL ); + + IotLogDebug( "Creating new mutex %p.", pNewMutex ); + + if( recursive ) + { + ( void ) xSemaphoreCreateRecursiveMutexStatic( &internalMutex->xMutex ); + } + else + { + ( void ) xSemaphoreCreateMutexStatic( &internalMutex->xMutex ); + } + + /* remember the type of mutex */ + if( recursive ) + { + internalMutex->recursive = pdTRUE; + } + else + { + internalMutex->recursive = pdFALSE; + } + + return true; +} + +/*-----------------------------------------------------------*/ + +void IotMutex_Destroy( IotMutex_t * pMutex ) +{ + _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex; + + configASSERT( internalMutex != NULL ); + + vSemaphoreDelete( ( SemaphoreHandle_t ) &internalMutex->xMutex ); +} + +/*-----------------------------------------------------------*/ + +bool prIotMutexTimedLock( IotMutex_t * pMutex, + TickType_t timeout ) +{ + _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex; + BaseType_t lockResult; + + configASSERT( internalMutex != NULL ); + + IotLogDebug( "Locking mutex %p.", internalMutex ); + + /* Call the correct FreeRTOS mutex take function based on mutex type. */ + if( internalMutex->recursive == pdTRUE ) + { + lockResult = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout ); + } + else + { + lockResult = xSemaphoreTake( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout ); + } + + return( lockResult == pdTRUE ); +} + +/*-----------------------------------------------------------*/ + +void IotMutex_Lock( IotMutex_t * pMutex ) +{ + prIotMutexTimedLock( pMutex, portMAX_DELAY ); +} + +/*-----------------------------------------------------------*/ + +bool IotMutex_TryLock( IotMutex_t * pMutex ) +{ + return prIotMutexTimedLock( pMutex, 0 ); +} + +/*-----------------------------------------------------------*/ + +void IotMutex_Unlock( IotMutex_t * pMutex ) +{ + _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex; + + configASSERT( internalMutex != NULL ); + + IotLogDebug( "Unlocking mutex %p.", internalMutex ); + + /* Call the correct FreeRTOS mutex unlock function based on mutex type. */ + if( internalMutex->recursive == pdTRUE ) + { + ( void ) xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex ); + } + else + { + ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &internalMutex->xMutex ); + } +} + +/*-----------------------------------------------------------*/ + +bool IotSemaphore_Create( IotSemaphore_t * pNewSemaphore, + uint32_t initialValue, + uint32_t maxValue ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pNewSemaphore; + + configASSERT( internalSemaphore != NULL ); + + IotLogDebug( "Creating new semaphore %p.", pNewSemaphore ); + + ( void ) xSemaphoreCreateCountingStatic( maxValue, initialValue, &internalSemaphore->xSemaphore ); + + return true; +} + +/*-----------------------------------------------------------*/ + +uint32_t IotSemaphore_GetCount( IotSemaphore_t * pSemaphore ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; + UBaseType_t count = 0; + + configASSERT( internalSemaphore != NULL ); + + count = uxSemaphoreGetCount( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore ); + + IotLogDebug( "Semaphore %p has count %d.", pSemaphore, count ); + + return ( uint32_t ) count; +} + +/*-----------------------------------------------------------*/ + +void IotSemaphore_Destroy( IotSemaphore_t * pSemaphore ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; + + configASSERT( internalSemaphore != NULL ); + + IotLogDebug( "Destroying semaphore %p.", internalSemaphore ); + + vSemaphoreDelete( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore ); +} + +/*-----------------------------------------------------------*/ + +void IotSemaphore_Wait( IotSemaphore_t * pSemaphore ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; + + configASSERT( internalSemaphore != NULL ); + + IotLogDebug( "Waiting on semaphore %p.", internalSemaphore ); + + /* Take the semaphore using the FreeRTOS API. */ + if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore, + portMAX_DELAY ) != pdTRUE ) + { + IotLogWarn( "Failed to wait on semaphore %p.", + pSemaphore ); + + /* Assert here, debugging we always want to know that this happened because you think + * that you are waiting successfully on the semaphore but you are not */ + configASSERT( false ); + } +} + +/*-----------------------------------------------------------*/ + +bool IotSemaphore_TryWait( IotSemaphore_t * pSemaphore ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; + + configASSERT( internalSemaphore != NULL ); + + IotLogDebug( "Attempting to wait on semaphore %p.", internalSemaphore ); + + return IotSemaphore_TimedWait( pSemaphore, 0 ); +} + +/*-----------------------------------------------------------*/ + +bool IotSemaphore_TimedWait( IotSemaphore_t * pSemaphore, + uint32_t timeoutMs ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; + + configASSERT( internalSemaphore != NULL ); + + /* Take the semaphore using the FreeRTOS API. Cast the calculation to 64 bit to avoid overflows*/ + if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore, + pdMS_TO_TICKS( timeoutMs ) ) != pdTRUE ) + { + /* Only warn if timeout > 0 */ + if( timeoutMs > 0 ) + { + IotLogWarn( "Timeout waiting on semaphore %p.", + internalSemaphore ); + } + + return false; + } + + return true; +} + +/*-----------------------------------------------------------*/ + +void IotSemaphore_Post( IotSemaphore_t * pSemaphore ) +{ + _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; + + configASSERT( internalSemaphore != NULL ); + + IotLogDebug( "Posting to semaphore %p.", internalSemaphore ); + /* Give the semaphore using the FreeRTOS API. */ + BaseType_t result = xSemaphoreGive( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore ); + + if( result == pdFALSE ) + { + IotLogDebug( "Unable to give semaphore over maximum", internalSemaphore ); + } +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/abstractions/platform/include/platform/iot_clock.h b/bsp/aws_libraries/abstractions/platform/include/platform/iot_clock.h new file mode 100644 index 0000000..ccf2a62 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/include/platform/iot_clock.h @@ -0,0 +1,235 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_clock.h + * @brief Time-related functions used by libraries in this SDK. + */ + +#ifndef IOT_CLOCK_H_ +#define IOT_CLOCK_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include + +/* Platform layer types include. */ +#include "types/iot_platform_types.h" + +/** + * @functions_page{platform_clock,platform clock component,Clock} + * @functions_brief{platform clock component} + * - @function_name{platform_clock_function_gettimestring} + * @function_brief{platform_clock_function_gettimestring} + * - @function_name{platform_clock_function_gettimems} + * @function_brief{platform_clock_function_gettimems} + * - @function_name{platform_clock_function_sleepms} + * @function_brief{platform_clock_function_sleepms} + * - @function_name{platform_clock_function_timercreate} + * @function_brief{platform_clock_function_timercreate} + * - @function_name{platform_clock_function_timerdestroy} + * @function_brief{platform_clock_function_timerdestroy} + * - @function_name{platform_clock_function_timerarm} + * @function_brief{platform_clock_function_timerarm} + */ + +/** + * @function_page{IotClock_GetTimestring,platform_clock,gettimestring} + * @function_snippet{platform_clock,gettimestring,this} + * @copydoc IotClock_GetTimestring + * @function_page{IotClock_GetTimeMs,platform_clock,gettimems} + * @function_snippet{platform_clock,gettimems,this} + * @copydoc IotClock_GetTimeMs + * @function_page{IotClock_SleepMs,platform_clock,sleepms} + * @function_snippet{platform_clock,sleepms,this} + * @copydoc IotClock_SleepMs + * @function_page{IotClock_TimerCreate,platform_clock,timercreate} + * @function_snippet{platform_clock,timercreate,this} + * @copydoc IotClock_TimerCreate + * @function_page{IotClock_TimerDestroy,platform_clock,timerdestroy} + * @function_snippet{platform_clock,timerdestroy,this} + * @copydoc IotClock_TimerDestroy + * @function_page{IotClock_TimerArm,platform_clock,timerarm} + * @function_snippet{platform_clock,timerarm,this} + * @copydoc IotClock_TimerArm + */ + +/** + * @brief Generates a human-readable timestring, such as "01 Jan 2018 12:00". + * + * This function uses the system clock to generate a human-readable timestring. + * This timestring is printed by the [logging functions](@ref logging_functions). + * + * @param[out] pBuffer A buffer to store the timestring in. + * @param[in] bufferSize The size of `pBuffer`. + * @param[out] pTimestringLength The actual length of the timestring stored in + * `pBuffer`. + * + * @return `true` if a timestring was successfully generated; `false` otherwise. + * + * @warning The implementation of this function must not call any [logging functions] + * (@ref logging_functions). + * + * Example + * @code{c} + * char timestring[ 32 ]; + * size_t timestringLength = 0; + * + * if( IotClock_GetTimestring( timestring, 32, ×tringLength ) == true ) + * { + * printf( "Timestring: %.*s", timestringLength, timestring ); + * } + * @endcode + */ +/* @[declare_platform_clock_gettimestring] */ +bool IotClock_GetTimestring( char * pBuffer, + size_t bufferSize, + size_t * pTimestringLength ); +/* @[declare_platform_clock_gettimestring] */ + +/** + * @brief Returns a nonzero, monotonically-increasing system time in milliseconds. + * + * This function reads a millisecond-resolution system clock. The clock should + * always be monotonically-increasing; therefore, real-time clocks that may be + * set by another process are not suitable for this function's implementation. + * + * @return The value of the system clock. This function is not expected to fail. + * + * Example + * @code{c} + * // Get current time. + * uint64_t currentTime = IotClock_GetTimeMs(); + * @endcode + */ +/* @[declare_platform_clock_gettimems] */ +uint64_t IotClock_GetTimeMs( void ); +/* @[declare_platform_clock_gettimems] */ + +/** + * @brief Delay for the given number of milliseconds. + * + * This function suspends its calling thread for at least `sleepTimeMs` milliseconds. + * + * @param[in] sleepTimeMs Sleep time (in milliseconds). + */ +/* @[declare_platform_clock_sleepms] */ +void IotClock_SleepMs( uint32_t sleepTimeMs ); +/* @[declare_platform_clock_sleepms] */ + +/** + * @brief Create a new timer. + * + * This function creates a new, unarmed timer. It must be called on an uninitialized + * #IotTimer_t. This function must not be called on an already-initialized #IotTimer_t. + * + * @param[out] pNewTimer Set to a new timer handle on success. + * @param[in] expirationRoutine The function to run when this timer expires. This + * function should be called in its own detached thread. + * @param[in] pArgument The argument to pass to `expirationRoutine`. + * + * @return `true` if the timer is successfully created; `false` otherwise. + * + * @see @ref platform_clock_function_timerdestroy, @ref platform_clock_function_timerarm + */ +/* @[declare_platform_clock_timercreate] */ +bool IotClock_TimerCreate( IotTimer_t * pNewTimer, + IotThreadRoutine_t expirationRoutine, + void * pArgument ); +/* @[declare_platform_clock_timercreate] */ + +/** + * @brief Free resources used by a timer. + * + * This function frees resources used by a timer. It must be called on an initialized + * #IotTimer_t. No other timer functions should be called on `pTimer` after calling + * this function (unless the timer is re-created). + * + * This function will stop the `pTimer` if it is armed. + * + * @param[in] pTimer The timer to destroy. + * + * @see @ref platform_clock_function_timercreate, @ref platform_clock_function_timerarm + */ +/* @[declare_platform_clock_timerdestroy] */ +void IotClock_TimerDestroy( IotTimer_t * pTimer ); +/* @[declare_platform_clock_timerdestroy] */ + +/** + * @brief Arm a timer to expire at the given relative timeout. + * + * This function arms a timer to run its expiration routine at the given time. + * + * If `periodMs` is nonzero, the timer should expire periodically at intervals + * such as: + * - `relativeTimeoutMs` + * - `relativeTimeoutMs + periodMs` + * - `relativeTimeoutMs + 2 * periodMs` + * - Etc. (subject to some jitter). + * + * Setting `periodMs` to `0` arms a one-shot, non-periodic timer. + * + * @param[in] pTimer The timer to arm. + * @param[in] relativeTimeoutMs When the timer should expire, relative to the time + * this function is called. + * @param[in] periodMs How often the timer should expire again after `relativeTimerMs`. + * + * @return `true` if the timer was successfully armed; `false` otherwise. + * + * @see @ref platform_clock_function_timercreate, @ref platform_clock_function_timerdestroy + * + * Example + * @code{c} + * + * void timerExpirationRoutine( void * pArgument ); + * + * void timerExample( void ) + * { + * IotTimer_t timer; + * + * if( IotClock_TimerCreate( &timer, timerExpirationRoutine, NULL ) == true ) + * { + * // Set the timer to periodically expire every 10 seconds. + * if( IotClock_TimerArm( &timer, 10000, 10000 ) == true ) + * { + * // Wait for timer to expire. + * } + * + * IotClock_TimerDestroy( &timer ); + * } + * } + * @endcode + */ +/* @[declare_platform_clock_timerarm] */ +bool IotClock_TimerArm( IotTimer_t * pTimer, + uint32_t relativeTimeoutMs, + uint32_t periodMs ); +/* @[declare_platform_clock_timerarm] */ + +#endif /* ifndef IOT_CLOCK_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/include/platform/iot_metrics.h b/bsp/aws_libraries/abstractions/platform/include/platform/iot_metrics.h new file mode 100644 index 0000000..344a757 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/include/platform/iot_metrics.h @@ -0,0 +1,113 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_metrics.h + * @brief Functions for retrieving [Device Defender](@ref defender) metrics. + * + * The functions in this header are only required by Device Defender. They do not + * need to be implemented if Device Defender is not used. + */ + +#ifndef IOT_METRICS_H_ +#define IOT_METRICS_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include + +/* Linear containers (lists and queues) include. */ +#include "iot_linear_containers.h" + +/** + * @functions_page{platform_metrics,platform metrics component,Metrics} + * @functions_brief{platform metrics component} + * - @function_name{platform_metrics_function_init} + * @function_brief{platform_metrics_function_init} + * - @function_name{platform_metrics_function_cleanup} + * @function_brief{platform_metrics_function_cleanup} + * - @function_name{platform_metrics_function_gettcpconnections} + * @function_brief{platform_metrics_function_gettcpconnections} + */ + +/** + * @function_page{IotMetrics_Init,platform_metrics,init} + * @function_snippet{platform_metrics,init,this} + * @copydoc IotMetrics_Init + * @function_page{IotMetrics_Cleanup,platform_metrics,cleanup} + * @function_snippet{platform_metrics,cleanup,this} + * @copydoc IotMetrics_Cleanup + * @function_page{IotMetrics_GetTcpConnections,platform_metrics,gettcpconnections} + * @function_snippet{platform_metrics,gettcpconnections,this} + * @copydoc IotMetrics_GetTcpConnections + */ + +/** + * @brief One-time initialization function for the platform metrics component. + * + * This function initializes the platform metrics component. It must be called + * once (and only once) before calling any other metrics or [Device Defender function] + * (@ref defender_functions). Calling this function more than once without first + * calling @ref platform_metrics_function_cleanup may result in a crash. + * + * @return `true` is initialization succeeded; `false` otherwise. + * + * @warning No thread-safety guarantees are provided for this function. + */ +/* @[declare_platform_metrics_init] */ +bool IotMetrics_Init( void ); +/* @[declare_platform_metrics_init] */ + +/** + * @brief One-time deinitialization function for the platform metrics component. + * + * This function frees resources taken in @ref platform_metrics_function_init. + * No other metrics or [Device Defender functions](@ref defender_functions) may + * be called unless @ref platform_metrics_function_init is called again. + * + * @warning No thread-safety guarantees are provided for this function. + */ +/* @[declare_platform_metrics_cleanup] */ +void IotMetrics_Cleanup( void ); +/* @[declare_platform_metrics_cleanup] */ + +/** + * @brief Retrieve a list of active TCP connections from the system. + * + * The provided connections are reported by Device Defender. + * + * @param[in] pContext Context passed as the first parameter of `metricsCallback`. + * @param[in] metricsCallback Called by this function to provide the list of TCP + * connections. The list given by this function is should not be used after the + * callback returns. + */ +/* @[declare_platform_metrics_gettcpconnections] */ +void IotMetrics_GetTcpConnections( void * pContext, + void ( * metricsCallback )( void *, const IotListDouble_t * ) ); +/* @[declare_platform_metrics_gettcpconnections] */ + +#endif /* ifndef IOT_METRICS_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/include/platform/iot_network.h b/bsp/aws_libraries/abstractions/platform/include/platform/iot_network.h new file mode 100644 index 0000000..22691a7 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/include/platform/iot_network.h @@ -0,0 +1,343 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_network.h + * @brief Abstraction of network functions used by libraries in this SDK. + */ + +#ifndef IOT_NETWORK_H_ +#define IOT_NETWORK_H_ + +/* Standard includes. */ +#include +#include +#include + +/** + * @ingroup platform_datatypes_enums + * @brief Return codes for [network functions](@ref platform_network_functions). + */ +typedef enum IotNetworkError +{ + IOT_NETWORK_SUCCESS = 0, /**< Function successfully completed. */ + IOT_NETWORK_FAILURE, /**< Generic failure not covered by other values. */ + IOT_NETWORK_BAD_PARAMETER, /**< At least one parameter was invalid. */ + IOT_NETWORK_NO_MEMORY, /**< Memory allocation failed. */ + IOT_NETWORK_SYSTEM_ERROR /**< An error occurred when calling a system API. */ +} IotNetworkError_t; + +/** + * @page platform_network_functions Networking + * @brief Functions of the network abstraction component. + * + * The network abstraction component does not declare functions, but uses function + * pointers instead. This allows multiple network stacks to be used at the same time. + * Libraries that require the network will request an #IotNetworkInterface_t + * parameter. The members of the #IotNetworkInterface_t will be called whenever + * the library interacts with the network. + * + * The following function pointers are associated with an #IotNetworkInterface_t. + * Together, they represent a network stack. + * - @function_name{platform_network_function_create} + * @function_brief{platform_network_function_create} + * - @function_name{platform_network_function_setreceivecallback} + * @function_brief{platform_network_function_setreceivecallback} + * - @function_name{platform_network_function_send} + * @function_brief{platform_network_function_send} + * - @function_name{platform_network_function_receive} + * @function_brief{platform_network_function_receive} + * - @function_name{platform_network_function_receiveupto} + * @function_brief{platform_network_function_receiveupto} + * - @function_name{platform_network_function_close} + * @function_brief{platform_network_function_close} + * - @function_name{platform_network_function_destroy} + * @function_brief{platform_network_function_destroy} + * - @function_name{platform_network_function_receivecallback} + * @function_brief{platform_network_function_receivecallback} + */ + +/** + * @function_page{IotNetworkInterface_t::create,platform_network,create} + * @function_snippet{platform_network,create,this} + * @copydoc IotNetworkInterface_t::create + * @function_page{IotNetworkInterface_t::setReceiveCallback,platform_network,setreceivecallback} + * @function_snippet{platform_network,setreceivecallback,this} + * @copydoc IotNetworkInterface_t::setReceiveCallback + * @function_page{IotNetworkInterface_t::send,platform_network,send} + * @function_snippet{platform_network,send,this} + * @copydoc IotNetworkInterface_t::send + * @function_page{IotNetworkInterface_t::receive,platform_network,receive} + * @function_snippet{platform_network,receive,this} + * @copydoc IotNetworkInterface_t::receive + * @function_page{IotNetworkInterface_t::receiveUpto,platform_network,receiveupto} + * @function_snippet{platform_network,receiveupto,this} + * @copydoc IotNetworkInterface_t::receiveUpto + * @function_page{IotNetworkInterface_t::close,platform_network,close} + * @function_snippet{platform_network,close,this} + * @copydoc IotNetworkInterface_t::close + * @function_page{IotNetworkInterface_t::destroy,platform_network,destroy} + * @function_snippet{platform_network,destroy,this} + * @copydoc IotNetworkInterface_t::destroy + * @function_page{IotNetworkReceiveCallback_t,platform_network,receivecallback} + * @function_snippet{platform_network,receivecallback,this} + * @copydoc IotNetworkReceiveCallback_t + */ + +/** + * @brief Provide an asynchronous notification of incoming network data. + * + * A function with this signature may be set with @ref platform_network_function_setreceivecallback + * to be invoked when data is available on the network. + * + * @param[in] pConnection The connection on which data is available, defined by + * the network stack. + * @param[in] pContext The third argument passed to @ref platform_network_function_setreceivecallback. + */ +/* @[declare_platform_network_receivecallback] */ +typedef void ( * IotNetworkReceiveCallback_t )( void * pConnection, + void * pContext ); +/* @[declare_platform_network_receivecallback] */ + +/** + * @ingroup platform_datatypes_paramstructs + * @brief Represents the functions of a network stack. + * + * Functions that match these signatures should be implemented against a system's + * network stack. See the `platform` directory for existing implementations. + */ +typedef struct IotNetworkInterface +{ + /** + * @brief Create a new network connection. + * + * This function allocates resources and establishes a new network connection. + * @param[in] pConnectionInfo Represents information needed to set up the + * new connection, defined by the network stack. + * @param[in] pCredentialInfo Represents information needed to secure the + * new connection, defined by the network stack. + * @param[out] pConnection Set to represent a new connection, defined by the + * network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + */ + /* @[declare_platform_network_create] */ + IotNetworkError_t ( * create )( void * pConnectionInfo, + void * pCredentialInfo, + void ** pConnection ); + /* @[declare_platform_network_create] */ + + /** + * @brief Register an @ref platform_network_function_receivecallback. + * + * Sets an @ref platform_network_function_receivecallback to be called + * asynchronously when data arrives on the network. The network stack + * should invoke this function "as if" it were the thread routine of a + * detached thread. + * + * Each network connection may only have one receive callback at any time. + * @ref platform_network_function_close is expected to remove any active + * receive callbacks. + * + * @param[in] pConnection The connection to associate with the receive callback. + * @param[in] receiveCallback The function to invoke for incoming network data. + * @param[in] pContext A value to pass as the first parameter to the receive callback. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @see platform_network_function_receivecallback + */ + /* @[declare_platform_network_setreceivecallback] */ + IotNetworkError_t ( * setReceiveCallback )( void * pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ); + /* @[declare_platform_network_setreceivecallback] */ + + /** + * @brief Send data over a return connection. + * + * Attempts to transmit `messageLength` bytes of `pMessage` across the + * connection represented by `pConnection`. Returns the number of bytes + * actually sent, `0` on failure. + * + * @param[in] pConnection The connection used to send data, defined by the + * network stack. + * @param[in] pMessage The message to send. + * @param[in] messageLength The length of `pMessage`. + * + * @return The number of bytes successfully sent, `0` on failure. + */ + /* @[declare_platform_network_send] */ + size_t ( * send )( void * pConnection, + const uint8_t * pMessage, + size_t messageLength ); + /* @[declare_platform_network_send] */ + + /** + * @brief Block and wait for incoming network data. + * + * Wait for a message of size `bytesRequested` to arrive on the network and + * place it in `pBuffer`. + * + * @param[in] pConnection The connection to wait on, defined by the network + * stack. + * @param[out] pBuffer Where to place the incoming network data. This buffer + * must be at least `bytesRequested` in size. + * @param[in] bytesRequested How many bytes to wait for. `pBuffer` must be at + * least this size. + * + * @return The number of bytes successfully received. This MUST be + * `bytesRequested` when successful. Any other value may indicate an error. + */ + /* @[declare_platform_network_receive] */ + size_t ( * receive )( void * pConnection, + uint8_t * pBuffer, + size_t bytesRequested ); + /* @[declare_platform_network_receive] */ + + /** + * @brief Read incoming data available in the network buffers. + * + * Reads bytes available in the network buffers into `pBuffer`. + * - If there is less data available than requested, it will return + * the available number of bytes. + * - If there is more data available than requested, it will fill the + * whole `pBuffer`. + * - If there is no data available, it will return 0. + * + * @param[in] pConnection The connection to receive data on, defined by + * the network stack. + * @param[out] pBuffer The buffer to place the incoming network data. + * @param[in] bufferSize The size of `pBuffer`. + * + * @return The number of bytes successfully received. + */ + /* @[declare_platform_network_receiveupto] */ + size_t ( * receiveUpto )( void * pConnection, + uint8_t * pBuffer, + size_t bufferSize ); + /* @[declare_platform_network_receiveupto] */ + + /** + * @brief Close a network connection. + * + * This function closes the connection, but does not release the resources + * used by the connection. This allows calls to other networking functions + * to return an error and handle a closed connection without the risk of + * crashing. Once it can be guaranteed that `pConnection` will no longer be + * used, the connection can be destroyed with @ref platform_network_function_destroy. + * + * In addition to closing the connection, this function SHOULD also remove + * any active [receive callback](@ref platform_network_function_receivecallback). + * + * @param[in] pConnection The network connection to close, defined by the + * network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @note It MUST be safe to call this function on an already-closed connection. + */ + /* @[declare_platform_network_close] */ + IotNetworkError_t ( * close )( void * pConnection ); + /* @[declare_platform_network_close] */ + + /** + * @brief Free resources used by a network connection. + * + * This function releases the resources of a closed connection. It MUST be + * called after @ref platform_network_function_close. + * + * @param[in] pConnection The network connection to destroy, defined by + * the network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @attention No function MAY be called on the network connection after + * calling this function. This function MUST be safe to call from a + * [receive callback](@ref platform_network_function_receivecallback). + */ + /* @[declare_platform_network_destroy] */ + IotNetworkError_t ( * destroy )( void * pConnection ); + /* @[declare_platform_network_destroy] */ +} IotNetworkInterface_t; + +/** + * @ingroup platform_datatypes_paramstructs + * @brief Information on the remote server for connection setup. + * + * May be passed to #IotNetworkInterface_t.create as `pConnectionInfo`. This + * structure contains commonly-used parameters, but may be replaced with an + * alternative. + */ +typedef struct IotNetworkServerInfo +{ + const char * pHostName; /**< @brief Server host name. Must be NULL-terminated. */ + uint16_t port; /**< @brief Server port in host-order. */ +} IotNetworkServerInfo_t; + +/** + * @ingroup platform_datatypes_paramstructs + * @brief Contains the credentials necessary for connection setup. + * + * May be passed to #IotNetworkInterface_t.create as `pCredentialInfo`. This + * structure contains commonly-used parameters, but may be replaced with an + * alternative. + */ +typedef struct IotNetworkCredentials +{ + /** + * @brief Set this to a non-NULL value to use ALPN. + * + * This string must be NULL-terminated. + * + * See [this link] + * (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/) + * for more information. + */ + const char * pAlpnProtos; + + /** + * @brief Set this to a non-zero value to use TLS max fragment length + * negotiation (TLS MFLN). + * + * @note The network stack may have a minimum value for this parameter and + * may return an error if this parameter is too small. + */ + size_t maxFragmentLength; + + /** + * @brief Disable server name indication (SNI) for a TLS session. + */ + bool disableSni; + + const char * pRootCa; /**< @brief String representing a trusted server root certificate. */ + size_t rootCaSize; /**< @brief Size associated with #IotNetworkCredentials_t.pRootCa. */ + const char * pClientCert; /**< @brief String representing the client certificate. */ + size_t clientCertSize; /**< @brief Size associated with #IotNetworkCredentials_t.pClientCert. */ + const char * pPrivateKey; /**< @brief String representing the client certificate's private key. */ + size_t privateKeySize; /**< @brief Size associated with #IotNetworkCredentials_t.pPrivateKey. */ +} IotNetworkCredentials_t; + +#endif /* ifndef IOT_NETWORK_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/include/platform/iot_threads.h b/bsp/aws_libraries/abstractions/platform/include/platform/iot_threads.h new file mode 100644 index 0000000..6ded9c5 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/include/platform/iot_threads.h @@ -0,0 +1,396 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_threads.h + * @brief Threading and synchronization functions used by libraries in this SDK. + */ + +#ifndef IOT_THREADS_H_ +#define IOT_THREADS_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include + +/* Platform layer types include. */ +#include "types/iot_platform_types.h" + +/** + * @functions_page{platform_threads,platform thread management,Thread Management} + * @functions_brief{platform thread management} + * - @function_name{platform_threads_function_createdetachedthread} + * @function_brief{platform_threads_function_createdetachedthread} + * - @function_name{platform_threads_function_mutexcreate} + * @function_brief{platform_threads_function_mutexcreate} + * - @function_name{platform_threads_function_mutexdestroy} + * @function_brief{platform_threads_function_mutexdestroy} + * - @function_name{platform_threads_function_mutexlock} + * @function_brief{platform_threads_function_mutexlock} + * - @function_name{platform_threads_function_mutextrylock} + * @function_brief{platform_threads_function_mutextrylock} + * - @function_name{platform_threads_function_mutexunlock} + * @function_brief{platform_threads_function_mutexunlock} + * - @function_name{platform_threads_function_semaphorecreate} + * @function_brief{platform_threads_function_semaphorecreate} + * - @function_name{platform_threads_function_semaphoredestroy} + * @function_brief{platform_threads_function_semaphoredestroy} + * - @function_name{platform_threads_function_semaphoregetcount} + * @function_brief{platform_threads_function_semaphoregetcount} + * - @function_name{platform_threads_function_semaphorewait} + * @function_brief{platform_threads_function_semaphorewait} + * - @function_name{platform_threads_function_semaphoretrywait} + * @function_brief{platform_threads_function_semaphoretrywait} + * - @function_name{platform_threads_function_semaphoretimedwait} + * @function_brief{platform_threads_function_semaphoretimedwait} + * - @function_name{platform_threads_function_semaphorepost} + * @function_brief{platform_threads_function_semaphorepost} + */ + +/** + * @function_page{Iot_CreateDetachedThread,platform_threads,createdetachedthread} + * @function_snippet{platform_threads,createdetachedthread,this} + * @copydoc Iot_CreateDetachedThread + * @function_page{IotMutex_Create,platform_threads,mutexcreate} + * @function_snippet{platform_threads,mutexcreate,this} + * @copydoc IotMutex_Create + * @function_page{IotMutex_Destroy,platform_threads,mutexdestroy} + * @function_snippet{platform_threads,mutexdestroy,this} + * @copydoc IotMutex_Destroy + * @function_page{IotMutex_Lock,platform_threads,mutexlock} + * @function_snippet{platform_threads,mutexlock,this} + * @copydoc IotMutex_Lock + * @function_page{IotMutex_TryLock,platform_threads,mutextrylock} + * @function_snippet{platform_threads,mutextrylock,this} + * @copydoc IotMutex_TryLock + * @function_page{IotMutex_Unlock,platform_threads,mutexunlock} + * @function_snippet{platform_threads,mutexunlock,this} + * @copydoc IotMutex_Unlock + * @function_page{IotSemaphore_Create,platform_threads,semaphorecreate} + * @function_snippet{platform_threads,semaphorecreate,this} + * @copydoc IotSemaphore_Create + * @function_page{IotSemaphore_Destroy,platform_threads,semaphoredestroy} + * @function_snippet{platform_threads,semaphoredestroy,this} + * @copydoc IotSemaphore_Destroy + * @function_page{IotSemaphore_GetCount,platform_threads,semaphoregetcount} + * @function_snippet{platform_threads,semaphoregetcount,this} + * @copydoc IotSemaphore_GetCount + * @function_page{IotSemaphore_Wait,platform_threads,semaphorewait} + * @function_snippet{platform_threads,semaphorewait,this} + * @copydoc IotSemaphore_Wait + * @function_page{IotSemaphore_TryWait,platform_threads,semaphoretrywait} + * @function_snippet{platform_threads,semaphoretrywait,this} + * @copydoc IotSemaphore_TryWait + * @function_page{IotSemaphore_TimedWait,platform_threads,semaphoretimedwait} + * @function_snippet{platform_threads,semaphoretimedwait,this} + * @copydoc IotSemaphore_TimedWait + * @function_page{IotSemaphore_Post,platform_threads,semaphorepost} + * @function_snippet{platform_threads,semaphorepost,this} + * @copydoc IotSemaphore_Post + */ + +/** + * @brief Create a new detached thread, i.e. a thread that cleans up after itself. + * + * This function creates a new thread. Threads created by this function exit + * upon returning from the thread routine. Any resources taken must be freed + * by the exiting thread. + * + * @param[in] threadRoutine The function this thread should run. + * @param[in] pArgument The argument passed to `threadRoutine`. + * @param[in] priority Represents the priority of the new thread, as defined by + * the system. The value #IOT_THREAD_DEFAULT_PRIORITY (i.e. `0`) must be used to + * represent the system default for thread priority. + * @param[in] stackSize Represents the stack size of the new thread, as defined + * by the system. The value #IOT_THREAD_DEFAULT_STACK_SIZE (i.e. `0`) must be used + * to represent the system default for stack size. + * + * @return `true` if the new thread was successfully created; `false` otherwise. + * + * @code{c} + * // Thread routine. + * void threadRoutine( void * pArgument ); + * + * // Run threadRoutine in a detached thread, using default priority and stack size. + * if( Iot_CreateDetachedThread( threadRoutine, + * NULL, + * IOT_THREAD_DEFAULT_PRIORITY, + * IOT_THREAD_DEFAULT_STACK_SIZE ) == true ) + * { + * // Success + * } + * else + * { + * // Failure, no thread was created. + * } + * @endcode + */ +/* @[declare_platform_threads_createdetachedthread] */ +bool Iot_CreateDetachedThread( IotThreadRoutine_t threadRoutine, + void * pArgument, + int32_t priority, + size_t stackSize ); +/* @[declare_platform_threads_createdetachedthread] */ + +/** + * @brief Create a new mutex. + * + * This function creates a new, unlocked mutex. It must be called on an uninitialized + * #IotMutex_t. This function must not be called on an already-initialized #IotMutex_t. + * + * @param[in] pNewMutex Pointer to the memory that will hold the new mutex. + * @param[in] recursive Set to `true` to create a recursive mutex, i.e. a mutex that + * may be locked multiple times by the same thread. If the system does not support + * recursive mutexes, this function should do nothing and return `false`. + * + * @return `true` if mutex creation succeeds; `false` otherwise. + * + * @see @ref platform_threads_function_mutexdestroy + * + * Example + * @code{c} + * IotMutex_t mutex; + * + * // Create non-recursive mutex. + * if( IotMutex_Create( &mutex, false ) == true ) + * { + * // Lock and unlock the mutex... + * + * // Destroy the mutex when it's no longer needed. + * IotMutex_Destroy( &mutex ); + * } + * @endcode + */ +/* @[declare_platform_threads_mutexcreate] */ +bool IotMutex_Create( IotMutex_t * pNewMutex, + bool recursive ); +/* @[declare_platform_threads_mutexcreate] */ + +/** + * @brief Free resources used by a mutex. + * + * This function frees resources used by a mutex. It must be called on an initialized + * #IotMutex_t. No other mutex functions should be called on `pMutex` after calling + * this function (unless the mutex is re-created). + * + * @param[in] pMutex The mutex to destroy. + * + * @warning This function must not be called on a locked mutex. + * @see @ref platform_threads_function_mutexcreate + */ +/* @[declare_platform_threads_mutexdestroy] */ +void IotMutex_Destroy( IotMutex_t * pMutex ); +/* @[declare_platform_threads_mutexdestroy] */ + +/** + * @brief Lock a mutex. This function should only return when the mutex is locked; + * it is not expected to fail. + * + * This function blocks and waits until a mutex is available. It waits forever + * (deadlocks) if `pMutex` is already locked and never unlocked. + * + * @param[in] pMutex The mutex to lock. + * + * @see @ref platform_threads_function_mutextrylock for a nonblocking lock. + */ +/* @[declare_platform_threads_mutexlock] */ +void IotMutex_Lock( IotMutex_t * pMutex ); +/* @[declare_platform_threads_mutexlock] */ + +/** + * @brief Attempt to lock a mutex. Return immediately if the mutex is not available. + * + * If `pMutex` is available, this function immediately locks it and returns. + * Otherwise, this function returns without locking `pMutex`. + * + * @param[in] pMutex The mutex to lock. + * + * @return `true` if the mutex was successfully locked; `false` if the mutex was + * not available. + * + * @see @ref platform_threads_function_mutexlock for a blocking lock. + */ +/* @[declare_platform_threads_mutextrylock] */ +bool IotMutex_TryLock( IotMutex_t * pMutex ); +/* @[declare_platform_threads_mutextrylock] */ + +/** + * @brief Unlock a mutex. This function should only return when the mutex is unlocked; + * it is not expected to fail. + * + * Unlocks a locked mutex. `pMutex` must have been locked by the thread calling + * this function. + * + * @param[in] pMutex The mutex to unlock. + * + * @note This function should not be called on a mutex that is already unlocked. + */ +/* @[declare_platform_threads_mutexunlock] */ +void IotMutex_Unlock( IotMutex_t * pMutex ); +/* @[declare_platform_threads_mutexunlock] */ + +/** + * @brief Create a new counting semaphore. + * + * This function creates a new counting semaphore with a given intial and + * maximum value. It must be called on an uninitialized #IotSemaphore_t. + * This function must not be called on an already-initialized #IotSemaphore_t. + * + * @param[in] pNewSemaphore Pointer to the memory that will hold the new semaphore. + * @param[in] initialValue The semaphore should be initialized with this value. + * @param[in] maxValue The maximum value the semaphore will reach. + * + * @return `true` if semaphore creation succeeds; `false` otherwise. + * + * @see @ref platform_threads_function_semaphoredestroy + * + * Example + * @code{c} + * IotSemaphore_t sem; + * + * // Create a locked binary semaphore. + * if( IotSemaphore_Create( &sem, 0, 1 ) == true ) + * { + * // Unlock the semaphore. + * IotSemaphore_Post( &sem ); + * + * // Destroy the semaphore when it's no longer needed. + * IotSemaphore_Destroy( &sem ); + * } + * @endcode + */ +/* @[declare_platform_threads_semaphorecreate] */ +bool IotSemaphore_Create( IotSemaphore_t * pNewSemaphore, + uint32_t initialValue, + uint32_t maxValue ); +/* @[declare_platform_threads_semaphorecreate] */ + +/** + * @brief Free resources used by a semaphore. + * + * This function frees resources used by a semaphore. It must be called on an initialized + * #IotSemaphore_t. No other semaphore functions should be called on `pSemaphore` after + * calling this function (unless the semaphore is re-created). + * + * @param[in] pSemaphore The semaphore to destroy. + * + * @warning This function must not be called on a semaphore with waiting threads. + * @see @ref platform_threads_function_semaphorecreate + */ +/* @[declare_platform_threads_semaphoredestroy] */ +void IotSemaphore_Destroy( IotSemaphore_t * pSemaphore ); +/* @[declare_platform_threads_semaphoredestroy] */ + +/** + * @brief Query the current count of the semaphore. + * + * This function queries a counting semaphore for its current value. A counting + * semaphore's value is always 0 or positive. + * + * @param[in] pSemaphore The semaphore to query. + * + * @return The current count of the semaphore. This function should not fail. + */ +/* @[declare_platform_threads_semaphoregetcount] */ +uint32_t IotSemaphore_GetCount( IotSemaphore_t * pSemaphore ); +/* @[declare_platform_threads_semaphoregetcount] */ + +/** + * @brief Wait on (lock) a semaphore. This function should only return when the + * semaphore wait succeeds; it is not expected to fail. + * + * This function blocks and waits until a counting semaphore is positive. It + * waits forever (deadlocks) if `pSemaphore` has a count `0` that is never + * [incremented](@ref platform_threads_function_semaphorepost). + * + * @param[in] pSemaphore The semaphore to lock. + * + * @see @ref platform_threads_function_semaphoretrywait for a nonblocking wait; + * @ref platform_threads_function_semaphoretimedwait for a wait with timeout. + */ +/* @[declare_platform_threads_semaphorewait] */ +void IotSemaphore_Wait( IotSemaphore_t * pSemaphore ); +/* @[declare_platform_threads_semaphorewait] */ + +/** + * @brief Attempt to wait on (lock) a semaphore. Return immediately if the semaphore + * is not available. + * + * If the count of `pSemaphore` is positive, this function immediately decrements + * the semaphore and returns. Otherwise, this function returns without decrementing + * `pSemaphore`. + * + * @param[in] pSemaphore The semaphore to lock. + * + * @return `true` if the semaphore wait succeeded; `false` if the semaphore has + * a count of `0`. + * + * @see @ref platform_threads_function_semaphorewait for a blocking wait; + * @ref platform_threads_function_semaphoretimedwait for a wait with timeout. + */ +/* @[declare_platform_threads_semaphoretrywait] */ +bool IotSemaphore_TryWait( IotSemaphore_t * pSemaphore ); +/* @[declare_platform_threads_semaphoretrywait] */ + +/** + * @brief Attempt to wait on (lock) a semaphore with a timeout. + * + * This function blocks and waits until a counting semaphore is positive + * or its timeout expires (whichever is sooner). It decrements + * `pSemaphore` and returns `true` if the semaphore is positive at some + * time during the wait. If `pSemaphore` is always `0` during the wait, + * this function returns `false`. + * + * @param[in] pSemaphore The semaphore to lock. + * @param[in] timeoutMs Relative timeout of semaphore lock. This function returns + * false if the semaphore couldn't be locked within this timeout. + * + * @return `true` if the semaphore wait succeeded; `false` if it timed out. + * + * @see @ref platform_threads_function_semaphoretrywait for a nonblocking wait; + * @ref platform_threads_function_semaphorewait for a blocking wait. + */ +/* @[declare_platform_threads_semaphoretimedwait] */ +bool IotSemaphore_TimedWait( IotSemaphore_t * pSemaphore, + uint32_t timeoutMs ); +/* @[declare_platform_threads_semaphoretimedwait] */ + +/** + * @brief Post to (unlock) a semaphore. This function should only return when the + * semaphore post succeeds; it is not expected to fail. + * + * This function increments the count of a semaphore. Any thread may call this + * function to increment a semaphore's count. + * + * @param[in] pSemaphore The semaphore to unlock. + */ +/* @[declare_platform_threads_semaphorepost] */ +void IotSemaphore_Post( IotSemaphore_t * pSemaphore ); +/* @[declare_platform_threads_semaphorepost] */ + +#endif /* ifndef IOT_THREADS_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/include/types/iot_network_types.h b/bsp/aws_libraries/abstractions/platform/include/types/iot_network_types.h new file mode 100644 index 0000000..f499a07 --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/include/types/iot_network_types.h @@ -0,0 +1,55 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_network_types.h + * @brief Header file contains the network types shared by both low level networking drivers + * and upper level applications. + */ + +#ifndef IOT_NETWORK_TYPES_H_ +#define IOT_NETWORK_TYPES_H_ + +/** + * @brief Network types supported by FreeRTOS. + */ +#define AWSIOT_NETWORK_TYPE_NONE 0x00000000 +#define AWSIOT_NETWORK_TYPE_WIFI 0x00000001 +#define AWSIOT_NETWORK_TYPE_BLE 0x00000002 +#define AWSIOT_NETWORK_TYPE_ETH 0x00000004 +#define AWSIOT_NETWORK_TYPE_ALL ( AWSIOT_NETWORK_TYPE_WIFI | AWSIOT_NETWORK_TYPE_BLE | AWSIOT_NETWORK_TYPE_ETH ) +#define AWSIOT_NETWORK_TYPE_TCP_IP ( AWSIOT_NETWORK_TYPE_WIFI | AWSIOT_NETWORK_TYPE_ETH ) + +/** + * @brief Enum types representing states for different networks. + */ +typedef enum AwsIotNetworkState +{ + eNetworkStateDisabled = 0, /*!< eNetworkStateDisabled State of Network is OFF or disabled. */ + eNetworkStateEnabled = 1, /*!< eNetworkStateEnabled State of the network is enabled but not yet serving traffic. */ + eNetworkStateConnected = 2 /*!< eNetworkStateConnected State of the network is connected and ready for serving traffic. */ +} AwsIotNetworkState_t; + +#endif /* IOT_NETWORK_TYPES_H_ */ diff --git a/bsp/aws_libraries/abstractions/platform/include/types/iot_platform_types.h b/bsp/aws_libraries/abstractions/platform/include/types/iot_platform_types.h new file mode 100644 index 0000000..a4bdb7d --- /dev/null +++ b/bsp/aws_libraries/abstractions/platform/include/types/iot_platform_types.h @@ -0,0 +1,158 @@ +/* + * FreeRTOS Platform V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_platform_types.h + * @brief Types of the platform layer. + */ + +#ifndef IOT_PLATFORM_TYPES_H_ +#define IOT_PLATFORM_TYPES_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Linear containers (lists and queues) include for metrics types. */ +#include "iot_linear_containers.h" + +/*------------------------- Thread management types -------------------------*/ + +/** + * @brief A value representing the system default for new thread priority. + */ +#ifndef IOT_THREAD_DEFAULT_PRIORITY + #define IOT_THREAD_DEFAULT_PRIORITY 0 +#endif + +/** + * @brief A value representhing the system default for new thread stack size. + */ +#ifndef IOT_THREAD_DEFAULT_STACK_SIZE + #define IOT_THREAD_DEFAULT_STACK_SIZE 0 +#endif + +/** + * @ingroup platform_datatypes_handles + * @brief The type used to represent mutexes, configured with the type + * `_IotSystemMutex_t`. + * + * + * `_IotSystemMutex_t` will be automatically configured during build and generally + * does not need to be defined. + * + * + * Mutexes should only be released by the threads that take them. + * + * Example
+ * To change the type of #IotMutex_t to `long`: + * @code{c} + * typedef long _IotSystemMutex_t; + * #include "iot_threads.h" + * @endcode + */ +typedef _IotSystemMutex_t IotMutex_t; + +/** + * @ingroup platform_datatypes_handles + * @brief The type used to represent semaphores, configured with the type + * `_IotSystemSemaphore_t`. + * + * + * `_IotSystemSemaphore_t` will be automatically configured during build and + * generally does not need to be defined. + * + * + * Semaphores must be counting, and any thread may take (wait on) or release + * (post to) a semaphore. + * + * Example
+ * To change the type of #IotSemaphore_t to `long`: + * @code{c} + * typedef long _IotSystemSemaphore_t; + * #include "iot_threads.h" + * @endcode + */ +typedef _IotSystemSemaphore_t IotSemaphore_t; + +/** + * @brief Thread routine function. + * + * @param[in] void * The argument passed to the @ref + * platform_threads_function_createdetachedthread. For application use. + */ +typedef void ( * IotThreadRoutine_t )( void * ); + +/*-------------------------- Clock and timer types --------------------------*/ + +/** + * @ingroup platform_datatypes_handles + * @brief The type used to represent timers, configured with the type + * `_IotSystemTimer_t`. + * + * + * `_IotSystemTimer_t` will be automatically configured during build and generally + * does not need to be defined. + * + * + * Example
+ * To change the type of #IotTimer_t to `long`: + * @code{c} + * typedef long _IotSystemTimer_t; + * #include "iot_clock.h" + * @endcode + */ +typedef _IotSystemTimer_t IotTimer_t; + +/*------------------------------ Metrics types ------------------------------*/ + +/** + * @brief The length of the buffer used to store IP addresses for metrics. + * + * This is the length of the longest IPv6 address plus space for the port number + * and NULL terminator. + */ +#define IOT_METRICS_IP_ADDRESS_LENGTH 54 + +/** + * @brief Represents a TCP connection to a remote IPv4 server. + * + * A list of these is provided by @ref platform_metrics_function_gettcpconnections. + */ +typedef struct IotMetricsTcpConnection +{ + IotLink_t link; /**< @brief List link member. */ + void * pNetworkContext; /**< @brief Context that may be used by metrics or Defender. */ + size_t addressLength; /**< @brief The length of the address stored in #IotMetricsTcpConnection_t.pRemoteAddress. */ + + /** + * @brief NULL-terminated IP address and port in text format. + * + * IPv4 addresses will be in the format `xxx.xxx.xxx.xxx:port`. + * IPv6 addresses will be in the format `[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:port`. + */ + char pRemoteAddress[ IOT_METRICS_IP_ADDRESS_LENGTH ]; +} IotMetricsTcpConnection_t; + +#endif /* ifndef IOT_PLATFORM_TYPES_H_ */ diff --git a/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets.h b/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets.h new file mode 100644 index 0000000..3938fab --- /dev/null +++ b/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets.h @@ -0,0 +1,667 @@ +/* + * FreeRTOS Secure Sockets V1.3.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_secure_sockets.h + * @brief Secure Sockets Interface. + * + * Secure sockets is a portable layer for establishing a TCP/IP + * connection, with the option of using TLS. + * + * Secure sockets is based on the Berkeley sockets API. + * A few difference general differences between Berkeley and SOCKETS are: + * - SOCKETS has additional socket options to enable TLS, server name + * indication, and per-socket root of trust server certificates. See + * SOCKETS_SetSockOpt() for more information. + * - SOCKETS API return an error code, rather than returning -1 and setting + * a global errno value. + * + */ + +#ifndef _AWS_SECURE_SOCKETS_H_ +#define _AWS_SECURE_SOCKETS_H_ + +/* + #ifdef __cplusplus + * extern "C" { + #endif + */ +#include +#include +#include "iot_secure_sockets_config.h" +#include "iot_secure_sockets_config_defaults.h" +#include "iot_secure_sockets_wrapper_metrics.h" +#include "iot_lib_init.h" + +/** + * @ingroup SecureSockets_datatypes_handles + * @brief The socket handle data type. + * + * For detail of socket, refer to [Network Sockets] + * (https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/socket.html) + * + * Data contained by the Socket_t type is port specific. + */ +struct xSOCKET; +typedef struct xSOCKET * Socket_t; /**< @brief Socket handle data type. */ + +/** + * @brief The "size_t" of secure sockets. + * + * This type is used for compatibility with the expected Berkeley sockets + * naming. + */ +#define Socklen_t uint32_t + +/** + * @anchor SocketsErrors + * @name SocketsErrors + * @brief Error codes returned by the SOCKETS API. + * + * Note that SOCKETS API may also propagate port-specific + * error codes when they are more descriptive. See your + * port's error codes for more details. + * PORT_SPECIFIC_LINK + */ +/**@{ */ + +#define SOCKETS_ERROR_NONE ( 0 ) /*!< No error. */ +#define SOCKETS_SOCKET_ERROR ( -1 ) /*!< Catch-all sockets error code. */ +#define SOCKETS_EWOULDBLOCK ( -11 ) /*!< A resource is temporarily unavailable. */ +#define SOCKETS_ENOMEM ( -12 ) /*!< Memory allocation failed. */ +#define SOCKETS_EINVAL ( -22 ) /*!< Invalid argument. */ +#define SOCKETS_ENOPROTOOPT ( -109 ) /*!< A bad option was specified . */ +#define SOCKETS_ENOTCONN ( -126 ) /*!< The supplied socket is not connected. */ +#define SOCKETS_EISCONN ( -127 ) /*!< The supplied socket is already connected. */ +#define SOCKETS_ECLOSED ( -128 ) /*!< The supplied socket has already been closed. */ +#define SOCKETS_TLS_INIT_ERROR ( -1001 ) /*!< TLS initialization failed. */ +#define SOCKETS_TLS_HANDSHAKE_ERROR ( -1002 ) /*!< TLS handshake failed. */ +#define SOCKETS_TLS_SERVER_UNVERIFIED ( -1003 ) /*!< A connection was made but the server could not be verified. It is recommended that the socket be closed. */ +#define SOCKETS_TLS_RECV_ERROR ( -1004 ) /*!< TLS receive operation failed. */ +#define SOCKETS_TLS_SEND_ERROR ( -1005 ) /*!< TLS send operation failed. */ +#define SOCKETS_PERIPHERAL_RESET ( -1006 ) /*!< Communications peripheral has been reset. */ +/**@} */ + +/** + * @brief Assigned to an Socket_t variable when the socket is not valid. + */ +#define SOCKETS_INVALID_SOCKET ( ( Socket_t ) ~0U ) + +/** + * @anchor SocketDomains + * @name SocketDomains + * + * @brief Options for the lDomain parameter of SOCKETS_Socket() + * function. + * + * These select the protocol family to be used for communication. + */ +/**@{ */ +#define SOCKETS_AF_INET ( 2 ) /*!< IPv4 Internet Protocols. */ +#define SOCKETS_PF_INET SOCKETS_AF_INET /*!< IPv4 Internet Protocol. */ +#define SOCKETS_AF_INET6 ( 10 ) /*!< IPv6 Internet Protocols. This option is currently not supported. */ +/**@} */ + +/** + * @anchor SocketTypes + * @name SocketTypes + * + * @brief Options for the lType parameter of SOCKETS_Socket() + * function. + * + * These specify the communication semantics. + */ +/**@{ */ +#define SOCKETS_SOCK_DGRAM ( 2 ) /*!< Datagram. */ +#define SOCKETS_SOCK_STREAM ( 1 ) /*!< Byte-stream. */ +/**@} */ + +/** + * @anchor Protocols + * @name Protocols + * + * @brief Options for the lProtocol parameter of SOCKETS_Socket() function. + * + */ +/**@{ */ +#define SOCKETS_IPPROTO_UDP ( 17 ) /*!< UDP. This option is currently not supported. */ +#define SOCKETS_IPPROTO_TCP ( 6 ) /*!< TCP. */ +/**@} */ + +/** + * @anchor SetSockOptOptions + * @name SetSockOptOptions + * + * @brief Options for lOptionName in SOCKETS_SetSockOpt(). + * + */ +/**@{ */ +#define SOCKETS_SO_RCVTIMEO ( 0 ) /**< Set the receive timeout. */ +#define SOCKETS_SO_SNDTIMEO ( 1 ) /**< Set the send timeout. */ +#define SOCKETS_SO_SNDBUF ( 4 ) /**< Set the size of the send buffer (TCP only). */ +#define SOCKETS_SO_RCVBUF ( 5 ) /**< Set the size of the receive buffer (TCP only). */ +#define SOCKETS_SO_SERVER_NAME_INDICATION ( 6 ) /**< Toggle client use of TLS SNI. */ +#define SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE ( 7 ) /**< Override default TLS server certificate trust. Must be PEM encoded and length must include null terminator. */ +#define SOCKETS_SO_REQUIRE_TLS ( 8 ) /**< Toggle client enforcement of TLS. */ +#define SOCKETS_SO_NONBLOCK ( 9 ) /**< Socket is nonblocking. */ +#define SOCKETS_SO_ALPN_PROTOCOLS ( 10 ) /**< Application protocol list to be included in TLS ClientHello. */ +#define SOCKETS_SO_WAKEUP_CALLBACK ( 17 ) /**< Set the callback to be called whenever there is data available on the socket for reading. */ +#define SOCKETS_SO_TCPKEEPALIVE ( 18 ) /**< Enable or Disable TCP keep-alive functionality. */ +#define SOCKETS_SO_TCPKEEPALIVE_INTERVAL ( 19 ) /**< Set the time in seconds between individual TCP keep-alive probes. */ +#define SOCKETS_SO_TCPKEEPALIVE_COUNT ( 20 ) /**< Set the maximum number of keep-alive probes TCP should send before dropping the connection. */ +#define SOCKETS_SO_TCPKEEPALIVE_IDLE_TIME ( 21 ) /**< Set the time in seconds for which the connection needs to remain idle before TCP starts sending keep-alive probes. */ + +/**@} */ + +/** + * @anchor ShutdownFlags
+ * @name ShutdownFlags + * + * @brief Options for the ulHow parameter in SOCKETS_Shutdown(). + */ +/**@{ */ +#define SOCKETS_SHUT_RD ( 0 ) /**< No further receives. */ +#define SOCKETS_SHUT_WR ( 1 ) /**< No further sends. */ +#define SOCKETS_SHUT_RDWR ( 2 ) /**< No further send or receive. */ +/**@} */ + +/** + * @brief Maximum length of an ASCII DNS name. + */ +#define securesocketsMAX_DNS_NAME_LENGTH ( 253 ) + +/** + * @ingroup SecureSockets_datatypes_paramstructs + * @brief Socket address. + * + * \sa PORT_SPECIFIC_LINK + */ +typedef struct SocketsSockaddr +{ + uint8_t ucLength; /**< Length of SocketsSockaddr structure. */ + uint8_t ucSocketDomain; /**< Only SOCKETS_AF_INET is supported. */ + uint16_t usPort; /**< Port number. Convention is to call this sin_port. */ + uint32_t ulAddress; /**< IP Address. Convention is to call this sin_addr. */ +} SocketsSockaddr_t; + +/** + * @brief Well-known port numbers. + */ +#define securesocketsDEFAULT_TLS_DESTINATION_PORT 443 + +/** + * @brief Secure Sockets library initialization function. + * + * This function does general initialization and setup. It must be called once + * and only once before calling any other function. + * + * @return + * * `pdPASS` if everything succeeds + * * `pdFAIL` otherwise. + */ +extern BaseType_t SOCKETS_Init( void ); + +/** + * @brief Creates a TCP socket. + * + * See the [FreeRTOS+TCP networking tutorial] + * (https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Networking_Tutorial.html) + * for more information on TCP sockets. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @sa SOCKETS_Close() + * + * @param[in] lDomain Must be set to SOCKETS_AF_INET. See @ref SocketDomains. + * @param[in] lType Set to SOCKETS_SOCK_STREAM to create a TCP socket. + * No other value is valid. See @ref SocketTypes. + * @param[in] lProtocol Set to SOCKETS_IPPROTO_TCP to create a TCP socket. + * No other value is valid. See @ref Protocols. + * + * @return + * * If a socket is created successfully, then the socket handle is + * returned + * * @ref SOCKETS_INVALID_SOCKET is returned if an error occurred. + */ + +/* + * This call allocates memory and claims a socket resource. + */ +/* @[declare_secure_sockets_socket] */ +Socket_t SOCKETS_Socket( int32_t lDomain, + int32_t lType, + int32_t lProtocol ); +/* @[declare_secure_sockets_socket] */ + +/** + * @brief Bind a TCP socket. + * + * See the [FreeRTOS+TCP networking tutorial] + * (https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Networking_Tutorial.html) + * for more information on TCP sockets. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @sa SOCKETS_Bind() + * A pre-configured source port allows customers to bind to the specified local port instead of ephemeral port + * for security and packet filter reasons. + * + * Limitations: + * + * i. The caller of SOCKETS_Bind() API should make sure the socket address has the correct local IP address for the interface. + * ii. Some source ports may be unavailable depending on the TCP/IP stack implementation. + * + * NOTE: If the SOCKETS_Bind() API binds to a source port in ephemeral port range, and the caller calls SOCKETS_Bind() API + * before SOCKETS_Connect() API, then a conflict of source port arises as another TCP connection + * may pick the the same chosen port via tcp_new_port() API ( by scanning its internal TCP connection list ) + * + * + * @param[in] xSocket The handle of the socket to which specified address to be bound. + * @param[in] pxAddress A pointer to a SocketsSockaddr_t structure that contains + * the address and port to be bound to the socket. + * @param[in] xAddressLength Should be set to sizeof( @ref SocketsSockaddr_t ). + * + * @return + * * If the bind was successful then SOCKETS_ERROR_NONE is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_bind] */ +int32_t SOCKETS_Bind( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ); +/* @[declare_secure_sockets_bind] */ + +/** + * @brief Connects the socket to the specified IP address and port. + * + * The socket must first have been successfully created by a call to SOCKETS_Socket(). + * + * \note To create a secure socket, SOCKETS_SetSockOpt() should be called with the + * SOCKETS_SO_REQUIRE_TLS option \a before SOCKETS_Connect() is called. + * + * If this function returns an error the socket is considered invalid. + * + * \warning SOCKETS_Connect() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the socket to be connected. + * @param[in] pxAddress A pointer to a SocketsSockaddr_t structure that contains the + * the address to connect the socket to. + * @param[in] xAddressLength Should be set to sizeof( @ref SocketsSockaddr_t ). + * + * @return + * * @ref SOCKETS_ERROR_NONE if a connection is established. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_connect] */ +int32_t SOCKETS_Connect( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ); +/* @[declare_secure_sockets_connect] */ + +/** + * @brief Receive data from a TCP socket. + * + * The socket must have already been created using a call to SOCKETS_Socket() + * and connected to a remote socket using SOCKETS_Connect(). + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the socket from which data is being received. + * @param[out] pvBuffer The buffer into which the received data will be placed. + * @param[in] xBufferLength The maximum number of bytes which can be received. + * pvBuffer must be at least xBufferLength bytes long. + * @param[in] ulFlags Not currently used. Should be set to 0. + * + * @return + * * If the receive was successful then the number of bytes received (placed in the + * buffer pointed to by pvBuffer) is returned. + * * If a timeout occurred before data could be received then 0 is returned (timeout + * is set using @ref SOCKETS_SO_RCVTIMEO). + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_recv] */ +int32_t SOCKETS_Recv( Socket_t xSocket, + void * pvBuffer, + size_t xBufferLength, + uint32_t ulFlags ); +/* @[declare_secure_sockets_recv] */ + +/** + * @brief Transmit data to the remote socket. + * + * The socket must have already been created using a call to SOCKETS_Socket() and + * connected to a remote socket using SOCKETS_Connect(). + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the sending socket. + * @param[in] pvBuffer The buffer containing the data to be sent. + * @param[in] xDataLength The length of the data to be sent. + * @param[in] ulFlags Not currently used. Should be set to 0. + * + * @return + * * On success, the number of bytes actually sent is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_send] */ +int32_t SOCKETS_Send( Socket_t xSocket, + const void * pvBuffer, + size_t xDataLength, + uint32_t ulFlags ); +/* @[declare_secure_sockets_send] */ + +/** + * @brief Closes all or part of a full-duplex connection on the socket. + * + * Disable reads and writes on a connected TCP socket. A connected TCP socket must be gracefully + * shut down before it can be closed. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * \warning SOCKETS_Shutdown() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * @param[in] xSocket The handle of the socket to shutdown. + * @param[in] ulHow SOCKETS_SHUT_RD, SOCKETS_SHUT_WR or SOCKETS_SHUT_RDWR. + * @ref ShutdownFlags + * + * @return + * * If the operation was successful, 0 is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_shutdown] */ +int32_t SOCKETS_Shutdown( Socket_t xSocket, + uint32_t ulHow ); +/* @[declare_secure_sockets_shutdown] */ + +/** + * @brief Closes the socket and frees the related resources. + * + * A socket should be shutdown gracefully before it is closed, and cannot be used after it has been closed. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * \warning SOCKETS_Close() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * @param[in] xSocket The handle of the socket to close. + * + * @return + * * On success, 0 is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_close] */ +int32_t SOCKETS_Close( Socket_t xSocket ); +/* @[declare_secure_sockets_close] */ + +/** + * @brief AWS IoT ALPN protocol name for MQTT over TLS on server port 443. + */ +#define socketsAWS_IOT_ALPN_MQTT "x-amzn-mqtt-ca" + +/** + * @brief Manipulates the options for the socket. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the socket to set the option for. + * @param[in] lLevel Not currently used. Should be set to 0. + * @param[in] lOptionName See @ref SetSockOptOptions. + * @param[in] pvOptionValue A buffer containing the value of the option to set. + * @param[in] xOptionLength The length of the buffer pointed to by pvOptionValue. + * + * \warning SOCKETS_Close() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * @note Socket option support and possible values vary by port. Please see + * PORT_SPECIFIC_LINK to check the valid options and limitations of your device. + * + * - Berkeley Socket Options + * - @ref SOCKETS_SO_RCVTIMEO + * - Sets the receive timeout + * - pvOptionValue (TickType_t) is the number of milliseconds that the + * receive function should wait before timing out. + * - Setting pvOptionValue = 0 causes receive to wait forever. + * - See PORT_SPECIFIC_LINK for device limitations. + * - @ref SOCKETS_SO_SNDTIMEO + * - Sets the send timeout + * - pvOptionValue (TickType_t) is the number of milliseconds that the + * send function should wait before timing out. + * - Setting pvOptionValue = 0 causes send to wait forever. + * - See PORT_SPECIFIC_LINK for device limitations. + * - Non-Standard Options + * - @ref SOCKETS_SO_NONBLOCK + * - Makes a socket non-blocking. + * - Non-blocking connect is not supported - socket option should be + * called after connect. + * - pvOptionValue is ignored for this option. + * - @ref SOCKETS_SO_WAKEUP_CALLBACK + * - Set the callback to be called whenever there is data available on + * the socket for reading + * - This option provides an asynchronous way to handle received data + * - pvOptionValue is a pointer to the callback function + * - See PORT_SPECIFIC_LINK for device limitations. + * - Security Sockets Options + * - @ref SOCKETS_SO_REQUIRE_TLS + * - Use TLS for all connect, send, and receive on this socket. + * - This socket options MUST be set for TLS to be used, even + * if other secure socket options are set. + * - This socket option should be set before SOCKETS_Connect() is + * called. + * - pvOptionValue is ignored for this option. + * - @ref SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE + * - Set the root of trust server certificate for the socket. + * - This socket option only takes effect if @ref SOCKETS_SO_REQUIRE_TLS + * is also set. If @ref SOCKETS_SO_REQUIRE_TLS is not set, + * this option will be ignored. + * - pvOptionValue is a pointer to the formatted server certificate. + * TODO: Link to description of how to format certificates with \n + * - xOptionLength (BaseType_t) is the length of the certificate + * in bytes. + * - @ref SOCKETS_SO_SERVER_NAME_INDICATION + * - Use Server Name Indication (SNI) + * - This socket option only takes effect if @ref SOCKETS_SO_REQUIRE_TLS + * is also set. If @ref SOCKETS_SO_REQUIRE_TLS is not set, + * this option will be ignored. + * - pvOptionValue is a pointer to a string containing the hostname + * - xOptionLength is the length of the hostname string in bytes. + * - @ref SOCKETS_SO_ALPN_PROTOCOLS + * - Negotiate an application protocol along with TLS. + * - The ALPN list is expressed as an array of NULL-terminated ANSI + * strings. + * - xOptionLength is the number of items in the array. + * - @ref SOCKETS_SO_TCPKEEPALIVE + * - Enable or disable the TCP keep-alive functionality. + * - pvOptionValue is the value to enable or disable Keepalive. + * - @ref SOCKETS_SO_TCPKEEPALIVE_INTERVAL + * - Set the time in seconds between individual TCP keep-alive probes. + * - pvOptionValue is the time in seconds. + * - @ref SOCKETS_SO_TCPKEEPALIVE_COUNT + * - Set the maximum number of keep-alive probes TCP should send before + * dropping the connection. + * - pvOptionValue is the maximum number of keep-alive probes. + * - @ref SOCKETS_SO_TCPKEEPALIVE_IDLE_TIME + * - Set the time in seconds for which the connection needs to remain idle + * before TCP starts sending keep-alive probes. + * - pvOptionValue is the time in seconds. + * + * @return + * * On success, 0 is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_setsockopt] */ +int32_t SOCKETS_SetSockOpt( Socket_t xSocket, + int32_t lLevel, + int32_t lOptionName, + const void * pvOptionValue, + size_t xOptionLength ); +/* @[declare_secure_sockets_setsockopt] */ + +/** + * @brief Resolve a host name using Domain Name Service. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] pcHostName The host name to resolve. + * @return + * * The IPv4 address of the specified host. + * * If an error has occurred, 0 is returned. + */ +/* @[declare_secure_sockets_gethostbyname] */ +uint32_t SOCKETS_GetHostByName( const char * pcHostName ); +/* @[declare_secure_sockets_gethostbyname] */ + + + +/** + * @brief Convert an unsigned thirty-two-bit value from host endianness to network + * endianness. + * + * @param[in] usIn The unsigned thirty-two-bit value to convert. + */ +#if defined( socketsconfigBYTE_ORDER ) && ( socketsconfigBYTE_ORDER == pdLITTLE_ENDIAN ) + #define SOCKETS_htonl( ulIn ) ( ( uint32_t ) ( ( ( ulIn & 0xFF ) << 24 ) | ( ( ulIn & 0xFF00 ) << 8 ) | ( ( ulIn & 0xFF0000 ) >> 8 ) | ( ( ulIn & 0xFF000000 ) >> 24 ) ) ) +#else + #define SOCKETS_htonl( usIn ) ( ( uint32_t ) ( usIn ) ) +#endif + +/** + * @brief Convert an unsigned thirty-two-bit value from network endianness to host + * endianness. + * + * @param[in] usIn The unsigned thirty-two-bit value to convert. + */ +#define SOCKETS_ntohl( usIn ) SOCKETS_htonl( usIn ) + + +/** + * @brief Convert an unsigned sixteen-bit value from host endianness to network + * endianness. + * + * @param[in] usIn The unsigned sixteen-bit value to convert. + */ + +#if defined( socketsconfigBYTE_ORDER ) && ( socketsconfigBYTE_ORDER == pdLITTLE_ENDIAN ) + #define SOCKETS_htons( usIn ) ( ( uint16_t ) ( ( ( usIn ) << 8U ) | ( ( usIn ) >> 8U ) ) ) +#else + #define SOCKETS_htons( usIn ) ( ( uint16_t ) ( usIn ) ) +#endif + + +/** + * @brief Convert an unsigned sixteen-bit value from network endianness to host + * endianness. + * + * @param[in] usIn The unsigned sixteen-bit value to convert. + */ +#define SOCKETS_ntohs( usIn ) SOCKETS_htons( usIn ) + +/** + * @brief Convert an IP address expressed as four separate numeric octets into a an IP address expressed as a 32-bit number in network byte order + * (for example 192, 168, 0, 100) + * + * @param[in] ucOctet0 0th IP Octet + * @param[in] ucOctet1 1st IP Octet + * @param[in] ucOctet2 2nd IP Octet + * @param[in] ucOctet3 3rd IP Octet + */ +#if defined( socketsconfigBYTE_ORDER ) && ( socketsconfigBYTE_ORDER == pdLITTLE_ENDIAN ) + + #define SOCKETS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \ + ( ( ( ( uint32_t ) ( ucOctet3 ) ) << 24UL ) | \ + ( ( ( uint32_t ) ( ucOctet2 ) ) << 16UL ) | \ + ( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \ + ( ( uint32_t ) ( ucOctet0 ) ) ) + +/** + * @brief Convert an IP address expressed as a 32-bit number in network byte order to a string in decimal dot notation. + * (for example "192.168.0.100") + * + * @param[in] ulIPAddress An IP address expressed as a 32-bit value in network byte order. + * @param[in] pucBuffer A pointer to a buffer into which the IP address will be written in decimal dot notation. + */ + #define SOCKETS_inet_ntoa( ulIPAddress, pucBuffer ) \ + sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \ + ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) ) + +#else /* socketsconfigBYTE_ORDER. */ + + #define SOCKETS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \ + ( ( ( ( uint32_t ) ( ucOctet0 ) ) << 24UL ) | \ + ( ( ( uint32_t ) ( ucOctet1 ) ) << 16UL ) | \ + ( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \ + ( ( uint32_t ) ( ucOctet3 ) ) ) + +/** + * @brief Convert an IP address expressed as a 32-bit number in network byte order to a string in decimal dot notation. + * (for example "192.168.0.100") + * + * @param[in] ulIPAddress An IP address expressed as a 32-bit value in network byte order. + * @param[in] pucBuffer A pointer to a buffer into which the IP address will be written in decimal dot notation. + */ + #define SOCKETS_inet_ntoa( ulIPAddress, pucBuffer ) \ + sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \ + ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) ) + +#endif /* socketsconfigBYTE_ORDER. */ + +/* + #ifdef __cplusplus + * } + #endif + */ + +#endif /* _AWS_SECURE_SOCKETS_H_ */ diff --git a/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h b/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h new file mode 100644 index 0000000..36227de --- /dev/null +++ b/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h @@ -0,0 +1,72 @@ +/* + * FreeRTOS Secure Sockets V1.3.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_secure_sockets_config_defaults.h + * @brief Ensures that the required sockets configuration options are supplied + * and the optional ones are set to sane values if the user does not supply. + */ + +#ifndef AWS_INC_SECURE_SOCKETS_CONFIG_DEFAULTS_H_ +#define AWS_INC_SECURE_SOCKETS_CONFIG_DEFAULTS_H_ + +/** + * @brief Byte order of the target MCU must be defined. + * + * Valid values are pdLITTLE_ENDIAN and pdBIG_ENDIAN. + */ +#ifndef socketsconfigBYTE_ORDER + #error "socketsconfigBYTE_ORDER must be defined." +#endif + +/** + * @brief Default socket send timeout. + * + * The user can change the send timeout for a socket using the SOCKETS_SetSockOpt API + * with the SOCKETS_SO_SNDTIMEO option. + */ +#ifndef socketsconfigDEFAULT_SEND_TIMEOUT + #define socketsconfigDEFAULT_SEND_TIMEOUT ( 10000 ) +#endif + +/** + * @brief Default socket receive timeout. + * + * The user can change the receive timeout for a socket using the SOCKETS_SetSockOpt API + * with the SOCKETS_SO_RCVTIMEO option. + */ +#ifndef socketsconfigDEFAULT_RECV_TIMEOUT + #define socketsconfigDEFAULT_RECV_TIMEOUT ( 10000 ) +#endif + +/** + * @brief By default, metrics of secure socket is disabled. + * + */ +#ifndef AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED + #define AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED ( 0 ) +#endif + +#endif /* AWS_INC_SECURE_SOCKETS_CONFIG_DEFAULTS_H_ */ diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/include/skipGeneric.h b/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h similarity index 58% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/include/skipGeneric.h rename to bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h index 13620b5..5103561 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/include/skipGeneric.h +++ b/bsp/aws_libraries/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * FreeRTOS Secure Sockets V1.3.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -18,32 +18,26 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org */ -#ifndef SKIPGENERIC_H_ -#define SKIPGENERIC_H_ +#ifndef _AWS_SECURE_SOCKETS_WRAPPER_METRICS_ +#define _AWS_SECURE_SOCKETS_WRAPPER_METRICS_ -#include -#include "core_json_annex.h" +/* This file redefines Secure Sockets functions to be called through a wrapper macro, + * but only if metrics is enabled explicitly. */ +#if AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED == 1 -/** - * @brief Advance buffer index beyond some minimum value. - * - * This function models the behavior of most of the skip* functions - * from core_json.c. - * - * @param[in] buf The buffer to parse. - * @param[in,out] start The index at which to begin. - * @param[in] max The size of the buffer. - * @param[in] min The smallest size required for a true result. - * - * @return true or false, nondeterministically - * if true, the index in start will increment by at least min - * but will not exceed max. - */ -bool skipGeneric( const char * buf, - size_t * start, - size_t max, - size_t min ); +/* This macro is included in aws_secure_socket.c and aws_secure_socket_wrapper_metrics.c. + * It will prevent the redefine in those source files. */ + #ifndef _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE + #define SOCKETS_Init Sockets_MetricsInit + #define SOCKETS_Connect Sockets_MetricsConnect + #define SOCKETS_Shutdown Sockets_MetricsShutdown + #endif + +#endif -#endif /* ifndef SKIPGENERIC_H_ */ +#endif /* ifndef _AWS_SECURE_SOCKETS_WRAPPER_METRICS_ */ diff --git a/bsp/aws_libraries/abstractions/secure_sockets/lwip/iot_secure_sockets.c b/bsp/aws_libraries/abstractions/secure_sockets/lwip/iot_secure_sockets.c new file mode 100644 index 0000000..011eb86 --- /dev/null +++ b/bsp/aws_libraries/abstractions/secure_sockets/lwip/iot_secure_sockets.c @@ -0,0 +1,1063 @@ +/* + * FreeRTOS Secure Sockets V1.3.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_secure_sockets.c + * @brief Secure Socket interface implementation. + */ + +/* Secure Socket interface includes. */ +#include "iot_secure_sockets.h" + + +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" +#include "lwip/err.h" + +#include "iot_tls.h" + +#include "iot_atomic.h" + +#include "FreeRTOSConfig.h" + +#include "task.h" + +#include "event_groups.h" + +#include + +/* + * The loop delay used while waiting for DNS resolution + * to complete. + */ + +#define lwip_dns_resolver_LOOP_DELAY_MS ( 250 ) +#define lwip_dns_resolver_LOOP_DELAY_TICKS ( ( TickType_t ) lwip_dns_resolver_LOOP_DELAY_MS / portTICK_PERIOD_MS ) + +/* + * The maximum time to wait for DNS resolution + * to complete. + */ +#define lwip_dns_resolver_MAX_WAIT_SECONDS ( 20 ) + +/* + * The maximum number of loop iterations to wait for DNS + * resolution to complete. + */ +#define lwip_dns_resolver_MAX_WAIT_CYCLES \ + ( ( ( lwip_dns_resolver_MAX_WAIT_SECONDS ) * 1000 ) / \ + ( lwip_dns_resolver_LOOP_DELAY_MS ) ) + +/*-----------------------------------------------------------*/ + +#define SS_STATUS_CONNECTED ( 1 ) +#define SS_STATUS_SECURED ( 2 ) + +#define SECURE_SOCKETS_SELECT_WAIT_SEC ( 10 ) + +#define SOCKETS_START_DELETION ( 0x01 ) +#define SOCKETS_COMPLETE_DELETION ( 0x02 ) + +/* + * secure socket context. + */ +typedef enum E_AWS_SOCkET_RX_STATE +{ + SST_RX_IDLE, + SST_RX_READY, + SST_RX_CLOSING, + SST_RX_CLOSED, +} T_AWS_SOCKET_RX_STATE; + +typedef struct _ss_ctx_t +{ + int ip_socket; + + int state; + unsigned int status; + int send_flag; + int recv_flag; + + TaskHandle_t rx_handle; + void ( * rx_callback )( Socket_t pxSocket ); + EventGroupHandle_t rx_EventGroup; + + bool enforce_tls; + void * tls_ctx; + char * destination; + + char * server_cert; + int server_cert_len; + + char ** ppcAlpnProtocols; + uint32_t ulAlpnProtocolsCount; + uint32_t ulRefcount; +} ss_ctx_t; + +/*-----------------------------------------------------------*/ + +/*#define SUPPORTED_DESCRIPTORS (2) */ + +/*-----------------------------------------------------------*/ + +/*static int8_t sockets_allocated = SUPPORTED_DESCRIPTORS; */ +static int8_t sockets_allocated = socketsconfigDEFAULT_MAX_NUM_SECURE_SOCKETS; + + +/*-----------------------------------------------------------*/ + +/* + * convert from system ticks to seconds. + */ +#define TICK_TO_S( _t_ ) ( ( _t_ ) / configTICK_RATE_HZ ) + +/* + * convert from system ticks to micro seconds. + */ +#define TICK_TO_US( _t_ ) ( ( _t_ ) * 1000 / configTICK_RATE_HZ * 1000 ) + +/*-----------------------------------------------------------*/ + +/* + * @brief Sockets close + */ +static void prvSocketsClose( ss_ctx_t * ctx ) +{ + uint32_t ulProtocol; + + sockets_allocated++; + + /* Clean-up application protocol array. */ + if( NULL != ctx->ppcAlpnProtocols ) + { + for( ulProtocol = 0; + ulProtocol < ctx->ulAlpnProtocolsCount; + ulProtocol++ ) + { + if( NULL != ctx->ppcAlpnProtocols[ ulProtocol ] ) + { + vPortFree( ctx->ppcAlpnProtocols[ ulProtocol ] ); + } + } + + vPortFree( ctx->ppcAlpnProtocols ); + } + + if( true == ctx->enforce_tls ) + { + TLS_Cleanup( ctx->tls_ctx ); + } + + if( ctx->server_cert ) + { + vPortFree( ctx->server_cert ); + } + + if( ctx->destination ) + { + vPortFree( ctx->destination ); + } + + vPortFree( ctx ); +} + +/* + * @brief Decrement ctx refcount and call release function if the count is 1 ( + * last user of the ctx) + */ +static void prvDecrementRefCount( ss_ctx_t * ctx ) +{ + if( Atomic_Decrement_u32( &ctx->ulRefcount ) == 1 ) + { + prvSocketsClose( ctx ); + } +} + +/* + * @brief Increment ctx refcount + */ +static void prvIncrementRefCount( ss_ctx_t * ctx ) +{ + Atomic_Increment_u32( &ctx->ulRefcount ); +} + +/* + * @brief Network send callback. + */ +static BaseType_t prvNetworkSend( void * pvContext, + const unsigned char * pucData, + size_t xDataLength ) +{ + ss_ctx_t * ctx = ( ss_ctx_t * ) pvContext; + + int ret = lwip_send( ctx->ip_socket, + pucData, + xDataLength, + ctx->send_flag ); + + return ( BaseType_t ) ret; +} + +/*-----------------------------------------------------------*/ + +/* + * @brief Network receive callback. + */ +static BaseType_t prvNetworkRecv( void * pvContext, + unsigned char * pucReceiveBuffer, + size_t xReceiveLength ) +{ + ss_ctx_t * ctx; + + ctx = ( ss_ctx_t * ) pvContext; + + configASSERT( ctx->ip_socket >= 0 ); + + int ret = lwip_recv( ctx->ip_socket, + pucReceiveBuffer, + xReceiveLength, + ctx->recv_flag ); + + if( -1 == ret ) + { + /* + * 1. EWOULDBLOCK if the socket is NON-blocking, but there is no data + * when recv is called. + * 2. EAGAIN if the socket would block and have waited long enough but + * packet is not received. + */ + if( ( errno == EWOULDBLOCK ) || ( errno == EAGAIN ) ) + { + return SOCKETS_ERROR_NONE; /* timeout or would block */ + } + + /* + * socket is not connected. + */ + if( errno == EBADF ) + { + return SOCKETS_ECLOSED; + } + } + + if( ( 0 == ret ) && ( errno == ENOTCONN ) ) + { + ret = SOCKETS_ECLOSED; + } + + return ( BaseType_t ) ret; +} + +/*-----------------------------------------------------------*/ + +static void vTaskRxSelect( void * param ) +{ + ss_ctx_t * ctx = ( ss_ctx_t * ) param; + int s = ctx->ip_socket; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + fd_set err_fds; + + FD_ZERO( &read_fds ); + FD_ZERO( &write_fds ); + FD_ZERO( &err_fds ); + + FD_SET( s, &read_fds ); + FD_SET( s, &err_fds ); + + ctx->state = SST_RX_READY; + + tv.tv_sec = SECURE_SOCKETS_SELECT_WAIT_SEC; + tv.tv_usec = 0; + + while( 1 ) + { + if( ctx->state == SST_RX_CLOSING ) + { + ctx->state = SST_RX_CLOSED; + break; + } + + if( lwip_select( s + 1, &read_fds, &write_fds, &err_fds, &tv ) == -1 ) + { + break; + } + + if( FD_ISSET( s, &read_fds ) ) + { + ctx->rx_callback( ( Socket_t ) ctx ); + } + + if( xEventGroupWaitBits( ctx->rx_EventGroup, SOCKETS_START_DELETION, pdTRUE, pdTRUE, 0 ) == SOCKETS_START_DELETION ) + { + /* Inform the main task that the event has been received. */ + ( void ) xEventGroupSetBits( ctx->rx_EventGroup, SOCKETS_COMPLETE_DELETION ); + break; + } + } + + prvDecrementRefCount( ctx ); + + vTaskDelete( NULL ); +} + + +/*-----------------------------------------------------------*/ + +static void prvRxSelectSet( ss_ctx_t * ctx, + const void * pvOptionValue ) +{ + BaseType_t xReturned; + TaskHandle_t xHandle = NULL; + configSTACK_DEPTH_TYPE xStackDepth = socketsconfigRECEIVE_CALLBACK_TASK_STACK_DEPTH; + + ctx->rx_callback = ( void ( * )( Socket_t ) )pvOptionValue; + + prvIncrementRefCount( ctx ); + + ctx->rx_EventGroup = xEventGroupCreate(); + + configASSERT( ctx->rx_EventGroup != NULL ); + + xReturned = xTaskCreate( vTaskRxSelect, /* pvTaskCode */ + "rxs", /* pcName */ + xStackDepth, /* usStackDepth */ + ctx, /* pvParameters */ + 1, /* uxPriority */ + &xHandle ); /* pxCreatedTask */ + + configASSERT( xReturned == pdPASS ); + configASSERT( xHandle != NULL ); + + ctx->rx_handle = xHandle; +} + +/*-----------------------------------------------------------*/ + +static void prvRxSelectClear( ss_ctx_t * ctx ) +{ + /* Inform the vTaskRxSelect to delete itself. */ + xEventGroupSetBits( ctx->rx_EventGroup, SOCKETS_START_DELETION ); + + /* Wait for the task to delete itself. */ + while( xEventGroupWaitBits( ctx->rx_EventGroup, + SOCKETS_COMPLETE_DELETION, + pdTRUE, + pdTRUE, + pdMS_TO_TICKS( SECURE_SOCKETS_SELECT_WAIT_SEC * 1000 ) ) != + SOCKETS_COMPLETE_DELETION ) + { + /* Continue waiting for the task to delete itself. */ + } + + /* Reset the handle of the task to NULL. */ + ctx->rx_handle = NULL; + + /* Delete the event group. */ + vEventGroupDelete( ctx->rx_EventGroup ); + + /* Remove the reference to the callback. */ + ctx->rx_callback = NULL; +} + +/*-----------------------------------------------------------*/ + +Socket_t SOCKETS_Socket( int32_t lDomain, + int32_t lType, + int32_t lProtocol ) +{ + ss_ctx_t * ctx; + + configASSERT( lDomain == SOCKETS_AF_INET ); + configASSERT( lType == SOCKETS_SOCK_STREAM ); + configASSERT( lProtocol == SOCKETS_IPPROTO_TCP ); + + if( ( lDomain != SOCKETS_AF_INET ) || + ( lType != SOCKETS_SOCK_STREAM ) || + ( lProtocol != SOCKETS_IPPROTO_TCP ) || + ( sockets_allocated <= 0 ) + ) + { + return SOCKETS_INVALID_SOCKET; + } + + ctx = ( ss_ctx_t * ) pvPortMalloc( sizeof( *ctx ) ); + + if( ctx ) + { + memset( ctx, 0, sizeof( *ctx ) ); + + ctx->ip_socket = lwip_socket( lDomain, lType, lProtocol ); + + if( ctx->ip_socket >= 0 ) + { + ctx->ulRefcount = 1; + sockets_allocated--; + return ( Socket_t ) ctx; + } + + vPortFree( ctx ); + } + + return ( Socket_t ) SOCKETS_INVALID_SOCKET; +} + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Bind( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ) +{ + ss_ctx_t * ctx; + int32_t ret; + struct sockaddr_in sa_addr = { 0 }; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + configPRINTF( ( "TCP socket Invalid\n" ) ); + return SOCKETS_EINVAL; + } + + if( pxAddress == NULL ) + { + configPRINTF( ( "TCP socket Invalid Address\n" ) ); + return SOCKETS_EINVAL; + } + + ctx = ( ss_ctx_t * ) xSocket; + + if( NULL == ctx ) + { + configPRINTF( ( "Invalid secure socket passed: Socket=%p\n", ctx ) ); + return SOCKETS_EINVAL; + } + + if( 0 > ctx->ip_socket ) + { + configPRINTF( ( "TCP socket Invalid index\n" ) ); + return SOCKETS_EINVAL; + } + + /* + * Setting SO_REUSEADDR socket option in order to be able to bind to the same ip:port again + * without netconn_bind failing. + */ + #if SO_REUSE + ret = lwip_setsockopt( ctx->ip_socket, SOL_SOCKET, SO_REUSEADDR, &( uint32_t ) { 1 }, sizeof( uint32_t ) ); + + if( 0 > ret ) + { + return SOCKETS_SOCKET_ERROR; + } + #endif /* SO_REUSE */ + + sa_addr.sin_family = pxAddress->ucSocketDomain ? pxAddress->ucSocketDomain : AF_INET; + sa_addr.sin_addr.s_addr = pxAddress->ulAddress; + sa_addr.sin_port = pxAddress->usPort; + + ret = lwip_bind( ctx->ip_socket, ( struct sockaddr * ) &sa_addr, sizeof( sa_addr ) ); + + if( 0 > ret ) + { + configPRINTF( ( "lwip_bind fail :%d\n", ret ) ); + return SOCKETS_SOCKET_ERROR; + } + + return SOCKETS_ERROR_NONE; +} + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Connect( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ) +{ + ss_ctx_t * ctx; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + return SOCKETS_EINVAL; + } + + /* removed because qualification program wants invalid length to go through */ + #if 0 + if( ( NULL == pxAddress ) || ( 0 == xAddressLength ) ) + { + return SOCKETS_EINVAL; + } + #endif + + if( pxAddress == NULL ) + { + return SOCKETS_EINVAL; + } + + /* support only SOCKETS_AF_INET for now */ + pxAddress->ucSocketDomain = SOCKETS_AF_INET; + + ctx = ( ss_ctx_t * ) xSocket; + configASSERT( ctx->ip_socket >= 0 ); + + struct sockaddr_in sa_addr = { 0 }; + int ret; + sa_addr.sin_family = pxAddress->ucSocketDomain; + sa_addr.sin_addr.s_addr = pxAddress->ulAddress; + sa_addr.sin_port = pxAddress->usPort; + + ret = lwip_connect( ctx->ip_socket, + ( struct sockaddr * ) &sa_addr, + sizeof( sa_addr ) ); + + if( 0 == ret ) + { + TLSParams_t tls_params = { 0 }; + BaseType_t status; + + ctx->status |= SS_STATUS_CONNECTED; + + if( !ctx->enforce_tls ) + { + return SOCKETS_ERROR_NONE; + } + + tls_params.ulSize = sizeof( tls_params ); + tls_params.pcDestination = ctx->destination; + tls_params.pcServerCertificate = ctx->server_cert; + tls_params.ulServerCertificateLength = ctx->server_cert_len; + tls_params.pvCallerContext = ctx; + tls_params.pxNetworkRecv = prvNetworkRecv; + tls_params.pxNetworkSend = prvNetworkSend; + tls_params.ppcAlpnProtocols = ( const char ** ) ctx->ppcAlpnProtocols; + tls_params.ulAlpnProtocolsCount = ctx->ulAlpnProtocolsCount; + + status = TLS_Init( &ctx->tls_ctx, &tls_params ); + + if( pdFREERTOS_ERRNO_NONE != status ) + { + configPRINTF( ( "TLS_Init fail\n" ) ); + return SOCKETS_SOCKET_ERROR; + } + + status = TLS_Connect( ctx->tls_ctx ); + + if( pdFREERTOS_ERRNO_NONE == status ) + { + ctx->status |= SS_STATUS_SECURED; + return SOCKETS_ERROR_NONE; + } + else + { + configPRINTF( ( "TLS_Connect fail (0x%x, %s)\n", + ( unsigned int ) -status, + ctx->destination ? ctx->destination : "NULL" ) ); + } + } + else + { + configPRINTF( ( "LwIP connect fail %d %d\n", ret, errno ) ); + } + + return SOCKETS_SOCKET_ERROR; +} + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Recv( Socket_t xSocket, + void * pvBuffer, + size_t xBufferLength, + uint32_t ulFlags ) +{ + ss_ctx_t * ctx = ( ss_ctx_t * ) xSocket; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + return SOCKETS_SOCKET_ERROR; + } + + if( ( NULL == pvBuffer ) || ( 0 == xBufferLength ) ) + { + return SOCKETS_EINVAL; + } + + if( ( ctx->status & SS_STATUS_CONNECTED ) != SS_STATUS_CONNECTED ) + { + return SOCKETS_ENOTCONN; + } + + ctx->recv_flag = ulFlags; + + configASSERT( ctx->ip_socket >= 0 ); + + if( ctx->enforce_tls ) + { + /* Receive through TLS pipe, if negotiated. */ + return TLS_Recv( ctx->tls_ctx, pvBuffer, xBufferLength ); + } + else + { + return prvNetworkRecv( ( void * ) ctx, pvBuffer, xBufferLength ); + } +} + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Send( Socket_t xSocket, + const void * pvBuffer, + size_t xDataLength, + uint32_t ulFlags ) +{ + ss_ctx_t * ctx; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + return SOCKETS_SOCKET_ERROR; + } + + if( ( NULL == pvBuffer ) || ( 0 == xDataLength ) ) + { + return SOCKETS_EINVAL; + } + + ctx = ( ss_ctx_t * ) xSocket; + + if( ( ctx->status & SS_STATUS_CONNECTED ) != SS_STATUS_CONNECTED ) + { + return SOCKETS_ENOTCONN; + } + + configASSERT( ctx->ip_socket >= 0 ); + ctx->send_flag = ulFlags; + + if( ctx->enforce_tls ) + { + /* Send through TLS pipe, if negotiated. */ + return TLS_Send( ctx->tls_ctx, pvBuffer, xDataLength ); + } + else + { + return prvNetworkSend( ( void * ) ctx, pvBuffer, xDataLength ); + } +} + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Shutdown( Socket_t xSocket, + uint32_t ulHow ) +{ + ss_ctx_t * ctx; + int ret; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + return SOCKETS_EINVAL; + } + + ctx = ( ss_ctx_t * ) xSocket; + + configASSERT( ctx->ip_socket >= 0 ); + ret = lwip_shutdown( ctx->ip_socket, ( int ) ulHow ); + + if( 0 > ret ) + { + return SOCKETS_SOCKET_ERROR; + } + + return SOCKETS_ERROR_NONE; +} + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Close( Socket_t xSocket ) +{ + ss_ctx_t * ctx; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + return SOCKETS_EINVAL; + } + + ctx = ( ss_ctx_t * ) xSocket; + ctx->state = SST_RX_CLOSING; + + lwip_close( ctx->ip_socket ); + prvDecrementRefCount( ctx ); + + return SOCKETS_ERROR_NONE; +} + + +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_SetSockOpt( Socket_t xSocket, + int32_t lLevel, + int32_t lOptionName, + const void * pvOptionValue, + size_t xOptionLength ) +{ + ss_ctx_t * ctx; + int ret = 0; + char ** ppcAlpnIn = ( char ** ) pvOptionValue; + size_t xLength = 0; + uint32_t ulProtocol; + + if( SOCKETS_INVALID_SOCKET == xSocket ) + { + return SOCKETS_EINVAL; + } + + ctx = ( ss_ctx_t * ) xSocket; + + configASSERT( ctx->ip_socket >= 0 ); + + switch( lOptionName ) + { + case SOCKETS_SO_RCVTIMEO: + case SOCKETS_SO_SNDTIMEO: + { + TickType_t ticks; + struct timeval tv; + + ticks = *( ( const TickType_t * ) pvOptionValue ); + + tv.tv_sec = TICK_TO_S( ticks ); + tv.tv_usec = TICK_TO_US( ticks % configTICK_RATE_HZ ); + + ret = lwip_setsockopt( ctx->ip_socket, + SOL_SOCKET, + lOptionName == SOCKETS_SO_RCVTIMEO ? + SO_RCVTIMEO : SO_SNDTIMEO, + ( struct timeval * ) &tv, + sizeof( tv ) ); + + if( 0 != ret ) + { + return SOCKETS_EINVAL; + } + + break; + } + + case SOCKETS_SO_NONBLOCK: + { + int opt; + + if( ( ctx->status & SS_STATUS_CONNECTED ) != SS_STATUS_CONNECTED ) + { + return SOCKETS_ENOTCONN; + } + + opt = 1; + + ret = lwip_ioctl( ctx->ip_socket, FIONBIO, &opt ); + + if( 0 != ret ) + { + return SOCKETS_EINVAL; + } + + break; + } + + case SOCKETS_SO_REQUIRE_TLS: + + if( ctx->status & SS_STATUS_CONNECTED ) + { + return SOCKETS_EISCONN; + } + + ctx->enforce_tls = true; + break; + + case SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE: + + if( ctx->status & SS_STATUS_CONNECTED ) + { + return SOCKETS_EISCONN; + } + + if( ( NULL == pvOptionValue ) || ( 0 == xOptionLength ) ) + { + return SOCKETS_EINVAL; + } + + if( ctx->server_cert ) + { + vPortFree( ctx->server_cert ); + } + + ctx->server_cert = pvPortMalloc( xOptionLength + 1 ); + + if( NULL == ctx->server_cert ) + { + return SOCKETS_ENOMEM; + } + + memset( ctx->server_cert, 0, xOptionLength + 1 ); + memcpy( ctx->server_cert, pvOptionValue, xOptionLength ); + ctx->server_cert_len = xOptionLength; + + break; + + case SOCKETS_SO_SERVER_NAME_INDICATION: + + if( ctx->status & SS_STATUS_CONNECTED ) + { + return SOCKETS_EISCONN; + } + + if( ( NULL == pvOptionValue ) || ( 0 == xOptionLength ) ) + { + return SOCKETS_EINVAL; + } + + if( ctx->destination ) + { + vPortFree( ctx->destination ); + } + + ctx->destination = pvPortMalloc( xOptionLength + 1 ); + + if( NULL == ctx->destination ) + { + return SOCKETS_ENOMEM; + } + + memcpy( ctx->destination, pvOptionValue, xOptionLength ); + ctx->destination[ xOptionLength ] = '\0'; + + break; + + case SOCKETS_SO_WAKEUP_CALLBACK: + + if( ( xOptionLength == sizeof( void * ) ) && + ( pvOptionValue != NULL ) ) + { + prvRxSelectSet( ctx, pvOptionValue ); + } + else + { + prvRxSelectClear( ctx ); + } + + break; + + case SOCKETS_SO_ALPN_PROTOCOLS: + + /* Do not set the ALPN option if the socket is already connected. */ + if( ctx->status & SS_STATUS_CONNECTED ) + { + return SOCKETS_EISCONN; + } + + /* Allocate a sufficiently long array of pointers. */ + ctx->ulAlpnProtocolsCount = 1 + xOptionLength; + + if( NULL == ( ctx->ppcAlpnProtocols = + ( char ** ) pvPortMalloc( ctx->ulAlpnProtocolsCount * + sizeof( char * ) ) ) ) + { + return SOCKETS_ENOMEM; + } + else + { + memset( ctx->ppcAlpnProtocols, + 0x00, + ctx->ulAlpnProtocolsCount * sizeof( char * ) ); + } + + /* Copy each protocol string. */ + for( ulProtocol = 0; ( ulProtocol < ctx->ulAlpnProtocolsCount - 1 ); + ulProtocol++ ) + { + xLength = strlen( ppcAlpnIn[ ulProtocol ] ); + + if( NULL == ( ctx->ppcAlpnProtocols[ ulProtocol ] = + ( char * ) pvPortMalloc( 1 + xLength ) ) ) + { + ctx->ppcAlpnProtocols[ ulProtocol ] = NULL; + return SOCKETS_ENOMEM; + } + else + { + memcpy( ctx->ppcAlpnProtocols[ ulProtocol ], + ppcAlpnIn[ ulProtocol ], + xLength ); + ctx->ppcAlpnProtocols[ ulProtocol ][ xLength ] = '\0'; + } + } + + break; + + case SOCKETS_SO_TCPKEEPALIVE: + + ret = lwip_setsockopt( ctx->ip_socket, + SOL_SOCKET, + SO_KEEPALIVE, + pvOptionValue, + sizeof( int ) ); + + break; + + #if LWIP_TCP_KEEPALIVE + case SOCKETS_SO_TCPKEEPALIVE_INTERVAL: + + ret = lwip_setsockopt( ctx->ip_socket, + IPPROTO_TCP, + TCP_KEEPINTVL, + pvOptionValue, + sizeof( int ) ); + + break; + + case SOCKETS_SO_TCPKEEPALIVE_COUNT: + + ret = lwip_setsockopt( ctx->ip_socket, + IPPROTO_TCP, + TCP_KEEPCNT, + pvOptionValue, + sizeof( int ) ); + + break; + + case SOCKETS_SO_TCPKEEPALIVE_IDLE_TIME: + + ret = lwip_setsockopt( ctx->ip_socket, + IPPROTO_TCP, + TCP_KEEPIDLE, + pvOptionValue, + sizeof( int ) ); + + break; + #endif /* if LWIP_TCP_KEEPALIVE */ + + + default: + return SOCKETS_ENOPROTOOPT; + } + + if( 0 > ret ) + { + return SOCKETS_SOCKET_ERROR; + } + + return ret; +} + +/*-----------------------------------------------------------*/ + +/* + * Lwip DNS Found callback, compatible with type "dns_found_callback" + * declared in lwip/dns.h. + * + * NOTE: this resolves only ipv4 addresses; calls to dns_gethostbyname_addrtype() + * must specify dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4. + */ +static void lwip_dns_found_callback( const char * name, + const ip_addr_t * ipaddr, + void * callback_arg ) +{ + uint32_t * addr = ( uint32_t * ) callback_arg; + + if( ipaddr != NULL ) + { + *addr = *( ( uint32_t * ) ipaddr ); /* NOTE: IPv4 addresses only */ + } + else + { + *addr = 0; + } +} + +/*-----------------------------------------------------------*/ + +uint32_t SOCKETS_GetHostByName( const char * pcHostName ) +{ + uint32_t addr = 0; /* 0 indicates failure to caller */ + err_t xLwipError = ERR_OK; + ip_addr_t xLwipIpv4Address; + uint32_t ulDnsResolutionWaitCycles = 0; + + if( strlen( pcHostName ) <= ( size_t ) securesocketsMAX_DNS_NAME_LENGTH ) + { + xLwipError = dns_gethostbyname_addrtype( pcHostName, &xLwipIpv4Address, + lwip_dns_found_callback, ( void * ) &addr, + LWIP_DNS_ADDRTYPE_IPV4 ); + + switch( xLwipError ) + { + case ERR_OK: + addr = *( ( uint32_t * ) &xLwipIpv4Address ); /* NOTE: IPv4 addresses only */ + break; + + case ERR_INPROGRESS: + + /* + * The DNS resolver is working the request. Wait for it to complete + * or time out; print a timeout error message if configured for debug + * printing. + */ + do + { + vTaskDelay( lwip_dns_resolver_LOOP_DELAY_TICKS ); + } while( ( ulDnsResolutionWaitCycles++ < lwip_dns_resolver_MAX_WAIT_CYCLES ) && addr == 0 ); + + if( addr == 0 ) + { + configPRINTF( ( "Unable to resolve (%s) within (%ul) seconds", + pcHostName, lwip_dns_resolver_MAX_WAIT_SECONDS ) ); + } + + break; + + default: + configPRINTF( ( "Unexpected error (%lu) from dns_gethostbyname_addrtype() while resolving (%s)!", + ( uint32_t ) xLwipError, pcHostName ) ); + break; + } + } + else + { + addr = 0; + configPRINTF( ( "Host name (%s) too long!", pcHostName ) ); + } + + return addr; +} + +/*-----------------------------------------------------------*/ + +BaseType_t SOCKETS_Init( void ) +{ + BaseType_t xResult = pdPASS; + + dns_init(); + + return xResult; +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.c b/bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.c new file mode 100755 index 0000000..b94837a --- /dev/null +++ b/bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.c @@ -0,0 +1,596 @@ +/* + * FreeRTOS Transport Secure Sockets V1.0.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file transport_secure_sockets.c + * @brief Implementation of transport interface and connect/disconnect API with Secure Sockets. + */ + +/* Standard includes. */ +#include + +/* TCP/IP abstraction includes. */ +#include "transport_secure_sockets.h" + +/*-----------------------------------------------------------*/ + +/** + * @brief Each compilation unit that consumes the NetworkContext must define it. + * It should contain a single pointer to the type of your desired transport. + * When using multiple transports in the same compilation unit, define this pointer as void *. + * + * @note Transport stacks are defined in amazon-freertos/libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h. + */ +struct NetworkContext +{ + SecureSocketsTransportParams_t * pParams; +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Set up the TCP context send and receive timeouts. + * + * @param[in] tcpSocket The context to be set. + * @param[in] sendTimeoutMs Timeout for transport send. + * @param[in] recvTimeoutMs Timeout for transport recv. + * + * @return #SOCKETS_ERROR_NONE or error code from Secure Sockets. + */ +static int32_t transportTimeoutSetup( Socket_t tcpSocket, + uint32_t sendTimeoutMs, + uint32_t recvTimeoutMs ); + +/** + * @brief Sets up a TCP only connection or a TLS session on top of a TCP connection with Secure Sockets API. + * + * @param[out] pNetworkContext The output parameter to return the created network context. + * @param[in] pServerInfo Server connection info. + * @param[in] pSocketsConfig Socket configurations for the connection. + * + * @return #TRANSPORT_SOCKET_STATUS_SUCCESS on success; + * #TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER, #TRANSPORT_SOCKET_STATUS_INSUFFICIENT_MEMORY, + * #TRANSPORT_SOCKET_STATUS_CREDENTIALS_INVALID, #TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR, + * #TRANSPORT_SOCKET_STATUS_DNS_FAILURE, #TRANSPORT_SOCKET_STATUS_CONNECT_FAILURE on failure. + */ +static TransportSocketStatus_t establishConnect( NetworkContext_t * pNetworkContext, + const ServerInfo_t * pServerInfo, + const SocketsConfig_t * pSocketsConfig ); + +/** + * @brief Set up TLS configurations for the socket. + * + * @param[in] pSocketsConfig The session configuration. + * @param[in] tcpSocket An initialized socket to secure. + * @param[in] pHostName Remote server name for SNI. + * @param[in] hostnameLength The length of `pHostName`. + * + * @return #SOCKETS_ERROR_NONE or #SOCKETS_SOCKET_ERROR. + */ +static int32_t tlsSetup( const SocketsConfig_t * pSocketsConfig, + Socket_t tcpSocket, + const char * pHostName, + size_t hostnameLength ); + + +/** + * Connect to the server specified in @p pServerInfo using @p tcpSocket. + * + * @param[in] tcpSocket The socket to establish connect. + * @param[in] pServerInfo Server connection info. + * + * @return #TRANSPORT_SOCKET_STATUS_SUCCESS on success; + * #TRANSPORT_SOCKET_STATUS_DNS_FAILURE, #TRANSPORT_SOCKET_STATUS_CONNECT_FAILURE on failure. + */ +static TransportSocketStatus_t connectToServer( Socket_t tcpSocket, + const ServerInfo_t * pServerInfo ); + +/*-----------------------------------------------------------*/ + +/* MISRA Rule 8.13 flags the following line for not using the const qualifier + * on `pNetworkContext`. Indeed, the object pointed by it is not modified + * by Secure Sockets, but other implementations of `TransportSend_t` may do so. */ +int32_t SecureSocketsTransport_Send( NetworkContext_t * pNetworkContext, + const void * pMessage, + size_t bytesToSend ) +{ + int32_t bytesSent = 0; + SecureSocketsTransportParams_t * pSecureSocketsTransportParams = NULL; + + if( ( pMessage == NULL ) || + ( bytesToSend == 0UL ) || + ( pNetworkContext == NULL ) || + ( pNetworkContext->pParams == NULL ) ) + { + LogError( ( "Invalid parameter: pMessage=%p, bytesToSend=%lu, pNetworkContext=%p", + pMessage, bytesToSend, ( void * ) pNetworkContext ) ); + bytesSent = SOCKETS_EINVAL; + } + else if( pNetworkContext->pParams->tcpSocket == SOCKETS_INVALID_SOCKET ) + { + LogError( ( "Invalid parameter: pNetworkContext->pParams->tcpSocket cannot be SOCKETS_INVALID_SOCKET." ) ); + bytesSent = SOCKETS_EINVAL; + } + else + { + pSecureSocketsTransportParams = pNetworkContext->pParams; + bytesSent = SOCKETS_Send( pSecureSocketsTransportParams->tcpSocket, + pMessage, + bytesToSend, + 0 ); + + /* If an error occurred, a negative value is returned. @ref SocketsErrors. */ + if( bytesSent >= 0 ) + { + if( bytesSent < ( int32_t ) bytesToSend ) + { + LogWarn( ( "bytesSent %d < bytesToSend %lu.", bytesSent, bytesToSend ) ); + } + else + { + LogInfo( ( "Successfully sent %d bytes over network.", bytesSent ) ); + } + } + else + { + LogError( ( "Failed to send data over network. bytesSent=%d.", bytesSent ) ); + } + } + + return bytesSent; +} + +/*-----------------------------------------------------------*/ + +/* MISRA Rule 8.13 flags the following line for not using the const qualifier + * on `pNetworkContext`. Indeed, the object pointed by it is not modified + * by Secure Sockets, but other implementations of `TransportRecv_t` may do so. */ +int32_t SecureSocketsTransport_Recv( NetworkContext_t * pNetworkContext, + void * pBuffer, + size_t bytesToRecv ) +{ + int32_t bytesReceived = SOCKETS_SOCKET_ERROR; + uint8_t * pRecvBuffer = ( uint8_t * ) pBuffer; + SecureSocketsTransportParams_t * pSecureSocketsTransportParams = NULL; + + if( ( pBuffer == NULL ) || + ( bytesToRecv == 0UL ) || + ( pNetworkContext == NULL ) || + ( pNetworkContext->pParams == NULL ) ) + { + LogError( ( "Invalid parameter: pBuffer=%p, bytesToRecv=%lu, pNetworkContext=%p", + pBuffer, bytesToRecv, ( void * ) pNetworkContext ) ); + bytesReceived = SOCKETS_EINVAL; + } + else if( pNetworkContext->pParams->tcpSocket == SOCKETS_INVALID_SOCKET ) + { + LogError( ( "Invalid parameter: pNetworkContext->pParams->tcpSocket cannot be SOCKETS_INVALID_SOCKET." ) ); + bytesReceived = SOCKETS_EINVAL; + } + else + { + pSecureSocketsTransportParams = pNetworkContext->pParams; + bytesReceived = SOCKETS_Recv( pSecureSocketsTransportParams->tcpSocket, + pRecvBuffer, + bytesToRecv, + 0 ); + + if( bytesReceived == SOCKETS_EWOULDBLOCK ) + { + /* The return value EWOULDBLOCK means no data was received within + * the receive timeout. */ + bytesReceived = 0; + } + else if( bytesReceived < 0 ) + { + LogError( ( "Failed to receive data over network. bytesReceived=%d", bytesReceived ) ); + } + else if( bytesReceived >= 0 ) + { + if( bytesReceived < ( int32_t ) bytesToRecv ) + { + LogInfo( ( "Receive requested %d bytes, but %lu bytes received instead.", + bytesToRecv, + bytesReceived ) ); + } + else + { + LogInfo( ( "Successfully received %d bytes.", + bytesReceived ) ); + } + } + else + { + /* MISRA 15.7 */ + } + } + + return bytesReceived; +} + +/*-----------------------------------------------------------*/ + +static int32_t tlsSetup( const SocketsConfig_t * pSocketsConfig, + Socket_t tcpSocket, + const char * pHostName, + size_t hostnameLength ) +{ + int32_t secureSocketStatus = SOCKETS_ERROR_NONE; + + configASSERT( tcpSocket != SOCKETS_INVALID_SOCKET ); + configASSERT( pSocketsConfig != NULL ); + configASSERT( pHostName != NULL ); + + /* ALPN options for AWS IoT. */ + + /* Set secured option. */ + secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_REQUIRE_TLS, + NULL, + 0 ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to set secured option for socket. secureSocketStatus=%d", secureSocketStatus ) ); + } + + /* Set ALPN option. */ + if( ( secureSocketStatus == SOCKETS_ERROR_NONE ) && ( pSocketsConfig->pAlpnProtos != NULL ) ) + { + secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_ALPN_PROTOCOLS, + pSocketsConfig->pAlpnProtos, + sizeof( pSocketsConfig->pAlpnProtos ) ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to set ALPN option socket. secureSocketStatus=%d", secureSocketStatus ) ); + } + } + + /* Set SNI option. */ + if( ( secureSocketStatus == SOCKETS_ERROR_NONE ) && ( pSocketsConfig->disableSni == false ) ) + { + secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_SERVER_NAME_INDICATION, + pHostName, + ( size_t ) ( hostnameLength + 1U ) ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to set SNI option for socket. secureSocketStatus=%d, HostNameLength=%lu", + secureSocketStatus, ( hostnameLength + 1UL ) ) ); + } + } + + /* Set custom server certificate. */ + if( ( secureSocketStatus == SOCKETS_ERROR_NONE ) && ( pSocketsConfig->pRootCa != NULL ) ) + { + secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE, + pSocketsConfig->pRootCa, + pSocketsConfig->rootCaSize ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to set server certificate option for socket. secureSocketStatus=%d", secureSocketStatus ) ); + } + } + + return secureSocketStatus; +} + +/*-----------------------------------------------------------*/ + +static TransportSocketStatus_t connectToServer( Socket_t tcpSocket, + const ServerInfo_t * pServerInfo ) +{ + TransportSocketStatus_t returnStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + int32_t secureSocketStatus = ( int32_t ) SOCKETS_ERROR_NONE; + SocketsSockaddr_t serverAddress = { 0 }; + + /* Establish connection. */ + serverAddress.ucSocketDomain = SOCKETS_AF_INET; + serverAddress.usPort = SOCKETS_htons( pServerInfo->port ); + serverAddress.ulAddress = SOCKETS_GetHostByName( pServerInfo->pHostName ); + + /* Check for errors from DNS lookup. */ + if( serverAddress.ulAddress == ( uint32_t ) 0 ) + { + LogError( ( "Failed to connect to server: DNS resolution failed: Server=%s.", + pServerInfo->pHostName ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_DNS_FAILURE; + } + else + { + secureSocketStatus = SOCKETS_Connect( tcpSocket, + &serverAddress, + sizeof( SocketsSockaddr_t ) ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to establish new connection. secureSocketStatus=%d.", secureSocketStatus ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_CONNECT_FAILURE; + } + } + + return returnStatus; +} + +/*-----------------------------------------------------------*/ + +static int32_t transportTimeoutSetup( Socket_t tcpSocket, + uint32_t sendTimeoutMs, + uint32_t recvTimeoutMs ) +{ + TickType_t receiveTimeout = 0, sendTimeout = 0; + int32_t secureSocketStatus = ( int32_t ) SOCKETS_ERROR_NONE; + + configASSERT( tcpSocket != SOCKETS_INVALID_SOCKET ); + + /* Secure Sockets uses TickType_t therefore replace the timeout value with portMAX_DELAY if it is exceeded. */ + receiveTimeout = pdMS_TO_TICKS( recvTimeoutMs ); + + if( receiveTimeout > portMAX_DELAY ) + { + receiveTimeout = portMAX_DELAY; + } + + secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_RCVTIMEO, + &receiveTimeout, + sizeof( TickType_t ) ); + + if( secureSocketStatus == SOCKETS_ERROR_NONE ) + { + /* Secure Sockets uses TickType_t therefore replace timeout vale with portMAX_DELAY if it exceeds. */ + if( pdMS_TO_TICKS( sendTimeoutMs ) > portMAX_DELAY ) + { + sendTimeout = portMAX_DELAY; + } + else + { + sendTimeout = pdMS_TO_TICKS( sendTimeoutMs ); + } + + secureSocketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_SNDTIMEO, + &sendTimeout, + sizeof( TickType_t ) ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to set socket send timeout. secureSocketStatus=%d.", secureSocketStatus ) ); + } + } + else + { + LogError( ( "Failed to set socket receive timeout. secureSocketStatus=%d.", secureSocketStatus ) ); + } + + return secureSocketStatus; +} + +/*-----------------------------------------------------------*/ + +static TransportSocketStatus_t establishConnect( NetworkContext_t * pNetworkContext, + const ServerInfo_t * pServerInfo, + const SocketsConfig_t * pSocketsConfig ) +{ + Socket_t tcpSocket = ( Socket_t ) SOCKETS_INVALID_SOCKET; + TransportSocketStatus_t returnStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + int32_t secureSocketStatus = ( int32_t ) SOCKETS_ERROR_NONE; + size_t hostnameLength = 0U; + SecureSocketsTransportParams_t * pSecureSocketsTransportParams = NULL; + + configASSERT( pNetworkContext != NULL ); + configASSERT( pNetworkContext->pParams != NULL ); + configASSERT( pServerInfo != NULL ); + configASSERT( pSocketsConfig != NULL ); + + hostnameLength = pServerInfo->hostNameLength; + pSecureSocketsTransportParams = pNetworkContext->pParams; + + if( ( hostnameLength > ( size_t ) securesocketsMAX_DNS_NAME_LENGTH ) ) + { + LogError( ( "Host name length %lu exceeds max length %d", + hostnameLength, securesocketsMAX_DNS_NAME_LENGTH ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + + if( returnStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + /* Create a new TCP socket. */ + tcpSocket = SOCKETS_Socket( SOCKETS_AF_INET, + SOCKETS_SOCK_STREAM, + SOCKETS_IPPROTO_TCP ); + + if( tcpSocket == SOCKETS_INVALID_SOCKET ) + { + LogError( ( "Failed to create new socket. tcpSocket=%p\n", ( void * ) tcpSocket ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INSUFFICIENT_MEMORY; + } + } + + if( returnStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + /* Set up connection encryption if credentials are provided. */ + if( pSocketsConfig->enableTls == true ) + { + if( ( int32_t ) SOCKETS_ERROR_NONE != tlsSetup( pSocketsConfig, + tcpSocket, + pServerInfo->pHostName, + hostnameLength ) ) + { + returnStatus = TRANSPORT_SOCKET_STATUS_CREDENTIALS_INVALID; + } + } + } + + if( returnStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + /* Establish the TCP connection. */ + returnStatus = connectToServer( tcpSocket, + pServerInfo ); + } + + if( returnStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + /* Configure send and receive timeouts for the socket. */ + secureSocketStatus = transportTimeoutSetup( tcpSocket, pSocketsConfig->sendTimeoutMs, pSocketsConfig->recvTimeoutMs ); + + if( secureSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to configure send and receive timeouts for socket: secureSocketStatus=%d.", secureSocketStatus ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR; + } + } + + if( returnStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + /* Set the socket in the network context. */ + pSecureSocketsTransportParams->tcpSocket = tcpSocket; + } + else + { + /* Clean up socket on failure. */ + if( tcpSocket != ( Socket_t ) SOCKETS_INVALID_SOCKET ) + { + ( void ) SOCKETS_Close( tcpSocket ); + } + } + + return returnStatus; +} + +/*-----------------------------------------------------------*/ + +TransportSocketStatus_t SecureSocketsTransport_Connect( NetworkContext_t * pNetworkContext, + const ServerInfo_t * pServerInfo, + const SocketsConfig_t * pSocketsConfig ) +{ + TransportSocketStatus_t returnStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + + /* Sanity checks for input parameters. */ + if( pSocketsConfig == NULL ) + { + LogError( ( "Parameter check failed: pSocketsConfig is NULL." ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + else if( pNetworkContext == NULL ) + { + LogError( ( "Parameter check failed: pNetworkContext is NULL." ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + else if( pNetworkContext->pParams == NULL ) + { + LogError( ( "Parameter check failed: pNetworkContext->pParams is NULL." ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + else if( pServerInfo == NULL ) + { + LogError( ( "Parameter check failed: pServerInfo is NULL." ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + else if( pServerInfo->pHostName == NULL ) + { + LogError( ( "Parameter check failed: pServerInfo->pHostName is NULL." ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + else if( pServerInfo->hostNameLength == 0UL ) + { + LogError( ( "Parameter check failed: hostNameLength must be greater than 0." ) ); + returnStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + } + else + { + /* Establish the TCP connection. */ + returnStatus = establishConnect( pNetworkContext, + pServerInfo, + pSocketsConfig ); + } + + return returnStatus; +} + +/*-----------------------------------------------------------*/ + +TransportSocketStatus_t SecureSocketsTransport_Disconnect( const NetworkContext_t * pNetworkContext ) +{ + TransportSocketStatus_t shutdownStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + TransportSocketStatus_t closeStatus = TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER; + int32_t transportSocketStatus = ( int32_t ) SOCKETS_ERROR_NONE; + SecureSocketsTransportParams_t * pSecureSocketsTransportParams = NULL; + + if( ( pNetworkContext != NULL ) && + ( pNetworkContext->pParams != NULL ) ) + { + pSecureSocketsTransportParams = pNetworkContext->pParams; + /* Call Secure Sockets shutdown function to close connection. */ + transportSocketStatus = SOCKETS_Shutdown( pSecureSocketsTransportParams->tcpSocket, SOCKETS_SHUT_RDWR ); + + if( transportSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to close connection: SOCKETS_Shutdown call failed. %d", transportSocketStatus ) ); + shutdownStatus = TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR; + } + else + { + shutdownStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + } + + /* Call Secure Sockets close function to close socket. */ + transportSocketStatus = SOCKETS_Close( pSecureSocketsTransportParams->tcpSocket ); + + if( transportSocketStatus != ( int32_t ) SOCKETS_ERROR_NONE ) + { + LogError( ( "Failed to close connection: SOCKETS_Close call failed. transportSocketStatus %d", transportSocketStatus ) ); + closeStatus = TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR; + } + else + { + closeStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + } + + if( ( shutdownStatus != TRANSPORT_SOCKET_STATUS_SUCCESS ) || ( closeStatus != TRANSPORT_SOCKET_STATUS_SUCCESS ) ) + { + shutdownStatus = TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR; + } + } + else + { + LogError( ( "Failed to close connection: pTransportInterface is NULL." ) ); + } + + return shutdownStatus; +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h b/bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h new file mode 100755 index 0000000..a818863 --- /dev/null +++ b/bsp/aws_libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h @@ -0,0 +1,204 @@ +/* + * FreeRTOS Transport Secure Sockets V1.0.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file transport_secure_sockets.h + * @brief Secure Sockets based API for transport interface implementation. + */ + +#ifndef TRANSPORT_SECURE_SOCKETS_H +#define TRANSPORT_SECURE_SOCKETS_H + +/* bool is defined in only C99+. */ +#if defined( __cplusplus ) || ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) ) + #include +#elif !defined( bool ) && !defined( false ) && !defined( true ) + #define bool int8_t + #define false ( int8_t ) 0 + #define true ( int8_t ) 1 +#endif +/** @endcond */ + +/* Transport interface include. */ +#include "transport_interface.h" +#include "iot_secure_sockets.h" + +/* Kernel include. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Include header that defines log levels. */ +#include "logging_levels.h" + +/* Logging configuration for the transport interface implementation which uses + * Secure Sockets. */ +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME "Transport_Secure_Sockets" +#endif +#ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL LOG_ERROR +#endif + +/* Logging implementation header include. */ +#include "logging_stack.h" + +/** + * @brief Definition of the network context for the transport interface + * implementation that uses Secure Sockets API. + */ +typedef struct SecureSocketsTransportParams +{ + Socket_t tcpSocket; +} SecureSocketsTransportParams_t; + +/** + * @brief TCP, TLS Connect / Disconnect return status. + */ +typedef enum TransportSocketStatus +{ + TRANSPORT_SOCKET_STATUS_SUCCESS = 0, /**< Function successfully completed. */ + TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER, /**< At least one parameter was invalid. */ + TRANSPORT_SOCKET_STATUS_INSUFFICIENT_MEMORY, /**< Insufficient memory required to establish connection. */ + TRANSPORT_SOCKET_STATUS_CREDENTIALS_INVALID, /**< Provided credentials were invalid. */ + TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR, /**< A call to a system API resulted in an internal error. */ + TRANSPORT_SOCKET_STATUS_DNS_FAILURE, /**< Resolving hostname of the server failed. */ + TRANSPORT_SOCKET_STATUS_CONNECT_FAILURE /**< Initial connection to the server failed. */ +} TransportSocketStatus_t; + + +/** + * @brief Information on the remote server for connection setup. + */ +typedef struct ServerInfo +{ + const char * pHostName; /**< @brief Server host name. Must be NULL-terminated. */ + size_t hostNameLength; /**< @brief Length of the server host name. */ + uint16_t port; /**< @brief Server port in host-order. */ +} ServerInfo_t; + + +/** + * @brief Contains the credentials necessary for connection setup. + * + */ +typedef struct SocketsConfig +{ + bool enableTls; /**< @brief Whether require TLS for the transport. */ + uint32_t sendTimeoutMs; /**< @brief Timeout for transport send. */ + uint32_t recvTimeoutMs; /**< @brief Timeout for transport recv. */ + + /** + * @brief Set this to a non-NULL value to use ALPN. + * + * This string must be NULL-terminated. + * + * See [this link] + * (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/) + * for more information. + */ + const char * pAlpnProtos; + + /** + * @brief Disable server name indication (SNI) for a TLS session. + */ + bool disableSni; + + /** + * @brief Set this to a non-zero value to use TLS max fragment length + * negotiation (TLS MFLN). + * + * @note The network stack may have a minimum value for this parameter and + * may return an error if this parameter is too small. + */ + size_t maxFragmentLength; + + const char * pRootCa; /**< @brief String representing a trusted server Root CA certificate. */ + size_t rootCaSize; /**< @brief Size associated with #IotNetworkCredentials_t.pRootCa. */ +} SocketsConfig_t; + + +/** + * @brief Sets up a TCP only connection or a TLS session on top of a TCP connection with Secure Sockets API. + * + * @param[out] pNetworkContext The output parameter to return the created network context. + * @param[in] pServerInfo Server connection info. + * @param[in] pSocketsConfig socket configs for the connection. + * + * @return #TRANSPORT_SOCKET_STATUS_SUCCESS on success; + * #TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER, #TRANSPORT_SOCKET_STATUS_INSUFFICIENT_MEMORY, + * #TRANSPORT_SOCKET_STATUS_CREDENTIALS_INVALID, #TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR, + * #TRANSPORT_SOCKET_STATUS_DNS_FAILURE, #TRANSPORT_SOCKET_STATUS_CONNECT_FAILURE on failure. + */ +TransportSocketStatus_t SecureSocketsTransport_Connect( NetworkContext_t * pNetworkContext, + const ServerInfo_t * pServerInfo, + const SocketsConfig_t * pSocketsConfig ); + +/** + * @brief Closes a TLS session on top of a TCP connection using the Secure Sockets API. + * + * @param[out] pNetworkContext The output parameter to end the TLS session and + * clean the created network context. + * + * @return #TRANSPORT_SOCKET_STATUS_SUCCESS on success; + * #TRANSPORT_SOCKET_STATUS_INVALID_PARAMETER, #TRANSPORT_SOCKET_STATUS_INTERNAL_ERROR on failure. + */ +TransportSocketStatus_t SecureSocketsTransport_Disconnect( const NetworkContext_t * pNetworkContext ); + + +/** + * @brief Receives data over an established TLS session using the Secure Sockets API. + * + * This can be used as #TransportInterface.recv function for receiving data + * from the network. + * + * @param[in] pNetworkContext The network context created using Socket_Connect API. + * @param[out] pBuffer Buffer to receive network data into. + * @param[in] bytesToRecv Number of bytes requested from the network. + * + * @return Number of bytes (> 0) received if successful; + * 0 if the socket times out without reading any bytes; + * negative value on error. + */ +int32_t SecureSocketsTransport_Recv( NetworkContext_t * pNetworkContext, + void * pBuffer, + size_t bytesToRecv ); + +/** + * @brief Sends data over an established TLS session using the Secure Sockets API. + * + * This can be used as the #TransportInterface.send function to send data + * over the network. + * + * @param[in] pNetworkContext The network context created using Secure Sockets API. + * @param[in] pBuffer Buffer containing the bytes to send over the network stack. + * @param[in] bytesToSend Number of bytes to send over the network. + * + * @return Number of bytes sent if successful; negative value on error. + */ +int32_t SecureSocketsTransport_Send( NetworkContext_t * pNetworkContext, + const void * pMessage, + size_t bytesToSend ); + +#endif /* TRANSPORT_SECURE_SOCKETS_H */ diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipSpace.c b/bsp/aws_libraries/c_sdk/standard/common/include/iot_atomic.h similarity index 76% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipSpace.c rename to bsp/aws_libraries/c_sdk/standard/common/include/iot_atomic.h index 44383c7..d3a23aa 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipSpace.c +++ b/bsp/aws_libraries/c_sdk/standard/common/include/iot_atomic.h @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * FreeRTOS Common V1.2.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -18,19 +18,22 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org */ -#include "skipGeneric.h" - -/* - * This function is a replacement for the function of the same name from core_json.c. - * Please see core_json.c for documentation. +/** + * @file iot_atomic.h + * @brief Chooses the appropriate atomic operations header. + * + * On FreeRTOS, this file chooses the atomic header provided with the FreeRTOS + * kernel. */ -void skipSpace( const char * buf, - size_t * start, - size_t max ) -{ - /* min argument is 1 for a single space. */ - skipGeneric( buf, start, max, 1 ); -} +#ifndef IOT_ATOMIC_H_ +#define IOT_ATOMIC_H_ + +#include "atomic.h" + +#endif /* ifndef IOT_ATOMIC_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/iot_init.h b/bsp/aws_libraries/c_sdk/standard/common/include/iot_init.h new file mode 100644 index 0000000..be92a59 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/iot_init.h @@ -0,0 +1,67 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_init.h + * @brief Provides function signatures for common initialization and cleanup of + * this SDK. + */ + +#ifndef IOT_INIT_H_ +#define IOT_INIT_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include + +/** + * @brief One-time initialization function for this SDK. + * + * This function initializes common libraries, such as static memory and task + * pool. It must be called once (and only once) before calling any other + * function in this SDK. Calling this function more than once without first + * calling `IotSdk_Cleanup` may result in a crash. + * + * @return `true` if initialization succeeded; `false` otherwise. Logs may be + * printed in case of failure. + * + * @warning No thread-safety guarantees are provided for this function. + */ +bool IotSdk_Init( void ); + +/** + * @brief One-time deinitialization function for all common libraries. + * + * This function frees resources taken in `IotSdk_Init`. No other function + * in this SDK may be called after calling this function unless `IotSdk_Init` + * is called again. + * + * @warning No thread-safety guarantees are provided for this function. + */ +void IotSdk_Cleanup( void ); + +#endif /* IOT_INIT_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/iot_linear_containers.h b/bsp/aws_libraries/c_sdk/standard/common/include/iot_linear_containers.h new file mode 100644 index 0000000..3985370 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/iot_linear_containers.h @@ -0,0 +1,1048 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_linear_containers.h + * @brief Declares and implements doubly-linked lists and queues. + */ + +#ifndef IOT_LINEAR_CONTAINERS_H_ +#define IOT_LINEAR_CONTAINERS_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include + +/** + * @defgroup linear_containers_datatypes_listqueue List and queue + * @brief Structures that represent a list or queue. + */ + +/** + * @ingroup linear_containers_datatypes_listqueue + * @brief Link member placed in structs of a list or queue. + * + * All elements in a list or queue must contain one of these members. The macro + * #IotLink_Container can be used to calculate the starting address of the + * link's container. + */ +typedef struct IotLink +{ + struct IotLink * pPrevious; /**< @brief Pointer to the previous element. */ + struct IotLink * pNext; /**< @brief Pointer to the next element. */ +} IotLink_t; + +/** + * @ingroup linear_containers_datatypes_listqueue + * @brief Represents a doubly-linked list. + */ +typedef IotLink_t IotListDouble_t; + +/** + * @ingroup linear_containers_datatypes_listqueue + * @brief Represents a queue. + */ +typedef IotLink_t IotDeQueue_t; + +/** + * @constants_page{linear_containers} + * @constants_brief{linear containers library} + * + * @section linear_containers_constants_initializers Linear Containers Initializers + * @brief Provides default values for initializing the linear containers data types. + * + * @snippet this define_linear_containers_initializers + * + * All user-facing data types of the linear containers library should be initialized + * using one of the following. + * + * @warning Failure to initialize a linear containers data type with the appropriate + * initializer may result in a runtime error! + * @note The initializers may change at any time in future versions, but their + * names will remain the same. + */ +/* @[define_linear_containers_initializers] */ +#define IOT_LINK_INITIALIZER { 0 } /**< @brief Initializer for an #IotLink_t. */ +#define IOT_LIST_DOUBLE_INITIALIZER IOT_LINK_INITIALIZER /**< @brief Initializer for an #IotListDouble_t. */ +#define IOT_DEQUEUE_INITIALIZER IOT_LINK_INITIALIZER /**< @brief Initializer for an #IotDeQueue_t. */ +/* @[define_linear_containers_initializers] */ + +/** + * @def IotContainers_Assert( expression ) + * @brief Assertion macro for the linear containers library. + * + * Set @ref IOT_CONTAINERS_ENABLE_ASSERTS to `1` to enable assertions in the linear + * containers library. + * + * @param[in] expression Expression to be evaluated. + */ +#if IOT_CONTAINERS_ENABLE_ASSERTS == 1 + #ifndef IotContainers_Assert + #include + #define IotContainers_Assert( expression ) assert( expression ) + #endif +#else + #define IotContainers_Assert( expression ) +#endif + +/** + * @brief Calculates the starting address of a containing struct. + * + * @param[in] type Type of the containing struct. + * @param[in] pLink Pointer to a link member. + * @param[in] linkName Name of the #IotLink_t in the containing struct. + */ +#define IotLink_Container( type, pLink, linkName ) \ + ( ( type * ) ( void * ) ( ( ( uint8_t * ) ( pLink ) ) - offsetof( type, linkName ) ) ) + +/** + * @brief Iterates through all elements of a linear container. + * + * Container elements must not be freed or removed while iterating. + * + * @param[in] pStart The first element to iterate from. + * @param[out] pLink Pointer to a container element. + */ +#define IotContainers_ForEach( pStart, pLink ) \ + for( ( pLink ) = ( pStart )->pNext; \ + ( pLink ) != ( pStart ); \ + ( pLink ) = ( pLink )->pNext ) + +/** + * @functions_page{linear_containers, Linear Containers} + * @functions_brief{linear containers} + * - @function_name{linear_containers_function_link_islinked} + * @function_brief{linear_containers_function_link_islinked} + * - @function_name{linear_containers_function_list_double_create} + * @function_brief{linear_containers_function_list_double_create} + * - @function_name{linear_containers_function_list_double_count} + * @function_brief{linear_containers_function_list_double_count} + * - @function_name{linear_containers_function_list_double_isempty} + * @function_brief{linear_containers_function_list_double_isempty} + * - @function_name{linear_containers_function_list_double_peekhead} + * @function_brief{linear_containers_function_list_double_peekhead} + * - @function_name{linear_containers_function_list_double_peektail} + * @function_brief{linear_containers_function_list_double_peektail} + * - @function_name{linear_containers_function_list_double_inserthead} + * @function_brief{linear_containers_function_list_double_inserthead} + * - @function_name{linear_containers_function_list_double_inserttail} + * @function_brief{linear_containers_function_list_double_inserttail} + * - @function_name{linear_containers_function_list_double_insertbefore} + * @function_brief{linear_containers_function_list_double_insertbefore} + * - @function_name{linear_containers_function_list_double_insertafter} + * @function_brief{linear_containers_function_list_double_insertafter} + * - @function_name{linear_containers_function_list_double_insertsorted} + * @function_brief{linear_containers_function_list_double_insertsorted} + * - @function_name{linear_containers_function_list_double_remove} + * @function_brief{linear_containers_function_list_double_remove} + * - @function_name{linear_containers_function_list_double_removehead} + * @function_brief{linear_containers_function_list_double_removehead} + * - @function_name{linear_containers_function_list_double_removetail} + * @function_brief{linear_containers_function_list_double_removetail} + * - @function_name{linear_containers_function_list_double_removeall} + * @function_brief{linear_containers_function_list_double_removeall} + * - @function_name{linear_containers_function_list_double_findfirstmatch} + * @function_brief{linear_containers_function_list_double_findfirstmatch} + * - @function_name{linear_containers_function_list_double_removefirstmatch} + * @function_brief{linear_containers_function_list_double_removefirstmatch} + * - @function_name{linear_containers_function_list_double_removeallmatches} + * @function_brief{linear_containers_function_list_double_removeallmatches} + * - @function_name{linear_containers_function_queue_create} + * @function_brief{linear_containers_function_queue_create} + * - @function_name{linear_containers_function_queue_count} + * @function_brief{linear_containers_function_queue_count} + * - @function_name{linear_containers_function_queue_isempty} + * @function_brief{linear_containers_function_queue_isempty} + * - @function_name{linear_containers_function_queue_peekhead} + * @function_brief{linear_containers_function_queue_peekhead} + * - @function_name{linear_containers_function_queue_peektail} + * @function_brief{linear_containers_function_queue_peektail} + * - @function_name{linear_containers_function_queue_enqueuehead} + * @function_brief{linear_containers_function_queue_enqueuehead} + * - @function_name{linear_containers_function_queue_dequeuehead} + * @function_brief{linear_containers_function_queue_dequeuehead} + * - @function_name{linear_containers_function_queue_enqueuetail} + * @function_brief{linear_containers_function_queue_enqueuetail} + * - @function_name{linear_containers_function_queue_dequeuetail} + * @function_brief{linear_containers_function_queue_dequeuetail} + * - @function_name{linear_containers_function_queue_remove} + * @function_brief{linear_containers_function_queue_remove} + * - @function_name{linear_containers_function_queue_removeall} + * @function_brief{linear_containers_function_queue_removeall} + * - @function_name{linear_containers_function_queue_removeallmatches} + * @function_brief{linear_containers_function_queue_removeallmatches} + */ + +/** + * @function_page{IotLink_IsLinked,linear_containers,link_islinked} + * @function_snippet{linear_containers,link_islinked,this} + * @copydoc IotLink_IsLinked + * @function_page{IotListDouble_Create,linear_containers,list_double_create} + * @function_snippet{linear_containers,list_double_create,this} + * @copydoc IotListDouble_Create + * @function_page{IotListDouble_Count,linear_containers,list_double_count} + * @function_snippet{linear_containers,list_double_count,this} + * @copydoc IotListDouble_Count + * @function_page{IotListDouble_IsEmpty,linear_containers,list_double_isempty} + * @function_snippet{linear_containers,list_double_isempty,this} + * @copydoc IotListDouble_IsEmpty + * @function_page{IotListDouble_PeekHead,linear_containers,list_double_peekhead} + * @function_snippet{linear_containers,list_double_peekhead,this} + * @copydoc IotListDouble_PeekHead + * @function_page{IotListDouble_PeekTail,linear_containers,list_double_peektail} + * @function_snippet{linear_containers,list_double_peektail,this} + * @copydoc IotListDouble_PeekTail + * @function_page{IotListDouble_InsertHead,linear_containers,list_double_inserthead} + * @function_snippet{linear_containers,list_double_inserthead,this} + * @copydoc IotListDouble_InsertHead + * @function_page{IotListDouble_InsertTail,linear_containers,list_double_inserttail} + * @function_snippet{linear_containers,list_double_inserttail,this} + * @copydoc IotListDouble_InsertTail + * @function_page{IotListDouble_InsertBefore,linear_containers,list_double_insertbefore} + * @function_snippet{linear_containers,list_double_insertbefore,this} + * @copydoc IotListDouble_InsertBefore + * @function_page{IotListDouble_InsertAfter,linear_containers,list_double_insertafter} + * @function_snippet{linear_containers,list_double_insertafter,this} + * @copydoc IotListDouble_InsertAfter + * @function_page{IotListDouble_InsertSorted,linear_containers,list_double_insertsorted} + * @function_snippet{linear_containers,list_double_insertsorted,this} + * @copydoc IotListDouble_InsertSorted + * @function_page{IotListDouble_Remove,linear_containers,list_double_remove} + * @function_snippet{linear_containers,list_double_remove,this} + * @copydoc IotListDouble_Remove + * @function_page{IotListDouble_RemoveHead,linear_containers,list_double_removehead} + * @function_snippet{linear_containers,list_double_removehead,this} + * @copydoc IotListDouble_RemoveHead + * @function_page{IotListDouble_RemoveTail,linear_containers,list_double_removetail} + * @function_snippet{linear_containers,list_double_removetail,this} + * @copydoc IotListDouble_RemoveTail + * @function_page{IotListDouble_RemoveAll,linear_containers,list_double_removeall} + * @function_snippet{linear_containers,list_double_removeall,this} + * @copydoc IotListDouble_RemoveAll + * @function_page{IotListDouble_FindFirstMatch,linear_containers,list_double_findfirstmatch} + * @function_snippet{linear_containers,list_double_findfirstmatch,this} + * @copydoc IotListDouble_FindFirstMatch + * @function_page{IotListDouble_RemoveFirstMatch,linear_containers,list_double_removefirstmatch} + * @function_snippet{linear_containers,list_double_removefirstmatch,this} + * @copydoc IotListDouble_RemoveFirstMatch + * @function_page{IotListDouble_RemoveAllMatches,linear_containers,list_double_removeallmatches} + * @function_snippet{linear_containers,list_double_removeallmatches,this} + * @copydoc IotListDouble_RemoveAllMatches + * @function_page{IotDeQueue_Create,linear_containers,queue_create} + * @function_snippet{linear_containers,queue_create,this} + * @copydoc IotDeQueue_Create + * @function_page{IotDeQueue_Count,linear_containers,queue_count} + * @function_snippet{linear_containers,queue_count,this} + * @copydoc IotDeQueue_Count + * @function_page{IotDeQueue_IsEmpty,linear_containers,queue_isempty} + * @function_snippet{linear_containers,queue_isempty,this} + * @copydoc IotDeQueue_IsEmpty + * @function_page{IotDeQueue_PeekHead,linear_containers,queue_peekhead} + * @function_snippet{linear_containers,queue_peekhead,this} + * @copydoc IotDeQueue_PeekHead + * @function_page{IotDeQueue_PeekTail,linear_containers,queue_peektail} + * @function_snippet{linear_containers,queue_peektail,this} + * @copydoc IotDeQueue_PeekTail + * @function_page{IotDeQueue_EnqueueHead,linear_containers,queue_enqueuehead} + * @function_snippet{linear_containers,queue_enqueuehead,this} + * @copydoc IotDeQueue_EnqueueHead + * @function_page{IotDeQueue_DequeueHead,linear_containers,queue_dequeuehead} + * @function_snippet{linear_containers,queue_dequeuehead,this} + * @copydoc IotDeQueue_DequeueHead + * @function_page{IotDeQueue_EnqueueTail,linear_containers,queue_enqueuetail} + * @function_snippet{linear_containers,queue_enqueuetail,this} + * @copydoc IotDeQueue_EnqueueTail + * @function_page{IotDeQueue_DequeueTail,linear_containers,queue_dequeuetail} + * @function_snippet{linear_containers,queue_dequeuetail,this} + * @copydoc IotDeQueue_DequeueTail + * @function_page{IotDeQueue_Remove,linear_containers,queue_remove} + * @function_snippet{linear_containers,queue_remove,this} + * @copydoc IotDeQueue_Remove + * @function_page{IotDeQueue_RemoveAll,linear_containers,queue_removeall} + * @function_snippet{linear_containers,queue_removeall,this} + * @copydoc IotDeQueue_RemoveAll + * @function_page{IotDeQueue_RemoveAllMatches,linear_containers,queue_removeallmatches} + * @function_snippet{linear_containers,queue_removeallmatches,this} + * @copydoc IotDeQueue_RemoveAllMatches + */ + +/** + * @brief Check if an #IotLink_t is linked in a list or queue. + * + * @param[in] pLink The link to check. + * + * @return `true` if `pCurrent` is linked in a list or queue; `false` otherwise. + */ +/* @[declare_linear_containers_link_islinked] */ +static inline bool IotLink_IsLinked( const IotLink_t * const pLink ) +/* @[declare_linear_containers_link_islinked] */ +{ + bool isLinked = false; + + if( pLink != NULL ) + { + isLinked = ( pLink->pNext != NULL ) && ( pLink->pPrevious != NULL ); + } + + return isLinked; +} + +/** + * @brief Create a new doubly-linked list. + * + * This function initializes a new doubly-linked list. It must be called on an + * uninitialized #IotListDouble_t before calling any other doubly-linked list + * function. This function must not be called on an already-initialized + * #IotListDouble_t. + * + * This function will not fail. The function @ref linear_containers_function_list_double_removeall + * may be called to destroy a list. + * + * @param[in] pList Pointer to the memory that will hold the new doubly-linked list. + */ +/* @[declare_linear_containers_list_double_create] */ +static inline void IotListDouble_Create( IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_create] */ +{ + /* This function must not be called with a NULL parameter. */ + IotContainers_Assert( pList != NULL ); + + /* An empty list is a link pointing to itself. */ + pList->pPrevious = pList; + pList->pNext = pList; +} + +/** + * @brief Return the number of elements contained in an #IotListDouble_t. + * + * @param[in] pList The doubly-linked list with the elements to count. + * + * @return The number of elements in the doubly-linked list. + */ +/* @[declare_linear_containers_list_double_count] */ +static inline size_t IotListDouble_Count( const IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_count] */ +{ + size_t count = 0; + + if( pList != NULL ) + { + /* Get the list head. */ + const IotLink_t * pCurrent = pList->pNext; + + /* Iterate through the list to count the elements. */ + while( pCurrent != pList ) + { + count++; + pCurrent = pCurrent->pNext; + } + } + + return count; +} + +/** + * @brief Check if a doubly-linked list is empty. + * + * @param[in] pList The doubly-linked list to check. + * + * @return `true` if the list is empty; `false` otherwise. + */ +/* @[declare_linear_containers_list_double_isempty] */ +static inline bool IotListDouble_IsEmpty( const IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_isempty] */ +{ + /* An empty list is NULL link, or a link pointing to itself. */ + return( ( pList == NULL ) || ( pList->pNext == pList ) ); +} + +/** + * @brief Return an #IotLink_t representing the first element in a doubly-linked list + * without removing it. + * + * @param[in] pList The list to peek. + * + * @return Pointer to an #IotLink_t representing the element at the head of the + * list; `NULL` if the list is empty. The macro #IotLink_Container may be used to + * determine the address of the link's container. + */ +/* @[declare_linear_containers_list_double_peekhead] */ +static inline IotLink_t * IotListDouble_PeekHead( const IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_peekhead] */ +{ + IotLink_t * pHead = NULL; + + if( pList != NULL ) + { + if( IotListDouble_IsEmpty( pList ) == false ) + { + pHead = pList->pNext; + } + } + + return pHead; +} + +/** + * @brief Return an #IotLink_t representing the last element in a doubly-linked + * list without removing it. + * + * @param[in] pList The list to peek. + * + * @return Pointer to an #IotLink_t representing the element at the tail of the + * list; `NULL` if the list is empty. The macro #IotLink_Container may be used to + * determine the address of the link's container. + */ +/* @[declare_linear_containers_list_double_peektail] */ +static inline IotLink_t * IotListDouble_PeekTail( const IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_peektail] */ +{ + IotLink_t * pTail = NULL; + + if( pList != NULL ) + { + if( IotListDouble_IsEmpty( pList ) == false ) + { + pTail = pList->pPrevious; + } + } + + return pTail; +} + +/** + * @brief Insert an element at the head of a doubly-linked list. + * + * @param[in] pList The doubly-linked list that will hold the new element. + * @param[in] pLink Pointer to the new element's link member. + */ +/* @[declare_linear_containers_list_double_inserthead] */ +static inline void IotListDouble_InsertHead( IotListDouble_t * const pList, + IotLink_t * const pLink ) +/* @[declare_linear_containers_list_double_inserthead] */ +{ + /* This function must not be called with NULL parameters. */ + IotContainers_Assert( pList != NULL ); + IotContainers_Assert( pLink != NULL ); + + /* Save current list head. */ + IotLink_t * pHead = pList->pNext; + + /* Place new element before list head. */ + pLink->pNext = pHead; + pLink->pPrevious = pList; + + /* Assign new list head. */ + pHead->pPrevious = pLink; + pList->pNext = pLink; +} + +/** + * @brief Insert an element at the tail of a doubly-linked list. + * + * @param[in] pList The double-linked list that will hold the new element. + * @param[in] pLink Pointer to the new element's link member. + */ +/* @[declare_linear_containers_list_double_inserttail] */ +static inline void IotListDouble_InsertTail( IotListDouble_t * const pList, + IotLink_t * const pLink ) +/* @[declare_linear_containers_list_double_inserttail] */ +{ + /* This function must not be called with NULL parameters. */ + IotContainers_Assert( pList != NULL ); + IotContainers_Assert( pLink != NULL ); + + /* Save current list tail. */ + IotLink_t * pTail = pList->pPrevious; + + pLink->pNext = pList; + pLink->pPrevious = pTail; + + pList->pPrevious = pLink; + pTail->pNext = pLink; +} + +/** + * @brief Insert an element before another element in a doubly-linked list. + * + * @param[in] pElement The new element will be placed before this element. + * @param[in] pLink Pointer to the new element's link member. + */ +/* @[declare_linear_containers_list_double_insertbefore] */ +static inline void IotListDouble_InsertBefore( IotLink_t * const pElement, + IotLink_t * const pLink ) +/* @[declare_linear_containers_list_double_insertbefore] */ +{ + IotListDouble_InsertTail( pElement, pLink ); +} + +/** + * @brief Insert an element after another element in a doubly-linked list. + * + * @param[in] pElement The new element will be placed after this element. + * @param[in] pLink Pointer to the new element's link member. + */ +/* @[declare_linear_containers_list_double_insertafter] */ +static inline void IotListDouble_InsertAfter( IotLink_t * const pElement, + IotLink_t * const pLink ) +/* @[declare_linear_containers_list_double_insertafter] */ +{ + IotListDouble_InsertHead( pElement, pLink ); +} + +/** + * @brief Insert an element in a sorted doubly-linked list. + * + * Places an element into a list by sorting it into order. The function + * `compare` is used to determine where to place the new element. + * + * @param[in] pList The list that will hold the new element. + * @param[in] pLink Pointer to the new element's link member. + * @param[in] compare Determines the order of the list. Returns a negative + * value if its first argument is less than its second argument; returns + * zero if its first argument is equal to its second argument; returns a + * positive value if its first argument is greater than its second argument. + * The parameters to this function are #IotLink_t, so the macro #IotLink_Container + * may be used to determine the address of the link's container. + */ +/* @[declare_linear_containers_list_double_insertsorted] */ +static inline void IotListDouble_InsertSorted( IotListDouble_t * const pList, + IotLink_t * const pLink, + int32_t ( * compare )( const IotLink_t * const, const IotLink_t * const ) ) +/* @[declare_linear_containers_list_double_insertsorted] */ +{ + /* This function must not be called with NULL parameters. */ + IotContainers_Assert( pList != NULL ); + IotContainers_Assert( pLink != NULL ); + IotContainers_Assert( compare != NULL ); + + /* Insert at head for empty list. */ + if( IotListDouble_IsEmpty( pList ) == true ) + { + IotListDouble_InsertHead( pList, pLink ); + } + else + { + bool inserted = false; + IotLink_t * pCurrent = pList->pNext; + + /* Iterate through the list to find the correct position. */ + while( pCurrent != pList ) + { + /* Comparing for '<' preserves the order of insertion. */ + if( compare( pLink, pCurrent ) < 0 ) + { + IotListDouble_InsertBefore( pCurrent, pLink ); + inserted = true; + + break; + } + + pCurrent = pCurrent->pNext; + } + + /* New element is greater than all elements in list. Insert at tail. */ + if( inserted == false ) + { + IotListDouble_InsertTail( pList, pLink ); + } + } +} + +/** + * @brief Remove a single element from a doubly-linked list. + * + * @param[in] pLink The element to remove. + */ +/* @[declare_linear_containers_list_double_remove] */ +static inline void IotListDouble_Remove( IotLink_t * const pLink ) +/* @[declare_linear_containers_list_double_remove] */ +{ + /* This function must not be called with a NULL parameter. */ + IotContainers_Assert( pLink != NULL ); + + /* This function must be called on a linked element. */ + IotContainers_Assert( IotLink_IsLinked( pLink ) == true ); + + pLink->pPrevious->pNext = pLink->pNext; + pLink->pNext->pPrevious = pLink->pPrevious; + pLink->pPrevious = NULL; + pLink->pNext = NULL; +} + +/** + * @brief Remove the element at the head of a doubly-linked list. + * + * @param[in] pList The doubly-linked list that holds the element to remove. + * + * @return Pointer to an #IotLink_t representing the removed list head; `NULL` + * if the list is empty. The macro #IotLink_Container may be used to determine + * the address of the link's container. + */ +/* @[declare_linear_containers_list_double_removehead] */ +static inline IotLink_t * IotListDouble_RemoveHead( IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_removehead] */ +{ + IotLink_t * pHead = NULL; + + if( IotListDouble_IsEmpty( pList ) == false ) + { + pHead = pList->pNext; + IotListDouble_Remove( pHead ); + } + + return pHead; +} + +/** + * @brief Remove the element at the tail of a doubly-linked list. + * + * @param[in] pList The doubly-linked list that holds the element to remove. + * + * @return Pointer to an #IotLink_t representing the removed list tail; `NULL` + * if the list is empty. The macro #IotLink_Container may be used to determine + * the address of the link's container. + */ +/* @[declare_linear_containers_list_double_removetail] */ +static inline IotLink_t * IotListDouble_RemoveTail( IotListDouble_t * const pList ) +/* @[declare_linear_containers_list_double_removetail] */ +{ + IotLink_t * pTail = NULL; + + if( IotListDouble_IsEmpty( pList ) == false ) + { + pTail = pList->pPrevious; + IotListDouble_Remove( pTail ); + } + + return pTail; +} + +/** + * @brief Remove all elements in a doubly-linked list. + * + * @param[in] pList The list to empty. + * @param[in] freeElement A function to free memory used by each removed list + * element. Optional; pass `NULL` to ignore. + * @param[in] linkOffset Offset in bytes of a link member in its container, used + * to calculate the pointer to pass to `freeElement`. This value should be calculated + * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL` + * or its value is `0`. + */ +/* @[declare_linear_containers_list_double_removeall] */ +static inline void IotListDouble_RemoveAll( IotListDouble_t * const pList, + void ( * freeElement )( void * ), + size_t linkOffset ) +/* @[declare_linear_containers_list_double_removeall] */ +{ + /* This function must not be called with a NULL pList parameter. */ + IotContainers_Assert( pList != NULL ); + + /* Get the list head. */ + IotLink_t * pCurrent = pList->pNext; + + /* Iterate through the list and remove all elements. */ + while( pCurrent != pList ) + { + /* Save a pointer to the next list element. */ + IotLink_t * pNext = pCurrent->pNext; + + /* Remove and free the current list element. */ + IotListDouble_Remove( pCurrent ); + + if( freeElement != NULL ) + { + freeElement( ( ( uint8_t * ) pCurrent ) - linkOffset ); + } + + /* Move the iterating pointer to the next list element. */ + pCurrent = pNext; + } +} + +/** + * @brief Search a doubly-linked list for the first matching element. + * + * If a match is found, the matching element is not removed from the list. + * See @ref linear_containers_function_list_double_removefirstmatch for the function + * that searches and removes. + * + * @param[in] pList The doubly-linked list to search. + * @param[in] pStartPoint An element in `pList`. Only elements between this one and + * the list tail are checked. Pass `NULL` to search from the beginning of the list. + * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to + * search using the address `pMatch`, i.e. `element == pMatch`. + * @param[in] pMatch If `isMatch` is `NULL`, each element in the list is compared + * to this address to find a match. Otherwise, it is passed as the second argument + * to `isMatch`. + * + * @return Pointer to an #IotLink_t representing the first matched element; `NULL` + * if no match is found. The macro #IotLink_Container may be used to determine the + * address of the link's container. + */ +/* @[declare_linear_containers_list_double_findfirstmatch] */ +static inline IotLink_t * IotListDouble_FindFirstMatch( const IotListDouble_t * const pList, + const IotLink_t * const pStartPoint, + bool ( * isMatch )( const IotLink_t * const, void * ), + void * pMatch ) +/* @[declare_linear_containers_list_double_findfirstmatch] */ +{ + /* The const must be cast away to match this function's return value. Nevertheless, + * this function will respect the const-ness of pStartPoint. */ + IotLink_t * pCurrent = ( IotLink_t * ) pStartPoint; + + /* This function must not be called with a NULL pList parameter. */ + IotContainers_Assert( pList != NULL ); + + /* Search starting from list head if no start point is given. */ + if( pStartPoint == NULL ) + { + pCurrent = pList->pNext; + } + + /* Iterate through the list to search for matches. */ + while( pCurrent != pList ) + { + /* Call isMatch if provided. Otherwise, compare pointers. */ + if( isMatch != NULL ) + { + if( isMatch( pCurrent, pMatch ) == true ) + { + return pCurrent; + } + } + else + { + if( pCurrent == pMatch ) + { + return pCurrent; + } + } + + pCurrent = pCurrent->pNext; + } + + /* No match found, return NULL. */ + return NULL; +} + +/** + * @brief Search a doubly-linked list for the first matching element and remove + * it. + * + * An #IotLink_t may be passed as `pList` to start searching after the head of a + * doubly-linked list. + * + * @param[in] pList The doubly-linked list to search. + * @param[in] pStartPoint An element in `pList`. Only elements between this one and + * the list tail are checked. Pass `NULL` to search from the beginning of the list. + * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to + * search using the address `pMatch`, i.e. `element == pMatch`. + * @param[in] pMatch If `isMatch` is `NULL`, each element in the list is compared + * to this address to find a match. Otherwise, it is passed as the second argument + * to `isMatch`. + * + * @return Pointer to an #IotLink_t representing the matched and removed element; + * `NULL` if no match is found. The macro #IotLink_Container may be used to determine + * the address of the link's container. + */ +/* @[declare_linear_containers_list_double_removefirstmatch] */ +static inline IotLink_t * IotListDouble_RemoveFirstMatch( IotListDouble_t * const pList, + const IotLink_t * const pStartPoint, + bool ( * isMatch )( const IotLink_t *, void * ), + void * pMatch ) +/* @[declare_linear_containers_list_double_removefirstmatch] */ +{ + IotLink_t * pMatchedElement = IotListDouble_FindFirstMatch( pList, + pStartPoint, + isMatch, + pMatch ); + + if( pMatchedElement != NULL ) + { + IotListDouble_Remove( pMatchedElement ); + } + + return pMatchedElement; +} + +/** + * @brief Remove all matching elements from a doubly-linked list. + * + * @param[in] pList The doubly-linked list to search. + * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to + * search using the address `pMatch`, i.e. `element == pMatch`. + * @param[in] pMatch If `isMatch` is `NULL`, each element in the list is compared + * to this address to find a match. Otherwise, it is passed as the second argument + * to `isMatch`. + * @param[in] freeElement A function to free memory used by each removed list + * element. Optional; pass `NULL` to ignore. + * @param[in] linkOffset Offset in bytes of a link member in its container, used + * to calculate the pointer to pass to `freeElement`. This value should be calculated + * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL` + * or its value is `0`. + */ +/* @[declare_linear_containers_list_double_removeallmatches] */ +static inline void IotListDouble_RemoveAllMatches( IotListDouble_t * const pList, + bool ( * isMatch )( const IotLink_t *, void * ), + void * pMatch, + void ( * freeElement )( void * ), + size_t linkOffset ) +/* @[declare_linear_containers_list_double_removeallmatches] */ +{ + IotLink_t * pMatchedElement = NULL, * pNextElement = NULL; + + /* Search the list for all matching elements. */ + do + { + pMatchedElement = IotListDouble_FindFirstMatch( pList, + pMatchedElement, + isMatch, + pMatch ); + + if( pMatchedElement != NULL ) + { + /* Save pointer to next element. */ + pNextElement = pMatchedElement->pNext; + + /* Match found; remove and free. */ + IotListDouble_Remove( pMatchedElement ); + + if( freeElement != NULL ) + { + freeElement( ( ( uint8_t * ) pMatchedElement ) - linkOffset ); + } + + /* Continue search from next element. */ + pMatchedElement = pNextElement; + } + } while( pMatchedElement != NULL ); +} + +/** + * @brief Create a new queue. + * + * This function initializes a new double-ended queue. It must be called on an uninitialized + * #IotDeQueue_t before calling any other queue function. This function must not be + * called on an already-initialized #IotDeQueue_t. + * + * This function will not fail. + * + * @param[in] pQueue Pointer to the memory that will hold the new queue. + */ +/* @[declare_linear_containers_queue_create] */ +static inline void IotDeQueue_Create( IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_create] */ +{ + IotListDouble_Create( pQueue ); +} + +/** + * @brief Return the number of elements contained in an #IotDeQueue_t. + * + * @param[in] pQueue The queue with the elements to count. + * + * @return The number of items elements in the queue. + */ +/* @[declare_linear_containers_queue_count] */ +static inline size_t IotDeQueue_Count( const IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_count] */ +{ + return IotListDouble_Count( pQueue ); +} + +/** + * @brief Check if a queue is empty. + * + * @param[in] pQueue The queue to check. + * + * @return `true` if the queue is empty; `false` otherwise. + * + */ +/* @[declare_linear_containers_queue_isempty] */ +static inline bool IotDeQueue_IsEmpty( const IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_isempty] */ +{ + return IotListDouble_IsEmpty( pQueue ); +} + +/** + * @brief Return an #IotLink_t representing the element at the front of the queue + * without removing it. + * + * @param[in] pQueue The queue to peek. + * + * @return Pointer to an #IotLink_t representing the element at the head of the + * queue; `NULL` if the queue is empty. The macro #IotLink_Container may be used + * to determine the address of the link's container. + */ +/* @[declare_linear_containers_queue_peekhead] */ +static inline IotLink_t * IotDeQueue_PeekHead( const IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_peekhead] */ +{ + return IotListDouble_PeekHead( pQueue ); +} + +/** + * @brief Return an #IotLink_t representing the element at the back of the queue + * without removing it. + * + * @param[in] pQueue The queue to peek. + * + * @return Pointer to an #IotLink_t representing the element at the head of the + * queue; `NULL` if the queue is empty. The macro #IotLink_Container may be used + * to determine the address of the link's container. + */ +/* @[declare_linear_containers_queue_peektail] */ +static inline IotLink_t * IotDeQueue_PeekTail( const IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_peektail] */ +{ + return IotListDouble_PeekTail( pQueue ); +} + +/** + * @brief Add an element at the head of the queue. + * + * @param[in] pQueue The queue that will hold the new element. + * @param[in] pLink Pointer to the new element's link member. + */ +/* @[declare_linear_containers_queue_enqueuehead] */ +static inline void IotDeQueue_EnqueueHead( IotDeQueue_t * const pQueue, + IotLink_t * const pLink ) +/* @[declare_linear_containers_queue_enqueuehead] */ +{ + IotListDouble_InsertHead( pQueue, pLink ); +} + +/** + * @brief Remove an element at the head of the queue. + * + * @param[in] pQueue The queue that holds the element to remove. + * + * @return Pointer to an #IotLink_t representing the removed queue element; `NULL` + * if the queue is empty. The macro #IotLink_Container may be used to determine + * the address of the link's container. + */ +/* @[declare_linear_containers_queue_dequeuehead] */ +static inline IotLink_t * IotDeQueue_DequeueHead( IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_dequeuehead] */ +{ + return IotListDouble_RemoveHead( pQueue ); +} + +/** + * @brief Add an element at the tail of the queue. + * + * @param[in] pQueue The queue that will hold the new element. + * @param[in] pLink Pointer to the new element's link member. + */ +/* @[declare_linear_containers_queue_enqueuetail] */ +static inline void IotDeQueue_EnqueueTail( IotDeQueue_t * const pQueue, + IotLink_t * const pLink ) +/* @[declare_linear_containers_queue_enqueuetail] */ +{ + IotListDouble_InsertTail( pQueue, pLink ); +} + +/** + * @brief Remove an element at the tail of the queue. + * + * @param[in] pQueue The queue that holds the element to remove. + * + * @return Pointer to an #IotLink_t representing the removed queue element; `NULL` + * if the queue is empty. The macro #IotLink_Container may be used to determine + * the address of the link's container. + */ +/* @[declare_linear_containers_queue_dequeuetail] */ +static inline IotLink_t * IotDeQueue_DequeueTail( IotDeQueue_t * const pQueue ) +/* @[declare_linear_containers_queue_dequeuetail] */ +{ + return IotListDouble_RemoveTail( pQueue ); +} + +/** + * @brief Remove a single element from a queue. + * + * @param[in] pLink The element to remove. + */ +/* @[declare_linear_containers_queue_remove] */ +static inline void IotDeQueue_Remove( IotLink_t * const pLink ) +/* @[declare_linear_containers_queue_remove] */ +{ + IotListDouble_Remove( pLink ); +} + +/** + * @brief Remove all elements in a queue. + * + * @param[in] pQueue The queue to empty. + * @param[in] freeElement A function to free memory used by each removed queue + * element. Optional; pass `NULL` to ignore. + * @param[in] linkOffset Offset in bytes of a link member in its container, used + * to calculate the pointer to pass to `freeElement`. This value should be calculated + * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL` + * or its value is `0`. + */ +/* @[declare_linear_containers_queue_removeall] */ +static inline void IotDeQueue_RemoveAll( IotDeQueue_t * const pQueue, + void ( * freeElement )( void * ), + size_t linkOffset ) +/* @[declare_linear_containers_queue_removeall] */ +{ + IotListDouble_RemoveAll( pQueue, freeElement, linkOffset ); +} + +/** + * @brief Remove all matching elements from a queue. + * + * @param[in] pQueue The queue to search. + * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to + * search using the address `pMatch`, i.e. `element == pMatch`. + * @param[in] pMatch If `isMatch` is `NULL`, each element in the queue is compared + * to this address to find a match. Otherwise, it is passed as the second argument + * to `isMatch`. + * @param[in] freeElement A function to free memory used by each removed queue + * element. Optional; pass `NULL` to ignore. + * @param[in] linkOffset Offset in bytes of a link member in its container, used + * to calculate the pointer to pass to `freeElement`. This value should be calculated + * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL` + * or its value is `0`. + */ +/* @[declare_linear_containers_queue_removeallmatches] */ +static inline void IotDeQueue_RemoveAllMatches( IotDeQueue_t * const pQueue, + bool ( * isMatch )( const IotLink_t *, void * ), + void * pMatch, + void ( * freeElement )( void * ), + size_t linkOffset ) +/* @[declare_linear_containers_queue_removeallmatches] */ +{ + IotListDouble_RemoveAllMatches( pQueue, isMatch, pMatch, freeElement, linkOffset ); +} + +#endif /* IOT_LINEAR_CONTAINERS_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/iot_logging_setup.h b/bsp/aws_libraries/c_sdk/standard/common/include/iot_logging_setup.h new file mode 100644 index 0000000..8d1125a --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/iot_logging_setup.h @@ -0,0 +1,233 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_logging_setup.h + * @brief Defines the logging macro #IotLog. + */ + +#ifndef IOT_LOGGING_SETUP_H_ +#define IOT_LOGGING_SETUP_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Logging include. Because it's included here, iot_logging.h never needs + * to be included in source. */ +#include "private/iot_logging.h" + +/** + * @function_page{IotLog,logging,log} + * @function_snippet{logging,log,this} + * @copydoc IotLog + * @function_page{IotLog_PrintBuffer,logging,printbuffer} + * @function_snippet{logging,printbuffer,this} + * @copydoc IotLog_PrintBuffer + */ + +/** + * @def IotLog( messageLevel, pLogConfig, ... ) + * @brief Logging function for a specific library. In most cases, this is the + * logging function to call. + * + * This function prints a single log message. It is available when @ref + * LIBRARY_LOG_LEVEL is not #IOT_LOG_NONE. Log messages automatically + * include the [log level](@ref logging_constants_levels), [library name] + * (@ref LIBRARY_LOG_NAME), and time. An optional @ref IotLogConfig_t may + * be passed to this function to hide information for a single log message. + * + * The logging library must be set up before this function may be called. See + * @ref logging_setup_use for more information. + * + * This logging function also has the following abbreviated forms that can be used + * when an #IotLogConfig_t isn't needed. + * + * Name | Equivalent to + * ---- | ------------- + * #IotLogError | @code{c} IotLog( IOT_LOG_ERROR, NULL, ... ) @endcode + * #IotLogWarn | @code{c} IotLog( IOT_LOG_WARN, NULL, ... ) @endcode + * #IotLogInfo | @code{c} IotLog( IOT_LOG_INFO, NULL, ... ) @endcode + * #IotLogDebug | @code{c} IotLog( IOT_LOG_DEBUG, NULL, ... ) @endcode + * + * @param[in] messageLevel Log level of this message. Must be one of the + * @ref logging_constants_levels. + * @param[in] pLogConfig Pointer to an #IotLogConfig_t. Optional; pass `NULL` + * to ignore. + * @param[in] ... Message and format specification. + * + * @return No return value. On errors, it prints nothing. + * + * @note This function may be implemented as a macro. + * @see @ref logging_function_generic for the generic (not library-specific) + * logging function. + */ + +/** + * @def IotLog_PrintBuffer( pHeader, pBuffer, bufferSize ) + * @brief Log the contents of buffer as bytes. Only available when @ref + * LIBRARY_LOG_LEVEL is #IOT_LOG_DEBUG. + * + * This function prints the bytes located at a given memory address. It is + * intended for debugging only, and is therefore only available when @ref + * LIBRARY_LOG_LEVEL is #IOT_LOG_DEBUG. + * + * Log messages printed by this function always include the [log level] + * (@ref logging_constants_levels), [library name](@ref LIBRARY_LOG_NAME), + * and time. In addition, this function may print an optional header `pHeader` + * before it prints the contents of the buffer. This function does not have an + * #IotLogConfig_t parameter. + * + * The logging library must be set up before this function may be called. See + * @ref logging_setup_use for more information. + * + * @param[in] pHeader A message to log before the buffer. Optional; pass `NULL` + * to ignore. + * @param[in] pBuffer Pointer to start of buffer. + * @param[in] bufferSize Size of `pBuffer`. + * + * @return No return value. On errors, it prints nothing. + * + * @note This function may be implemented as a macro. + * @note To conserve memory, @ref logging_function_genericprintbuffer (the underlying + * implementation) only allocates enough memory for a single line of output. Therefore, + * in multithreaded systems, its output may appear "fragmented" if other threads are + * logging simultaneously. + * @see @ref logging_function_genericprintbuffer for the generic (not library-specific) + * buffer logging function. + * + * Example + * @code{c} + * const uint8_t pBuffer[] = { 0x00, 0x01, 0x02, 0x03 }; + * + * IotLog_PrintBuffer( "This buffer contains:", + * pBuffer, + * 4 ); + * @endcode + * The code above prints something like the following: + * @code{c} + * [DEBUG][LIB_NAME][2018-01-01 12:00:00] This buffer contains: + * 00 01 02 03 + * @endcode + */ + +/** + * @def IotLogError( ... ) + * @brief Abbreviated logging macro for level #IOT_LOG_ERROR. + * + * Equivalent to: + * @code{c} + * IotLog( IOT_LOG_ERROR, NULL, ... ) + * @endcode + */ + +/** + * @def IotLogWarn( ... ) + * @brief Abbreviated logging macro for level #IOT_LOG_WARN. + * + * Equivalent to: + * @code{c} + * IotLog( IOT_LOG_WARN, NULL, ... ) + * @endcode + */ + +/** + * @def IotLogInfo( ... ) + * @brief Abbreviated logging macro for level #IOT_LOG_INFO. + * + * Equivalent to: + * @code{c} + * IotLog( IOT_LOG_INFO, NULL, ... ) + * @endcode + */ + +/** + * @def IotLogDebug( ... ) + * @brief Abbreviated logging macro for level #IOT_LOG_DEBUG. + * + * Equivalent to: + * @code{c} + * IotLog( IOT_LOG_DEBUG, NULL, ... ) + * @endcode + */ + +/* Check that LIBRARY_LOG_LEVEL is defined and has a valid value. */ +#if !defined( LIBRARY_LOG_LEVEL ) || \ + ( LIBRARY_LOG_LEVEL != IOT_LOG_NONE && \ + LIBRARY_LOG_LEVEL != IOT_LOG_ERROR && \ + LIBRARY_LOG_LEVEL != IOT_LOG_WARN && \ + LIBRARY_LOG_LEVEL != IOT_LOG_INFO && \ + LIBRARY_LOG_LEVEL != IOT_LOG_DEBUG ) + #error "Please define LIBRARY_LOG_LEVEL as either IOT_LOG_NONE, IOT_LOG_ERROR, IOT_LOG_WARN, IOT_LOG_INFO, or IOT_LOG_DEBUG." +/* Check that LIBRARY_LOG_NAME is defined and has a valid value. */ +#elif !defined( LIBRARY_LOG_NAME ) + #error "Please define LIBRARY_LOG_NAME." +#else + /* Define IotLog if the log level is greater than "none". */ + #if LIBRARY_LOG_LEVEL > IOT_LOG_NONE + #ifndef IotLog + #define IotLog( messageLevel, pLogConfig, ... ) \ + IotLog_Generic( LIBRARY_LOG_LEVEL, \ + LIBRARY_LOG_NAME, \ + messageLevel, \ + pLogConfig, \ + __VA_ARGS__ ) + #endif +/* Define the abbreviated logging macros. */ + #define IotLogError( ... ) IotLog( IOT_LOG_ERROR, NULL, __VA_ARGS__ ) + #define IotLogWarn( ... ) IotLog( IOT_LOG_WARN, NULL, __VA_ARGS__ ) + #define IotLogInfo( ... ) IotLog( IOT_LOG_INFO, NULL, __VA_ARGS__ ) + #define IotLogDebug( ... ) IotLog( IOT_LOG_DEBUG, NULL, __VA_ARGS__ ) + +/* If log level is DEBUG, enable the function to print buffers. */ + #if LIBRARY_LOG_LEVEL >= IOT_LOG_DEBUG + #ifndef IotLog_PrintBuffer + #define IotLog_PrintBuffer( pHeader, pBuffer, bufferSize ) \ + IotLog_GenericPrintBuffer( LIBRARY_LOG_NAME, \ + pHeader, \ + pBuffer, \ + bufferSize ) + #endif + #else + #undef IotLog_PrintBuffer + #define IotLog_PrintBuffer( pHeader, pBuffer, bufferSize ) + #endif + /* Remove references to IotLog from the source code if logging is disabled. */ + #else /* if LIBRARY_LOG_LEVEL > IOT_LOG_NONE */ + #undef IotLog + #undef IotLog_PrintBuffer + /* @[declare_logging_log] */ + #define IotLog( messageLevel, pLogConfig, ... ) + /* @[declare_logging_log] */ + /* @[declare_logging_printbuffer] */ + #define IotLog_PrintBuffer( pHeader, pBuffer, bufferSize ) + /* @[declare_logging_printbuffer] */ + #define IotLogError( ... ) + #define IotLogWarn( ... ) + #define IotLogInfo( ... ) + #define IotLogDebug( ... ) + #endif /* if LIBRARY_LOG_LEVEL > IOT_LOG_NONE */ +#endif /* if !defined( LIBRARY_LOG_LEVEL ) || ( LIBRARY_LOG_LEVEL != IOT_LOG_NONE && LIBRARY_LOG_LEVEL != IOT_LOG_ERROR && LIBRARY_LOG_LEVEL != IOT_LOG_WARN && LIBRARY_LOG_LEVEL != IOT_LOG_INFO && LIBRARY_LOG_LEVEL != IOT_LOG_DEBUG ) */ + +#endif /* ifndef IOT_LOGGING_SETUP_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/iot_taskpool.h b/bsp/aws_libraries/c_sdk/standard/common/include/iot_taskpool.h new file mode 100644 index 0000000..3515059 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/iot_taskpool.h @@ -0,0 +1,604 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_taskpool.h + * @brief User-facing functions of the task pool library. + */ + +#ifndef IOT_TASKPOOL_H_ +#define IOT_TASKPOOL_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include + +/* Task pool types. */ +#include "types/iot_taskpool_types.h" + +/*------------------------- Task Pool library functions --------------------------*/ + +/** + * @functions_page{taskpool, Taskpool} + * @functions_brief{task pool} + * - @function_name{taskpool_function_createsystemtaskpool} + * @function_brief{taskpool_function_createsystemtaskpool} + * - @function_name{taskpool_function_getsystemtaskpool} + * @function_brief{taskpool_function_getsystemtaskpool} + * - @function_name{taskpool_function_create} + * @function_brief{taskpool_function_create} + * - @function_name{taskpool_function_destroy} + * @function_brief{taskpool_function_destroy} + * - @function_name{taskpool_function_setmaxthreads} + * @function_brief{taskpool_function_setmaxthreads} + * - @function_name{taskpool_function_createjob} + * @function_brief{taskpool_function_createjob} + * - @function_name{taskpool_function_createrecyclablejob} + * @function_brief{taskpool_function_createrecyclablejob} + * - @function_name{taskpool_function_destroyrecyclablejob} + * @function_brief{taskpool_function_destroyrecyclablejob} + * - @function_name{taskpool_function_recyclejob} + * @function_brief{taskpool_function_recyclejob} + * - @function_name{taskpool_function_schedule} + * @function_brief{taskpool_function_schedule} + * - @function_name{taskpool_function_scheduledeferred} + * @function_brief{taskpool_function_scheduledeferred} + * - @function_name{taskpool_function_getstatus} + * @function_brief{taskpool_function_getstatus} + * - @function_name{taskpool_function_trycancel} + * @function_brief{taskpool_function_trycancel} + * - @function_name{taskpool_function_getjobstoragefromhandle} + * @function_brief{taskpool_function_getjobstoragefromhandle} + * - @function_name{taskpool_function_strerror} + * @function_brief{taskpool_function_strerror} + */ + +/** + * @function_page{IotTaskPool_CreateSystemTaskPool,taskpool,createsystemtaskpool} + * @function_snippet{taskpool,createsystemtaskpool,this} + * @copydoc IotTaskPool_CreateSystemTaskPool + * @function_page{IotTaskPool_GetSystemTaskPool,taskpool,getsystemtaskpool} + * @function_snippet{taskpool,getsystemtaskpool,this} + * @copydoc IotTaskPool_GetSystemTaskPool + * @function_page{IotTaskPool_Create,taskpool,create} + * @function_snippet{taskpool,create,this} + * @copydoc IotTaskPool_Create + * @function_page{IotTaskPool_Destroy,taskpool,destroy} + * @function_snippet{taskpool,destroy,this} + * @copydoc IotTaskPool_Destroy + * @function_page{IotTaskPool_SetMaxThreads,taskpool,setmaxthreads} + * @function_snippet{taskpool,setmaxthreads,this} + * @copydoc IotTaskPool_SetMaxThreads + * @function_page{IotTaskPool_CreateJob,taskpool,createjob} + * @function_snippet{taskpool,createjob,this} + * @copydoc IotTaskPool_CreateJob + * @function_page{IotTaskPool_CreateRecyclableJob,taskpool,createrecyclablejob} + * @function_snippet{taskpool,createrecyclablejob,this} + * @copydoc IotTaskPool_CreateRecyclableJob + * @function_page{IotTaskPool_DestroyRecyclableJob,taskpool,destroyrecyclablejob} + * @function_snippet{taskpool,destroyrecyclablejob,this} + * @copydoc IotTaskPool_DestroyRecyclableJob + * @function_page{IotTaskPool_RecycleJob,taskpool,recyclejob} + * @function_snippet{taskpool,recyclejob,this} + * @copydoc IotTaskPool_RecycleJob + * @function_page{IotTaskPool_Schedule,taskpool,schedule} + * @function_snippet{taskpool,schedule,this} + * @copydoc IotTaskPool_Schedule + * @function_page{IotTaskPool_ScheduleDeferred,taskpool,scheduledeferred} + * @function_snippet{taskpool,scheduledeferred,this} + * @copydoc IotTaskPool_ScheduleDeferred + * @function_page{IotTaskPool_GetStatus,taskpool,getstatus} + * @function_snippet{taskpool,getstatus,this} + * @copydoc IotTaskPool_GetStatus + * @function_page{IotTaskPool_TryCancel,taskpool,trycancel} + * @function_snippet{taskpool,trycancel,this} + * @copydoc IotTaskPool_TryCancel + * @function_page{IotTaskPool_GetJobStorageFromHandle,taskpool,getjobstoragefromhandle} + * @function_snippet{taskpool,getjobstoragefromhandle,this} + * @copydoc IotTaskPool_GetJobStorageFromHandle + * @function_page{IotTaskPool_strerror,taskpool,strerror} + * @function_snippet{taskpool,strerror,this} + * @copydoc IotTaskPool_strerror + */ + +/** + * @brief Creates the one single instance of the system task pool. + * + * This function should be called once by the application to initialize the one single instance of the system task pool. + * An application should initialize the system task pool early in the boot sequence, before initializing any other library + * and before posting any jobs. Early initialization it typically easy to accomplish by creating the system task pool + * before starting the scheduler. + * + * This function does not allocate memory to hold the task pool data structures and state, but it + * may allocate memory to hold the dependent entities and data structures, e.g. the threads of the task + * pool. The system task pool handle is recoverable for later use by calling @ref IotTaskPool_GetSystemTaskPool or + * the shortcut @ref IOT_SYSTEM_TASKPOOL. + * + * @param[in] pInfo A pointer to the task pool initialization data. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_NO_MEMORY + * + * @warning This function should be called only once. Calling this function more that once will result in + * undefined behavior. + * + */ +/* @[declare_taskpool_createsystemtaskpool] */ +IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo ); +/* @[declare_taskpool_createsystemtaskpool] */ + +/** + * @brief Retrieves the one and only instance of a system task pool + * + * This function retrieves the system task pool created with @ref IotTaskPool_CreateSystemTaskPool, and it is functionally + * equivalent to using the shortcut @ref IOT_SYSTEM_TASKPOOL. + * + * @return The system task pool handle. + * + * @warning This function should be called after creating the system task pool with @ref IotTaskPool_CreateSystemTaskPool. + * Calling this function before creating the system task pool may return a pointer to an uninitialized task pool, NULL, or otherwise + * fail with undefined behaviour. + * + */ +/* @[declare_taskpool_getsystemtaskpool] */ +IotTaskPool_t IotTaskPool_GetSystemTaskPool( void ); +/* @[declare_taskpool_getsystemtaskpool] */ + +/** + * @brief Creates one instance of a task pool. + * + * This function should be called by the user to initialize one instance of a task + * pool. The task pool instance will be created around the storage pointed to by the `pTaskPool` + * parameter. This function will create the minimum number of threads requested by the user + * through an instance of the #IotTaskPoolInfo_t type specified with the `pInfo` parameter. + * This function does not allocate memory to hold the task pool data structures and state, but it + * may allocates memory to hold the dependent data structures, e.g. the threads of the task + * pool. + * + * @param[in] pInfo A pointer to the task pool initialization data. + * @param[out] pTaskPool A pointer to the task pool handle to be used after initialization. + * The pointer `pTaskPool` will hold a valid handle only if (@ref IotTaskPool_Create) + * completes successfully. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_NO_MEMORY + * + */ +/* @[declare_taskpool_create] */ +IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo, + IotTaskPool_t * const pTaskPool ); +/* @[declare_taskpool_create] */ + +/** + * @brief Destroys a task pool instance and collects all memory associated with a task pool and its + * satellite data structures. + * + * This function should be called to destroy one instance of a task pool previously created with a call + * to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool. + * Calling this fuction release all underlying resources. After calling this function, any job scheduled but not yet executed + * will be cancelled and destroyed. + * The `taskPool` instance will no longer be valid after this function returns. + * + * @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create or + * @ref IotTaskPool_CreateSystemTaskPool. The `taskPool` instance will no longer be valid after this function returns. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * + */ +/* @[declare_taskpool_destroy] */ +IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPool ); +/* @[declare_taskpool_destroy] */ + +/** + * @brief Sets the maximum number of threads for one instance of a task pool. + * + * This function sets the maximum number of threads for the task pool + * pointed to by `taskPool`. + * + * If the number of currently active threads in the task pool is greater than `maxThreads`, this + * function causes the task pool to shrink the number of active threads. + * + * @param[in] taskPool A handle to the task pool that must have been previously initialized with + * a call to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool. + * @param[in] maxThreads The maximum number of threads for the task pool. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + */ +/* @[declare_taskpool_setmaxthreads] */ +IotTaskPoolError_t IotTaskPool_SetMaxThreads( IotTaskPool_t taskPool, + uint32_t maxThreads ); +/* @[declare_taskpool_setmaxthreads] */ + +/** + * @brief Creates a job for the task pool around a user-provided storage. + * + * This function may allocate memory to hold the state for a job. + * + * @param[in] userCallback A user-specified callback for the job. + * @param[in] pUserContext A user-specified context for the callback. + * @param[in] pJobStorage The storage for the job data structure. + * @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this + * function returns successfully. This handle can be used to inspect the job status with + * @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc.... + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * + * + */ +/* @[declare_taskpool_createjob] */ +IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback, + void * pUserContext, + IotTaskPoolJobStorage_t * const pJobStorage, + IotTaskPoolJob_t * const pJob ); +/* @[declare_taskpool_createjob] */ + +/** + * @brief Creates a job for the task pool by allocating the job dynamically. + * + * A recyclable job does not need to be allocated twice, but it can rather be reused through + * subsequent calls to @ref IotTaskPool_CreateRecyclableJob. + * + * @param[in] taskPool A handle to the task pool for which to create a recyclable job. + * @param[in] userCallback A user-specified callback for the job. + * @param[in] pUserContext A user-specified context for the callback. + * @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this + * function returns successfully. This handle can be used to inspect the job status with + * @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc.... + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_NO_MEMORY + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + * @note This function will not allocate memory. + * + * @warning A recyclable job should be recycled with a call to @ref IotTaskPool_RecycleJob rather than destroyed. + * + */ +/* @[declare_taskpool_createrecyclablejob] */ +IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPool, + IotTaskPoolRoutine_t userCallback, + void * pUserContext, + IotTaskPoolJob_t * const pJob ); +/* @[declare_taskpool_createrecyclablejob] */ + +/** + * @brief This function un-initializes a job. + * + * This function will destroy a job created with @ref IotTaskPool_CreateRecyclableJob. + * A job should not be destroyed twice. A job that was previously scheduled but has not completed yet should not be destroyed, + * but rather the application should attempt to cancel it first by calling @ref IotTaskPool_TryCancel. + * An attempt to destroy a job that was scheduled but not yet executed or canceled, may result in a + * @ref IOT_TASKPOOL_ILLEGAL_OPERATION error. + * + * @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool. + * @param[in] job A handle to a job that was create with a call to @ref IotTaskPool_CreateJob. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_ILLEGAL_OPERATION + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + * @warning The task pool will try and prevent destroying jobs that are currently queued for execution, but does + * not enforce strict ordering of operations. It is up to the user to make sure @ref IotTaskPool_DestroyRecyclableJob is not called + * our of order. + * + * @warning Calling this function on job that was not previously created with @ref IotTaskPool_CreateRecyclableJob + * will result in a @ref IOT_TASKPOOL_ILLEGAL_OPERATION error. + * + */ +/* @[declare_taskpool_destroyrecyclablejob] */ +IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPool, + IotTaskPoolJob_t job ); +/* @[declare_taskpool_destroyrecyclablejob] */ + +/** + * @brief Recycles a job into the task pool job cache. + * + * This function will try and recycle the job into the task pool cache. If the cache is full, + * the job memory is destroyed as if the user called @ref IotTaskPool_DestroyRecyclableJob. The job should be recycled into + * the task pool instance from where it was allocated. + * Failure to do so will yield undefined results. A job should not be recycled twice. A job + * that was previously scheduled but not completed or canceled cannot be safely recycled. An attempt to do so will result + * in an @ref IOT_TASKPOOL_ILLEGAL_OPERATION error. + * + * @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create. + * @param[out] job A pointer to a job that was create with a call to @ref IotTaskPool_CreateJob. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_ILLEGAL_OPERATION + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + * @warning The `taskPool` used in this function should be the same + * used to create the job pointed to by `job`, or the results will be undefined. + * + * @warning Attempting to call this function on a statically allocated job will result in @ref IOT_TASKPOOL_ILLEGAL_OPERATION + * error. + * + * @warning This function should be used to recycle a job in the task pool cache when after the job executed. + * Failing to call either this function or @ref IotTaskPool_DestroyRecyclableJob will result is a memory leak. Statically + * allocated jobs do not need to be recycled or destroyed. + * + */ +/* @[declare_taskpool_recyclejob] */ +IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPool, + IotTaskPoolJob_t job ); +/* @[declare_taskpool_recyclejob] */ + +/** + * @brief This function schedules a job created with @ref IotTaskPool_CreateJob or @ref IotTaskPool_CreateRecyclableJob + * against the task pool pointed to by `taskPool`. + * + * See @ref taskpool_design for a description of the jobs lifetime and interaction with the threads used in the task pool + * library. + * + * @param[in] taskPool A handle to the task pool that must have been previously initialized with. + * a call to @ref IotTaskPool_Create. + * @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob. + * @param[in] flags Flags to be passed by the user, e.g. to identify the job as high priority by specifying #IOT_TASKPOOL_JOB_HIGH_PRIORITY. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_ILLEGAL_OPERATION + * - #IOT_TASKPOOL_NO_MEMORY + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + * + * @note This function will not allocate memory, so it is guaranteed to succeed if the paramters are correct and the task pool + * was correctly initialized, and not yet destroyed. + * + * @warning The `taskPool` used in this function should be the same used to create the job pointed to by `job`, or the + * results will be undefined. + * + * Example + * @code{c} + * // An example of a user context to pass to a callback through a task pool thread. + * typedef struct JobUserContext + * { + * uint32_t counter; + * } JobUserContext_t; + * + * // An example of a user callback to invoke through a task pool thread. + * static void ExecutionCb( IotTaskPool_t taskPool, IotTaskPoolJob_t job, void * context ) + * { + * ( void )taskPool; + * ( void )job; + * + * JobUserContext_t * pUserContext = ( JobUserContext_t * )context; + * + * pUserContext->counter++; + * } + * + * void TaskPoolExample( ) + * { + * JobUserContext_t userContext = { 0 }; + * IotTaskPoolJob_t job; + * IotTaskPool_t taskPool; + * + * // Configure the task pool to hold at least two threads and three at the maximum. + * // Provide proper stack size and priority per the application needs. + * + * const IotTaskPoolInfo_t tpInfo = { .minThreads = 2, .maxThreads = 3, .stackSize = 512, .priority = 0 }; + * + * // Create a task pool. + * IotTaskPool_Create( &tpInfo, &taskPool ); + * + * // Statically allocate one job, schedule it. + * IotTaskPool_CreateJob( &ExecutionCb, &userContext, &job ); + * + * IotTaskPoolError_t errorSchedule = IotTaskPool_Schedule( taskPool, &job, 0 ); + * + * switch ( errorSchedule ) + * { + * case IOT_TASKPOOL_SUCCESS: + * break; + * case IOT_TASKPOOL_BAD_PARAMETER: // Invalid parameters, such as a NULL handle, can trigger this error. + * case IOT_TASKPOOL_ILLEGAL_OPERATION: // Scheduling a job that was previously scheduled or destroyed could trigger this error. + * case IOT_TASKPOOL_NO_MEMORY: // Scheduling a with flag #IOT_TASKPOOL_JOB_HIGH_PRIORITY could trigger this error. + * case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS: // Scheduling a job after trying to destroy the task pool could trigger this error. + * // ASSERT + * break; + * default: + * // ASSERT + * } + * + * // + * // ... Perform other operations ... + * // + * + * IotTaskPool_Destroy( taskPool ); + * } + * @endcode + */ +/* @[declare_taskpool_schedule] */ +IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool, + IotTaskPoolJob_t job, + uint32_t flags ); +/* @[declare_taskpool_schedule] */ + +/** + * @brief This function schedules a job created with @ref IotTaskPool_CreateJob against the task pool + * pointed to by `taskPool` to be executed after a user-defined time interval. + * + * See @ref taskpool_design for a description of the jobs lifetime and interaction with the threads used in the task pool + * library. + * + * @param[in] taskPool A handle to the task pool that must have been previously initialized with. + * a call to @ref IotTaskPool_Create. + * @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob. + * @param[in] timeMs The time in milliseconds to wait before scheduling the job. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_ILLEGAL_OPERATION + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + * + * @note This function will not allocate memory. + * + * @warning The `taskPool` used in this function should be the same + * used to create the job pointed to by `job`, or the results will be undefined. + * + */ +/* @[declare_taskpool_scheduledeferred] */ +IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPool, + IotTaskPoolJob_t job, + uint32_t timeMs ); +/* @[declare_taskpool_scheduledeferred] */ + +/** + * @brief This function retrieves the current status of a job. + * + * @param[in] taskPool A handle to the task pool that must have been previously initialized with + * a call to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool. + * @param[in] job The job to cancel. + * @param[out] pStatus The status of the job at the time of cancellation. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * + * @warning This function is not thread safe and the job status returned in `pStatus` may be invalid by the time + * the calling thread has a chance to inspect it. + */ +/* @[declare_taskpool_getstatus] */ +IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPool, + IotTaskPoolJob_t job, + IotTaskPoolJobStatus_t * const pStatus ); +/* @[declare_taskpool_getstatus] */ + +/** + * @brief This function tries to cancel a job that was previously scheduled with @ref IotTaskPool_Schedule. + * + * A job can be canceled only if it is not yet executing, i.e. if its status is + * @ref IOT_TASKPOOL_STATUS_READY or @ref IOT_TASKPOOL_STATUS_SCHEDULED. Calling + * @ref IotTaskPool_TryCancel on a job whose status is @ref IOT_TASKPOOL_STATUS_COMPLETED, + * or #IOT_TASKPOOL_STATUS_CANCELED will yield a #IOT_TASKPOOL_CANCEL_FAILED return result. + * + * @param[in] taskPool A handle to the task pool that must have been previously initialized with + * a call to @ref IotTaskPool_Create. + * @param[in] job The job to cancel. + * @param[out] pStatus The status of the job at the time of cancellation. + * + * @return One of the following: + * - #IOT_TASKPOOL_SUCCESS + * - #IOT_TASKPOOL_BAD_PARAMETER + * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS + * - #IOT_TASKPOOL_CANCEL_FAILED + * + * @warning The `taskPool` used in this function should be the same + * used to create the job pointed to by `job`, or the results will be undefined. + * + */ +/* @[declare_taskpool_trycancel] */ +IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPool, + IotTaskPoolJob_t job, + IotTaskPoolJobStatus_t * const pStatus ); +/* @[declare_taskpool_trycancel] */ + +/** + * @brief Returns a pointer to the job storage from an instance of a job handle + * of type @ref IotTaskPoolJob_t. This function is guaranteed to succeed for a + * valid job handle. + * + * @param[in] job The job handle. + * + * @return A pointer to the storage associated with the job handle `job`. + * + * @warning If the `job` handle used is invalid, the results will be undefined. + */ +/* @[declare_taskpool_getjobstoragefromhandle] */ +IotTaskPoolJobStorage_t * IotTaskPool_GetJobStorageFromHandle( IotTaskPoolJob_t job ); +/* @[declare_taskpool_getjobstoragefromhandle] */ + +/** + * @brief Returns a string that describes an @ref IotTaskPoolError_t. + * + * Like the POSIX's `strerror`, this function returns a string describing a + * return code. In this case, the return code is a task pool library error code, + * `status`. + * + * The string returned by this function MUST be treated as read-only: any + * attempt to modify its contents may result in a crash. Therefore, this function + * is limited to usage in logging. + * + * @param[in] status The status to describe. + * + * @return A read-only string that describes `status`. + * + * @warning The string returned by this function must never be modified. + */ +/* @[declare_taskpool_strerror] */ +const char * IotTaskPool_strerror( IotTaskPoolError_t status ); +/* @[declare_taskpool_strerror] */ + +/** + * @brief The maximum number of task pools to be created when using + * a memory pool. + */ +#ifndef IOT_TASKPOOLS + #define IOT_TASKPOOLS ( 4 ) +#endif + +/** + * @brief The maximum number of jobs to cache. + */ +#ifndef IOT_TASKPOOL_JOBS_RECYCLE_LIMIT + #define IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ( 8UL ) +#endif + +/** + * @brief The maximum timeout in milliseconds to wait for a job to be scheduled before waking up a worker thread. + * A worker thread that wakes up as a result of a timeout may exit to allow the task pool to fold back to its + * minimum number of threads. + */ +#ifndef IOT_TASKPOOL_JOB_WAIT_TIMEOUT_MS + #define IOT_TASKPOOL_JOB_WAIT_TIMEOUT_MS ( 60 * 1000UL ) +#endif + +#endif /* ifndef IOT_TASKPOOL_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_default_root_certificates.h b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_default_root_certificates.h new file mode 100644 index 0000000..f8243e7 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_default_root_certificates.h @@ -0,0 +1,197 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +#ifndef __DEFAULT__ROOT__CERTIFICATES__H__ +#define __DEFAULT__ROOT__CERTIFICATES__H__ + +/* + * https://www.amazontrust.com/repository/AmazonRootCA1.pem + * RSA 2048-bit + */ +static const char tlsATS1_ROOT_CERTIFICATE_PEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n" + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" + "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n" + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" + "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n" + "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n" + "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n" + "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n" + "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n" + "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n" + "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n" + "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n" + "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n" + "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n" + "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n" + "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n" + "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n" + "rqXRfboQnoZsG4q5WTP468SQvvG5\n" + "-----END CERTIFICATE-----\n"; +static const uint32_t tlsATS1_ROOT_CERTIFICATE_LENGTH = sizeof( tlsATS1_ROOT_CERTIFICATE_PEM ); + +/* + * https://www.amazontrust.com/repository/AmazonRootCA2.pem + * RSA 4096-bit + */ +static const char tlsATS2_ROOT_CERTIFICATE_PEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF\n" + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" + "b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL\n" + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" + "b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK\n" + "gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ\n" + "W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg\n" + "1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K\n" + "8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r\n" + "2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me\n" + "z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR\n" + "8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj\n" + "mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz\n" + "7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6\n" + "+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI\n" + "0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB\n" + "Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm\n" + "UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2\n" + "LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY\n" + "+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS\n" + "k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl\n" + "7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm\n" + "btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl\n" + "urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+\n" + "fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63\n" + "n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE\n" + "76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H\n" + "9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT\n" + "4PsJYGw=\n" + "-----END CERTIFICATE-----\n"; +static const uint32_t tlsATS2_ROOT_CERTIFICATE_LENGTH = sizeof( tlsATS2_ROOT_CERTIFICATE_PEM ); + +/* + * https://www.amazontrust.com/repository/AmazonRootCA3.pem + * EC 256-bit + */ +static const char tlsATS3_ROOT_CERTIFICATE_PEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n" + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" + "Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" + "Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n" + "ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n" + "QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n" + "ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n" + "BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n" + "YyRIHN8wfdVoOw==\n" + "-----END CERTIFICATE-----\n"; +static const uint32_t tlsATS3_ROOT_CERTIFICATE_LENGTH = sizeof( tlsATS3_ROOT_CERTIFICATE_PEM ); + +/* + * https://www.amazontrust.com/repository/AmazonRootCA4.pem + * EC 384-bit + */ +static const char tlsATS4_ROOT_CERTIFICATE_PEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5\n" + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" + "Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" + "Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi\n" + "9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk\n" + "M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB\n" + "/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB\n" + "MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw\n" + "CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW\n" + "1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" + "-----END CERTIFICATE-----\n"; +static const uint32_t tlsATS4_ROOT_CERTIFICATE_LENGTH = sizeof( tlsATS4_ROOT_CERTIFICATE_PEM ); + +/* + * Starfield Cross-signing CA + */ +static const char tlsSTARFIELD_ROOT_CERTIFICATE_PEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n" + "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n" + "U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n" + "NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n" + "ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n" + "ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n" + "DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n" + "8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n" + "+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n" + "X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n" + "K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n" + "1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n" + "A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n" + "zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n" + "YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n" + "bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n" + "DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n" + "L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n" + "eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n" + "xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n" + "VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n" + "WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n" + "-----END CERTIFICATE-----\n"; +static const uint32_t tlsSTARFIELD_ROOT_CERTIFICATE_LENGTH = sizeof( tlsSTARFIELD_ROOT_CERTIFICATE_PEM ); + +/* + * VeriSign-Class 3-Public-Primary-Certification-Authority-G5 + */ +static const char tlsVERISIGN_ROOT_CERTIFICATE_PEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n" + "yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n" + "ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\n" + "U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\n" + "ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\n" + "aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL\n" + "MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW\n" + "ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln\n" + "biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp\n" + "U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\n" + "aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1\n" + "nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex\n" + "t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz\n" + "SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG\n" + "BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+\n" + "rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/\n" + "NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E\n" + "BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH\n" + "BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy\n" + "aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv\n" + "MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE\n" + "p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y\n" + "5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK\n" + "WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ\n" + "4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N\n" + "hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq\n" + "-----END CERTIFICATE-----\n"; +static const uint32_t tlsVERISIGN_ROOT_CERTIFICATE_LENGTH = sizeof( tlsVERISIGN_ROOT_CERTIFICATE_PEM ); + +#endif /* ifndef __DEFAULT__ROOT__CERTIFICATES__H__ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_doubly_linked_list.h b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_doubly_linked_list.h new file mode 100644 index 0000000..12f2551 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_doubly_linked_list.h @@ -0,0 +1,242 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_doubly_linked_list.h + * @brief Doubly Linked List implementation. + * + * A generic implementation of circular Doubly Linked List which consists of a + * list head and some list entries (zero in case of an empty list). + * + * To start with, a structure of type Link_t should be embedded in the structure + * which is to be organized as doubly linked list. + * @code + * typedef struct UserStruct + * { + * uint32_t ulField1; + * uint32_t ulField2; + * Link_t xLink; + * } UserStruct_t; + * @endcode + * + * A List head should then be defined and initialized. + * @code + * Link_t xListHead; + * listINIT_HEAD( &xListHead ); + * @endcode + * + * listADD can then be used to add nodes to the list. + * @code + * listADD( &( xListHead ), &( pxUserStruct->xLink ) ); + * @endcode + * + * listFOR_EACH can be used for traversing the list. + * @code + * Link_t *pxLink; + * UserStruct_t *pxUserStruct; + * listFOR_EACH( pxLink, &( xListHead ) ) + * { + * pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink ); + * } + * @endcode + * + * listFOR_EACH_SAFE should be used if you want to perform destructive operations + * (like free) on nodes while traversing the list. + * @code + * Link_t *pxLink, *pxTempLink; + * UserStruct_t *pxUserStruct; + * listFOR_EACH( pxLink, pxTempLink, &( xListHead ) ) + * { + * pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink ); + * free( pxUserStruct ); + * } + * @endcode + */ + +#ifndef _AWS_DOUBLY_LINKED_LIST_H_ +#define _AWS_DOUBLY_LINKED_LIST_H_ + +#include +#include + +/** + * @brief Struct embedded in any struct to make it a doubly linked + * list. + * + * pxNext in the head points to the first node in the list and pxPrev + * in the head points to the last node in the list. In case of empty + * list, both pxPrev and pxNext in the head point to the head node itself. + */ +typedef struct Link +{ + struct Link * pxPrev; /**< Pointer to the previous node. */ + struct Link * pxNext; /**< Pointer to the next node. */ +} Link_t; + +/** + * @brief Initializes the given list head to an empty list. + * + * @param[in] pxHead The given list head to initialize. + */ +#define listINIT_HEAD( pxHead ) \ + { \ + ( pxHead )->pxPrev = ( pxHead ); \ + ( pxHead )->pxNext = ( pxHead ); \ + } + +/** + * @brief Adds the given new node to the given list. + * + * @param[in] pxHead The head of the given list. + * @param[in] pxLink The given new node to be added to the given + * list. + */ +#define listADD( pxHead, pxLink ) \ + { \ + Link_t * pxPrevLink = ( pxHead ); \ + Link_t * pxNextLink = ( ( pxHead )->pxNext ); \ + \ + ( pxLink )->pxNext = pxNextLink; \ + pxNextLink->pxPrev = ( pxLink ); \ + pxPrevLink->pxNext = ( pxLink ); \ + ( pxLink )->pxPrev = ( pxPrevLink ); \ + } + +/** + * @brief Removes the given node from the list it is part of. + * + * If the given node is not a part of any list (i.e. next and previous + * nodes are NULL), nothing happens. + * + * @param[in] pxLink The given node to remove from the list. + */ +#define listREMOVE( pxLink ) \ + { \ + /* If the link is part of a list, remove it from the list. */ \ + if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL ) \ + { \ + ( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext; \ + ( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev; \ + } \ + \ + /* Make sure that this link is not part of any list anymore. */ \ + ( pxLink )->pxPrev = NULL; \ + ( pxLink )->pxNext = NULL; \ + } + +/** + * @brief Given the head of a list, checks if the list is empty. + * + * @param[in] pxHead The head of the given list. + */ +#define listIS_EMPTY( pxHead ) ( ( ( pxHead ) == NULL ) || ( ( pxHead )->pxNext == ( pxHead ) ) ) + +/** + * @brief Removes the first node from the given list and returns it. + * + * Removes the first node from the given list and assigns it to the + * pxLink parameter. If the list is empty, it assigns NULL to the + * pxLink. + * + * @param[in] pxHead The head of the list from which to remove the + * first node. + * @param[out] pxLink The output parameter to receive the removed + * node. + */ +#define listPOP( pxHead, pxLink ) \ + { \ + if( listIS_EMPTY( ( pxHead ) ) ) \ + { \ + ( pxLink ) = NULL; \ + } \ + else \ + { \ + ( pxLink ) = ( pxHead )->pxNext; \ + /* If the link is part of a list, remove it from the list. */ \ + if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL ) \ + { \ + ( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext; \ + ( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev; \ + } \ + \ + /* Make sure that this link is not part of any list anymore. */ \ + ( pxLink )->pxPrev = NULL; \ + ( pxLink )->pxNext = NULL; \ + } \ + } + +/** + * @brief Merges a list into a given list. + * + * @param[in] pxHeadResultList The head of the given list into which the + * other list should be merged. + * @param[in] pxHeadListToMerge The head of the list to be merged into the + * given list. + */ +#define listMERGE( pxHeadResultList, pxHeadListToMerge ) \ + { \ + if( !listIS_EMPTY( ( pxHeadListToMerge ) ) ) \ + { \ + /* Setup links between last node of listToMerge and first node of resultList. */ \ + ( pxHeadListToMerge )->pxPrev->pxNext = ( pxHeadResultList )->pxNext; \ + ( pxHeadResultList )->pxNext->pxPrev = ( pxHeadListToMerge )->pxPrev; \ + \ + /* Setup links between first node of listToMerge and the head of resultList. */ \ + ( pxHeadListToMerge )->pxNext->pxPrev = ( pxHeadResultList ); \ + ( pxHeadResultList )->pxNext = ( pxHeadListToMerge )->pxNext; \ + /* Empty the merged list. */ \ + listINIT_HEAD( ( pxHeadListToMerge ) ); \ + } \ + } + +/** + * @brief Helper macro to iterate over a list. pxLink contains the link node + * in each iteration. + */ +#define listFOR_EACH( pxLink, pxHead ) \ + for( ( pxLink ) = ( pxHead )->pxNext; \ + ( pxLink ) != ( pxHead ); \ + ( pxLink ) = ( pxLink )->pxNext ) + +/** + * @brief Helper macro to iterate over a list. It is safe to destroy/free the + * nodes while iterating. pxLink contains the link node in each iteration. + */ +#define listFOR_EACH_SAFE( pxLink, pxTempLink, pxHead ) \ + for( ( pxLink ) = ( pxHead )->pxNext, ( pxTempLink ) = ( pxLink )->pxNext; \ + ( pxLink ) != ( pxHead ); \ + ( pxLink ) = ( pxTempLink ), ( pxTempLink ) = ( pxLink )->pxNext ) + +/** + * @brief Given the pointer to the link member (of type Link_t) in a struct, + * extracts the pointer to the containing struct. + * + * @param[in] pxLink The pointer to the link member. + * @param[in] type The type of the containing struct. + * @param[in] member Name of the link member in the containing struct. + */ +#define listCONTAINER( pxLink, type, member ) ( ( type * ) ( ( uint8_t * ) ( pxLink ) - ( uint8_t * ) ( &( ( type * ) 0 )->member ) ) ) + +#endif /* _AWS_DOUBLY_LINKED_LIST_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_error.h b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_error.h new file mode 100644 index 0000000..c14be22 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_error.h @@ -0,0 +1,117 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_error.h + * @brief Provides macros for error checking and function cleanup. + * + * The macros in this file are generic. They may be customized by each library + * by setting the library prefix. + */ + +#ifndef IOT_ERROR_H_ +#define IOT_ERROR_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/** + * @brief Declare the status variable and an initial value. + * + * This macro should be at the beginning of any functions that use cleanup sections. + * + * @param[in] statusType The type of the status variable for this function. + * @param[in] initialValue The initial value to assign to the status variable. + */ +#define IOT_FUNCTION_ENTRY( statusType, initialValue ) statusType status = initialValue + +/** + * @brief Declares the label that begins a cleanup section. + * + * This macro should be placed at the end of a function and followed by + * #IOT_FUNCTION_CLEANUP_END. + */ +#define IOT_FUNCTION_CLEANUP_BEGIN() iotCleanup : + +/** + * @brief Declares the end of a cleanup section. + * + * This macro should be placed at the end of a function and preceded by + * #IOT_FUNCTION_CLEANUP_BEGIN. + */ +#define IOT_FUNCTION_CLEANUP_END() return status + +/** + * @brief Declares an empty cleanup section. + * + * This macro should be placed at the end of a function to exit on error if no + * cleanup is required. + */ +#define IOT_FUNCTION_EXIT_NO_CLEANUP() IOT_FUNCTION_CLEANUP_BEGIN(); IOT_FUNCTION_CLEANUP_END() + +/** + * @brief Jump to the cleanup section. + */ +#define IOT_GOTO_CLEANUP() goto iotCleanup + +/** + * @brief Assign a value to the status variable and jump to the cleanup section. + * + * @param[in] statusValue The value to assign to the status variable. + */ +#define IOT_SET_AND_GOTO_CLEANUP( statusValue ) { status = ( statusValue ); IOT_GOTO_CLEANUP(); } + +/** + * @brief Jump to the cleanup section if a condition is `false`. + * + * This macro may be used in place of `assert` to exit a function is a condition + * is `false`. + * + * @param[in] condition The condition to check. + */ +#define IOT_GOTO_CLEANUP_IF_FALSE( condition ) { if( ( condition ) == false ) { IOT_GOTO_CLEANUP(); } } + +/** + * @brief Assign a value to the status variable and jump to the cleanup section + * if a condition is `false`. + * + * @param[in] statusValue The value to assign to the status variable. + * @param[in] condition The condition to check. + */ +#define IOT_SET_AND_GOTO_CLEANUP_IF_FALSE( statusValue, condition ) \ + if( ( condition ) == false ) \ + IOT_SET_AND_GOTO_CLEANUP( statusValue ) + +/** + * @brief Check a condition; if `false`, assign the "Bad parameter" status value + * and jump to the cleanup section. + * + * @param[in] libraryPrefix The library prefix of the status variable. + * @param[in] condition The condition to check. + */ +#define IOT_VALIDATE_PARAMETER( libraryPrefix, condition ) \ + IOT_SET_AND_GOTO_CLEANUP_IF_FALSE( libraryPrefix ## _BAD_PARAMETER, condition ) + +#endif /* ifndef IOT_ERROR_H_ */ diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipUTF8.c b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_lib_init.h similarity index 75% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipUTF8.c rename to bsp/aws_libraries/c_sdk/standard/common/include/private/iot_lib_init.h index 03716a4..f53ed73 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipUTF8.c +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_lib_init.h @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * FreeRTOS Common V1.2.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -18,19 +18,16 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org */ -#include "skipGeneric.h" +#ifndef _AWS_LIB_INIT_H_ +#define _AWS_LIB_INIT_H_ -/* - * This function is a replacement for the function of the same name from core_json.c. - * Please see core_json.c for documentation. - */ +#include "FreeRTOS.h" + +#define lib_initDECLARE_LIB_INIT( f ) extern BaseType_t f( void ) -bool skipUTF8( const char * buf, - size_t * start, - size_t max ) -{ - /* min argument is 1 for a single ASCII character. */ - return skipGeneric( buf, start, max, 1 ); -} +#endif /* _AWS_LIB_INIT_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_logging.h b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_logging.h new file mode 100644 index 0000000..f5067aa --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_logging.h @@ -0,0 +1,240 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_logging.h + * @brief Generic logging function header file. + * + * Declares the generic logging function and the log levels. This file never + * needs to be included in source code. The header iot_logging_setup.h should + * be included instead. + * + * @see iot_logging_setup.h + */ + +#ifndef IOT_LOGGING_H_ +#define IOT_LOGGING_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include + +/** + * @constants_page{logging} + * @constants_brief{logging library} + * + * @section logging_constants_levels Log levels + * @brief Log levels for the libraries in this SDK. + * + * Each library should specify a log level by setting @ref LIBRARY_LOG_LEVEL. + * All log messages with a level at or below the specified level will be printed + * for that library. + * + * Currently, there are 4 log levels. In the order of lowest to highest, they are: + * - #IOT_LOG_NONE
+ * @copybrief IOT_LOG_NONE + * - #IOT_LOG_ERROR
+ * @copybrief IOT_LOG_ERROR + * - #IOT_LOG_WARN
+ * @copybrief IOT_LOG_WARN + * - #IOT_LOG_INFO
+ * @copybrief IOT_LOG_INFO + * - #IOT_LOG_DEBUG
+ * @copybrief IOT_LOG_DEBUG + */ + +/** + * @brief No log messages. + * + * Log messages with this level will be silently discarded. When @ref + * LIBRARY_LOG_LEVEL is #IOT_LOG_NONE, logging is disabled and no [logging functions] + * (@ref logging_functions) can be called. + */ +#define IOT_LOG_NONE 0 + +/** + * @brief Only critical, unrecoverable errors. + * + * Log messages with this level will be printed when a library encounters an + * error from which it cannot easily recover. + */ +#define IOT_LOG_ERROR 1 + +/** + * @brief Message about an abnormal but recoverable event. + * + * Log messages with this level will be printed when a library encounters an + * abnormal event that may be indicative of an error. Libraries should continue + * execution after logging a warning. + */ +#define IOT_LOG_WARN 2 + +/** + * @brief A helpful, informational message. + * + * Log messages with this level may indicate the normal status of a library + * function. They should be used to track how far a program has executed. + */ +#define IOT_LOG_INFO 3 + +/** + * @brief Detailed and excessive debug information. + * + * Log messages with this level are intended for developers. They may contain + * excessive information such as internal variables, buffers, or other specific + * information. + */ +#define IOT_LOG_DEBUG 4 + +/** + * @paramstructs_group{logging} + * @paramstructs_brief{logging,logging} + */ + +/** + * @ingroup logging_datatypes_paramstructs + * @brief Log message configuration struct. + * + * @paramfor @ref logging_function_log, @ref logging_function_generic + * + * By default, log messages print the library name, log level, and a timestring. + * This struct can be passed to @ref logging_function_generic to disable one of + * the above components in the log message. + * + * Example: + * + * @code{c} + * IotLog_Generic( IOT_LOG_DEBUG, "SAMPLE", IOT_LOG_DEBUG, NULL, "Hello world!" ); + * @endcode + * The code above prints the following message: + * @code + * [DEBUG][SAMPLE][2018-01-01 12:00:00] Hello world! + * @endcode + * + * The timestring can be disabled as follows: + * @code + * IotLogConfig_t logConfig = { .hideLogLevel = false, .hideLibraryName = false, .hideTimestring = true}; + * IotLog_Generic( IOT_LOG_DEBUG, "SAMPLE", IOT_LOG_DEBUG, &logConfig, "Hello world!" ); + * @endcode + * The resulting log message will be: + * @code + * [DEBUG][SAMPLE] Hello world! + * @endcode + */ +typedef struct IotLogConfig +{ + bool hideLogLevel; /**< @brief Don't print the log level string for this message. */ + bool hideLibraryName; /**< @brief Don't print the library name for this message. */ + bool hideTimestring; /**< @brief Don't print the timestring for this message. */ +} IotLogConfig_t; + +/** + * @functions_page{logging, Logging} + * @functions_brief{logging} + * + * - @function_name{logging_function_log} + * @function_brief{logging_function_log} + * - @function_name{logging_function_printbuffer} + * @function_brief{logging_function_printbuffer} + * - @function_name{logging_function_generic} + * @function_brief{logging_function_generic} + * - @function_name{logging_function_genericprintbuffer} + * @function_brief{logging_function_genericprintbuffer} + */ + +/** + * @function_page{IotLog_Generic,logging,generic} + * @function_snippet{logging,generic,this} + * @copydoc IotLog_Generic + * @function_page{IotLog_PrintBuffer,logging,genericprintbuffer} + * @function_snippet{logging,genericprintbuffer,this} + * @copydoc IotLog_PrintBuffer + */ + +/** + * @brief Generic logging function that prints a single message. + * + * This function is the generic logging function shared across all libraries. + * The library-specific logging function @ref logging_function_log is implemented + * using this function. Like @ref logging_function_log, this function is only + * available when @ref LIBRARY_LOG_LEVEL is #IOT_LOG_NONE. + * + * In most cases, the library-specific logging function @ref logging_function_log + * should be called instead of this function. + * + * @param[in] libraryLogSetting The log level setting of the library, used to + * determine if the log message should be printed. Must be one of the @ref + * logging_constants_levels. + * @param[in] pLibraryName The library name to print. See @ref LIBRARY_LOG_NAME. + * @param[in] messageLevel The log level of the this message. See @ref LIBRARY_LOG_LEVEL. + * @param[in] pLogConfig Pointer to a #IotLogConfig_t. Optional; pass `NULL` to ignore. + * @param[in] pFormat Format string for the log message. + * @param[in] ... Arguments for format specification. + * + * @return No return value. On errors, it prints nothing. + */ +/* @[declare_logging_generic] */ +void IotLog_Generic( int libraryLogSetting, + const char * const pLibraryName, + int messageLevel, + const IotLogConfig_t * const pLogConfig, + const char * const pFormat, + ... ); +/* @[declare_logging_generic] */ + +/** + * @brief Generic function to log the contents of a buffer as bytes. + * + * This function is the generic buffer logging function shared across all libraries. + * The library-specific buffer logging function @ref logging_function_printbuffer is + * implemented using this function. Like @ref logging_function_printbuffer, this + * function is only available when @ref LIBRARY_LOG_LEVEL is #IOT_LOG_DEBUG. + * + * In most cases, the library-specific buffer logging function @ref + * logging_function_printbuffer should be called instead of this function. + * + * @param[in] pLibraryName The library name to print with the log. See @ref LIBRARY_LOG_NAME. + * @param[in] pHeader A message to print before printing the buffer. + * @param[in] pBuffer The buffer to print. + * @param[in] bufferSize The number of bytes in `pBuffer` to print. + * + * @return No return value. On errors, it prints nothing. + * + * @note To conserve memory, this function only allocates enough memory for a + * single line of output. Therefore, in multithreaded systems, its output may + * appear "fragmented" if other threads are logging simultaneously. + */ +/* @[declare_logging_genericprintbuffer] */ +void IotLog_GenericPrintBuffer( const char * const pLibraryName, + const char * const pHeader, + const uint8_t * const pBuffer, + size_t bufferSize ); +/* @[declare_logging_genericprintbuffer] */ + +#endif /* ifndef IOT_LOGGING_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_static_memory.h b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_static_memory.h new file mode 100644 index 0000000..4abcafa --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_static_memory.h @@ -0,0 +1,272 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_static_memory.h + * @brief Common functions for managing static buffers. Only used when + * @ref IOT_STATIC_MEMORY_ONLY is `1`. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* The functions in this file should only exist in static memory only mode, hence + * the check for IOT_STATIC_MEMORY_ONLY in the double inclusion guard. */ +#if !defined( IOT_STATIC_MEMORY_H_ ) && ( IOT_STATIC_MEMORY_ONLY == 1 ) + #define IOT_STATIC_MEMORY_H_ + +/* Standard includes. */ + #include + #include + #include + +/** + * @functions_page{static_memory, Static Memory} + * @functions_brief{static memory component} + * - @function_name{static_memory_function_init} + * @function_brief{static_memory_function_init} + * - @function_name{static_memory_function_cleanup} + * @function_brief{static_memory_function_cleanup} + * - @function_name{static_memory_function_findfree} + * @function_brief{static_memory_function_findfree} + * - @function_name{static_memory_function_returninuse} + * @function_brief{static_memory_function_returninuse} + * - @function_name{static_memory_function_messagebuffersize} + * @function_brief{static_memory_function_messagebuffersize} + * - @function_name{static_memory_function_mallocmessagebuffer} + * @function_brief{static_memory_function_mallocmessagebuffer} + * - @function_name{static_memory_function_freemessagebuffer} + * @function_brief{static_memory_function_freemessagebuffer} + */ + +/*----------------------- Initialization and cleanup ------------------------*/ + +/** + * @function_page{IotStaticMemory_Init,static_memory,init} + * @function_snippet{static_memory,init,this} + * @copydoc IotStaticMemory_Init + * @function_page{IotStaticMemory_Cleanup,static_memory,cleanup} + * @function_snippet{static_memory,cleanup,this} + * @copydoc IotStaticMemory_Cleanup + */ + +/** + * @brief One-time initialization function for static memory. + * + * This function performs internal setup of static memory. It must be called + * once (and only once) before calling any other static memory function. + * Calling this function more than once without first calling + * @ref static_memory_function_cleanup may result in a crash. + * + * @return `true` if initialization succeeded; `false` otherwise. + * + * @attention This function is called by `IotSdk_Init` and does not need to be + * called by itself. + * + * @warning No thread-safety guarantees are provided for this function. + * + * @see static_memory_function_cleanup + */ +/* @[declare_static_memory_init] */ + bool IotStaticMemory_Init( void ); +/* @[declare_static_memory_init] */ + +/** + * @brief One-time deinitialization function for static memory. + * + * This function frees resources taken in @ref static_memory_function_init. + * It should be called after to clean up static memory. After this function + * returns, @ref static_memory_function_init must be called again before + * calling any other static memory function. + * + * @attention This function is called by `IotSdk_Cleanup` and does not need + * to be called by itself. + * + * @warning No thread-safety guarantees are provided for this function. + * + * @see static_memory_function_init + */ +/* @[declare_static_memory_cleanup] */ + void IotStaticMemory_Cleanup( void ); +/* @[declare_static_memory_cleanup] */ + +/*------------------------- Buffer allocation and free ----------------------*/ + +/** + * @function_page{IotStaticMemory_FindFree,static_memory,findfree} + * @function_snippet{static_memory,findfree,this} + * @copydoc IotStaticMemory_FindFree + * @function_page{IotStaticMemory_ReturnInUse,static_memory,returninuse} + * @function_snippet{static_memory,returninuse,this} + * @copydoc IotStaticMemory_ReturnInUse + */ + +/** + * @brief Find a free buffer using the "in-use" flags. + * + * If a free buffer is found, this function marks the buffer in-use. This function + * is common to the static memory implementation. + * + * @param[in] pInUse The "in-use" flags to search. + * @param[in] limit How many flags to check, i.e. the size of `pInUse`. + * + * @return The index of a free buffer; `-1` if no free buffers are available. + * + * Example: + * @code{c} + * // To use this function, first declare two arrays. One provides the statically-allocated + * // objects, the other provides flags to determine which objects are in-use. + * #define NUMBER_OF_OBJECTS ... + * #define OBJECT_SIZE ... + * static bool _pInUseObjects[ NUMBER_OF_OBJECTS ] = { 0 }; + * static uint8_t _pObjects[ NUMBER_OF_OBJECTS ][ OBJECT_SIZE ] = { { 0 } }; // Placeholder for objects. + * + * // The function to statically allocate objects. Must have the same signature + * // as malloc(). + * void * Iot_MallocObject( size_t size ) + * { + * int32_t freeIndex = -1; + * void * pNewObject = NULL; + * + * // Check that sizes match. + * if( size != OBJECT_SIZE ) + * { + * // Get the index of a free object. + * freeIndex = IotStaticMemory_FindFree( _pInUseMessageBuffers, + * IOT_MESSAGE_BUFFERS ); + * + * if( freeIndex != -1 ) + * { + * pNewBuffer = &( _pMessageBuffers[ freeIndex ][ 0 ] ); + * } + * } + * + * return pNewBuffer; + * } + * @endcode + */ +/* @[declare_static_memory_findfree] */ + int32_t IotStaticMemory_FindFree( bool * pInUse, + size_t limit ); +/* @[declare_static_memory_findfree] */ + +/** + * @brief Return an "in-use" buffer. + * + * This function is common to the static memory implementation. + * + * @param[in] ptr Pointer to the buffer to return. + * @param[in] pPool The pool of buffers that the in-use buffer was allocated from. + * @param[in] pInUse The "in-use" flags for pPool. + * @param[in] limit How many buffers (and flags) to check while searching for ptr. + * @param[in] elementSize The size of a single element in pPool. + * + * Example: + * @code{c} + * // To use this function, first declare two arrays. One provides the statically-allocated + * // objects, the other provides flags to determine which objects are in-use. + * #define NUMBER_OF_OBJECTS ... + * #define OBJECT_SIZE ... + * static bool _pInUseObjects[ NUMBER_OF_OBJECTS ] = { 0 }; + * static uint8_t _pObjects[ NUMBER_OF_OBJECTS ][ OBJECT_SIZE ] = { { 0 } }; // Placeholder for objects. + * + * // The function to free statically-allocated objects. Must have the same signature + * // as free(). + * void Iot_FreeObject( void * ptr ) + * { + * IotStaticMemory_ReturnInUse( ptr, + * _pObjects, + * _pInUseObjects, + * NUMBER_OF_OBJECTS, + * OBJECT_SIZE ); + * } + * @endcode + */ +/* @[declare_static_memory_returninuse] */ + void IotStaticMemory_ReturnInUse( void * ptr, + void * pPool, + bool * pInUse, + size_t limit, + size_t elementSize ); +/* @[declare_static_memory_returninuse] */ + +/*------------------------ Message buffer management ------------------------*/ + +/** + * @function_page{Iot_MessageBufferSize,static_memory,messagebuffersize} + * @function_snippet{static_memory,messagebuffersize,this} + * @copydoc Iot_MessageBufferSize + * @function_page{Iot_MallocMessageBuffer,static_memory,mallocmessagebuffer} + * @function_snippet{static_memory,mallocmessagebuffer,this} + * @copydoc Iot_MallocMessageBuffer + * @function_page{Iot_FreeMessageBuffer,static_memory,freemessagebuffer} + * @function_snippet{static_memory,freemessagebuffer,this} + * @copydoc Iot_FreeMessageBuffer + */ + +/** + * @brief Get the fixed size of a message buffer. + * + * The size of the message buffers are known at compile time, but it is a [constant] + * (@ref IOT_MESSAGE_BUFFER_SIZE) that may not be visible to all source files. + * This function allows other source files to know the size of a message buffer. + * + * @return The size, in bytes, of a single message buffer. + */ +/* @[declare_static_memory_messagebuffersize] */ + size_t Iot_MessageBufferSize( void ); +/* @[declare_static_memory_messagebuffersize] */ + +/** + * @brief Get an empty message buffer. + * + * This function is the analog of [malloc] + * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html) + * for message buffers. + * + * @param[in] size Requested size for a message buffer. + * + * @return Pointer to the start of a message buffer. If the `size` argument is larger + * than the [fixed size of a message buffer](@ref IOT_MESSAGE_BUFFER_SIZE) + * or no message buffers are available, `NULL` is returned. + */ +/* @[declare_static_memory_mallocmessagebuffer] */ + void * Iot_MallocMessageBuffer( size_t size ); +/* @[declare_static_memory_mallocmessagebuffer] */ + +/** + * @brief Free an in-use message buffer. + * + * This function is the analog of [free] + * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html) + * for message buffers. + * + * @param[in] ptr Pointer to the message buffer to free. + */ +/* @[declare_static_memory_freemessagebuffer] */ + void Iot_FreeMessageBuffer( void * ptr ); +/* @[declare_static_memory_freemessagebuffer] */ + +#endif /* if !defined( IOT_STATIC_MEMORY_H_ ) && ( IOT_STATIC_MEMORY_ONLY == 1 ) */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_taskpool_internal.h b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_taskpool_internal.h new file mode 100644 index 0000000..9298896 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/private/iot_taskpool_internal.h @@ -0,0 +1,290 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_taskpool_internal.h + * @brief Internal header of task pool library. This header should not be included in + * typical application code. + */ + +#ifndef IOT_TASKPOOL_INTERNAL_H_ +#define IOT_TASKPOOL_INTERNAL_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Task pool include. */ +#include "private/iot_error.h" +#include "iot_taskpool.h" + +/* Establish a few convenience macros to handle errors in a standard way. */ + +/** + * @brief Every public API return an enumeration value with an undelying value of 0 in case of success. + */ +#define TASKPOOL_SUCCEEDED( x ) ( ( x ) == IOT_TASKPOOL_SUCCESS ) + +/** + * @brief Every public API returns an enumeration value with an undelying value different than 0 in case of success. + */ +#define TASKPOOL_FAILED( x ) ( ( x ) != IOT_TASKPOOL_SUCCESS ) + +/** + * @brief Jump to the cleanup area. + */ +#define TASKPOOL_GOTO_CLEANUP() IOT_GOTO_CLEANUP() + +/** + * @brief Declare the storage for the error status variable. + */ +#define TASKPOOL_FUNCTION_ENTRY( result ) IOT_FUNCTION_ENTRY( IotTaskPoolError_t, result ) + +/** + * @brief Check error and leave in case of failure. + */ +#define TASKPOOL_ON_ERROR_GOTO_CLEANUP( expr ) \ + { if( TASKPOOL_FAILED( status = ( expr ) ) ) { IOT_GOTO_CLEANUP(); } \ + } + +/** + * @brief Exit if an argument is NULL. + */ +#define TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ptr ) IOT_VALIDATE_PARAMETER( IOT_TASKPOOL, ( ptr != NULL ) ) + +/** + * @brief Exit if an argument is NULL. + */ +#define TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( expr ) IOT_VALIDATE_PARAMETER( IOT_TASKPOOL, ( ( expr ) == false ) ) + +/** + * @brief Set error and leave. + */ +#define TASKPOOL_SET_AND_GOTO_CLEANUP( expr ) IOT_SET_AND_GOTO_CLEANUP( expr ) + +/** + * @brief Initialize error and declare start of cleanup area. + */ +#define TASKPOOL_FUNCTION_CLEANUP() IOT_FUNCTION_CLEANUP_BEGIN() + +/** + * @brief Initialize error and declare end of cleanup area. + */ +#define TASKPOOL_FUNCTION_CLEANUP_END() IOT_FUNCTION_CLEANUP_END() + +/** + * @brief Create an empty cleanup area. + */ +#define TASKPOOL_NO_FUNCTION_CLEANUP() IOT_FUNCTION_EXIT_NO_CLEANUP() + +/** + * @brief Does not create a cleanup area. + */ +#define TASKPOOL_NO_FUNCTION_CLEANUP_NOLABEL() return status + +/** + * @def IotTaskPool_Assert( expression ) + * @brief Assertion macro for the Task pool library. + * + * Set @ref IOT_TASKPOOL_ENABLE_ASSERTS to `1` to enable assertions in the Task pool + * library. + * + * @param[in] expression Expression to be evaluated. + */ +#if IOT_TASKPOOL_ENABLE_ASSERTS == 1 + #ifndef IotTaskPool_Assert + #include + #define IotTaskPool_Assert( expression ) assert( expression ) + #endif +#else + #define IotTaskPool_Assert( expression ) +#endif + +/* Configure logs for TASKPOOL functions. */ +#ifdef IOT_LOG_LEVEL_TASKPOOL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_TASKPOOL +#else + #ifdef IOT_LOG_LEVEL_GLOBAL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL + #else + #define LIBRARY_LOG_LEVEL IOT_LOG_NONE + #endif +#endif + +#define LIBRARY_LOG_NAME ( "TASKPOOL" ) +#include "iot_logging_setup.h" + +/* + * Provide default values for undefined memory allocation functions based on + * the usage of dynamic memory allocation. + */ +#if IOT_STATIC_MEMORY_ONLY == 1 + #include "private/iot_static_memory.h" + +/** + * @brief Allocate an #_taskPool_t. This function should have the + * same signature as [malloc]. + */ + void * IotTaskPool_MallocTaskPool( size_t size ); + +/** + * @brief Free an #_taskPool_t. This function should have the + * same signature as [malloc]. + */ + void IotTaskPool_FreeTaskPool( void * ptr ); + +/** + * @brief Allocate an #IotTaskPoolJob_t. This function should have the + * same signature as [malloc]. + */ + void * IotTaskPool_MallocJob( size_t size ); + +/** + * @brief Free an #IotTaskPoolJob_t. This function should have the same + * same signature as [malloc]. + * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html). + */ + void IotTaskPool_FreeJob( void * ptr ); + +/** + * @brief Allocate an #_taskPoolTimerEvent_t. This function should have the + * same signature as [malloc]. + */ + void * IotTaskPool_MallocTimerEvent( size_t size ); + +/** + * @brief Free an #_taskPoolTimerEvent_t. This function should have the + * same signature as[ free ]. + */ + void IotTaskPool_FreeTimerEvent( void * ptr ); + +#else /* if IOT_STATIC_MEMORY_ONLY == 1 */ + #include + + #ifndef IotTaskPool_MallocTaskPool + #define IotTaskPool_MallocTaskPool malloc + #endif + + #ifndef IotTaskPool_FreeTaskPool + #define IotTaskPool_FreeTaskPool free + #endif + + #ifndef IotTaskPool_MallocJob + #define IotTaskPool_MallocJob malloc + #endif + + #ifndef IotTaskPool_FreeJob + #define IotTaskPool_FreeJob free + #endif + + #ifndef IotTaskPool_MallocTimerEvent + #define IotTaskPool_MallocTimerEvent malloc + #endif + + #ifndef IotTaskPool_FreeTimerEvent + #define IotTaskPool_FreeTimerEvent free + #endif + +#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */ + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * @cond DOXYGEN_IGNORE + * Doxygen should ignore this section. + * + * A macros to manage task pool memory allocation. + */ +#define IOT_TASK_POOL_INTERNAL_STATIC ( ( uint32_t ) 0x00000001 ) /* Flag to mark a job as user-allocated. */ +/** @endcond */ + +/** + * @brief Task pool jobs cache. + * + * @warning This is a system-level data type that should not be modified or used directly in any application. + * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility. + * + */ +typedef struct _taskPoolCache +{ + IotListDouble_t freeList; /**< @brief A list ot hold cached jobs. */ + + uint32_t freeCount; /**< @brief A counter to track the number of jobs in the cache. */ +} _taskPoolCache_t; + +/** + * @brief The task pool data structure keeps track of the internal state and the signals for the dispatcher threads. + * The task pool is a thread safe data structure. + * + * @warning This is a system-level data type that should not be modified or used directly in any application. + * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility. + * + */ +typedef struct _taskPool +{ + IotDeQueue_t dispatchQueue; /**< @brief The queue for the jobs waiting to be executed. */ + IotListDouble_t timerEventsList; /**< @brief The timeouts queue for all deferred jobs waiting to be executed. */ + _taskPoolCache_t jobsCache; /**< @brief A cache to re-use jobs in order to limit memory allocations. */ + uint32_t minThreads; /**< @brief The minimum number of threads for the task pool. */ + uint32_t maxThreads; /**< @brief The maximum number of threads for the task pool. */ + uint32_t activeThreads; /**< @brief The number of threads in the task pool at any given time. */ + uint32_t activeJobs; /**< @brief The number of active jobs in the task pool at any given time. */ + uint32_t stackSize; /**< @brief The stack size for all task pool threads. */ + int32_t priority; /**< @brief The priority for all task pool threads. */ + IotSemaphore_t dispatchSignal; /**< @brief The synchronization object on which threads are waiting for incoming jobs. */ + IotSemaphore_t startStopSignal; /**< @brief The synchronization object for threads to signal start and stop condition. */ + IotTimer_t timer; /**< @brief The timer for deferred jobs. */ + IotMutex_t lock; /**< @brief The lock to protect the task pool data structure access. */ +} _taskPool_t; + +/** + * @brief The job data structure keeps track of the user callback and context, as well as the status of the job. + * + * @warning This is a system-level data type that should not be modified or used directly in any application. + * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility. + * + */ +typedef struct _taskPoolJob +{ + IotLink_t link; /**< @brief The link to insert the job in the dispatch queue. */ + IotTaskPoolRoutine_t userCallback; /**< @brief The user provided callback. */ + void * pUserContext; /**< @brief The user provided context. */ + uint32_t flags; /**< @brief Internal flags. */ + IotTaskPoolJobStatus_t status; /**< @brief The status for the job. */ +} _taskPoolJob_t; + +/** + * @brief Represents an operation that is subject to a timer. + * + * These events are queued per MQTT connection. They are sorted by their + * expiration time. + */ +typedef struct _taskPoolTimerEvent +{ + IotLink_t link; /**< @brief List link member. */ + uint64_t expirationTime; /**< @brief When this event should be processed. */ + _taskPoolJob_t * pJob; /**< @brief The task pool job associated with this event. */ +} _taskPoolTimerEvent_t; + +#endif /* ifndef IOT_TASKPOOL_INTERNAL_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/include/types/iot_taskpool_types.h b/bsp/aws_libraries/c_sdk/standard/common/include/types/iot_taskpool_types.h new file mode 100644 index 0000000..9b4b7e0 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/include/types/iot_taskpool_types.h @@ -0,0 +1,364 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_taskpool_types.h + * @brief Types of the task pool. + */ + +#ifndef IOT_TASKPOOL_TYPES_H_ +#define IOT_TASKPOOL_TYPES_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include + +/* Platform types includes. */ +#include "types/iot_platform_types.h" + +/* Linear containers (lists and queues) include. */ +#include "iot_linear_containers.h" + +/*-------------------------- Task pool enumerated types --------------------------*/ + +/** + * @ingroup taskpool_datatypes_enums + * @brief Return codes of [task pool functions](@ref taskpool_functions). + */ +typedef enum IotTaskPoolError +{ + /** + * @brief Task pool operation completed successfully. + * + * Functions that may return this value: + * - @ref taskpool_function_createsystemtaskpool + * - @ref taskpool_function_create + * - @ref taskpool_function_destroy + * - @ref taskpool_function_setmaxthreads + * - @ref taskpool_function_createjob + * - @ref taskpool_function_createrecyclablejob + * - @ref taskpool_function_destroyrecyclablejob + * - @ref taskpool_function_recyclejob + * - @ref taskpool_function_schedule + * - @ref taskpool_function_scheduledeferred + * - @ref taskpool_function_getstatus + * - @ref taskpool_function_trycancel + * + */ + IOT_TASKPOOL_SUCCESS = 0, + + /** + * @brief Task pool operation failed because at least one parameter is invalid. + * + * Functions that may return this value: + * - @ref taskpool_function_createsystemtaskpool + * - @ref taskpool_function_create + * - @ref taskpool_function_destroy + * - @ref taskpool_function_setmaxthreads + * - @ref taskpool_function_createjob + * - @ref taskpool_function_createrecyclablejob + * - @ref taskpool_function_destroyrecyclablejob + * - @ref taskpool_function_recyclejob + * - @ref taskpool_function_schedule + * - @ref taskpool_function_scheduledeferred + * - @ref taskpool_function_getstatus + * - @ref taskpool_function_trycancel + * + */ + IOT_TASKPOOL_BAD_PARAMETER, + + /** + * @brief Task pool operation failed because it is illegal. + * + * Functions that may return this value: + * - @ref taskpool_function_createjob + * - @ref taskpool_function_createrecyclablejob + * - @ref taskpool_function_destroyrecyclablejob + * - @ref taskpool_function_recyclejob + * - @ref taskpool_function_schedule + * - @ref taskpool_function_scheduledeferred + * - @ref taskpool_function_trycancel + * + */ + IOT_TASKPOOL_ILLEGAL_OPERATION, + + /** + * @brief Task pool operation failed because allocating memory failed. + * + * Functions that may return this value: + * - @ref taskpool_function_createsystemtaskpool + * - @ref taskpool_function_create + * - @ref taskpool_function_setmaxthreads + * - @ref taskpool_function_createrecyclablejob + * - @ref taskpool_function_scheduledeferred + * - @ref taskpool_function_getstatus + * + */ + IOT_TASKPOOL_NO_MEMORY, + + /** + * @brief Task pool operation failed because of an invalid parameter. + * + * Functions that may return this value: + * - @ref taskpool_function_setmaxthreads + * - @ref taskpool_function_createrecyclablejob + * - @ref taskpool_function_destroyrecyclablejob + * - @ref taskpool_function_recyclejob + * - @ref taskpool_function_schedule + * - @ref taskpool_function_scheduledeferred + * - @ref taskpool_function_getstatus + * - @ref taskpool_function_trycancel + * + */ + IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS, + + /** + * @brief Task pool cancellation failed. + * + * Functions that may return this value: + * - @ref taskpool_function_trycancel + * + */ + IOT_TASKPOOL_CANCEL_FAILED, +} IotTaskPoolError_t; + +/** + * @enums_group{taskpool} + * @enums_brief{Task pool library} + */ + +/** + * @ingroup taskpool_datatypes_enums + * @brief Status codes of [task pool Job](@ref IotTaskPoolJob_t). + * + */ +typedef enum IotTaskPoolJobStatus +{ + /** + * @brief Job is ready to be scheduled. + * + */ + IOT_TASKPOOL_STATUS_READY = 0, + + /** + * @brief Job has been queued for execution. + * + */ + IOT_TASKPOOL_STATUS_SCHEDULED, + + /** + * @brief Job has been scheduled for deferred execution. + * + */ + IOT_TASKPOOL_STATUS_DEFERRED, + + /** + * @brief Job is executing. + * + */ + IOT_TASKPOOL_STATUS_COMPLETED, + + /** + * @brief Job has been canceled before executing. + * + */ + IOT_TASKPOOL_STATUS_CANCELED, + + /** + * @brief Job status is undefined. + * + */ + IOT_TASKPOOL_STATUS_UNDEFINED, +} IotTaskPoolJobStatus_t; + +/*------------------------- Task pool types and handles --------------------------*/ + +/** + * @ingroup taskpool_datatypes_handles + * @brief Opaque handle of a Task Pool instance. + * + * This type identifies a Task Pool instance, which is valid after a successful call + * to @ref taskpool_function_createsystemtaskpool or @ref taskpool_function_create. A + * variable of this type is passed as the first + * argument to [Task Pool library functions](@ref taskpool_functions) to identify which + * task pool that function acts on. + * + * A call to @ref taskpool_function_destroy makes a task pool handle invalid. Once + * @ref taskpool_function_destroy returns, the task handle should no longer + * be used. + * + * @initializer{IotTaskPool_t,IOT_TASKPOOL_INITIALIZER} + */ +typedef struct _taskPool * IotTaskPool_t; + +/** + * @ingroup taskpool_datatypes_structs + * @brief The job storage data structure provides the storage for a statically allocated Task Pool Job instance. + * + * @warning This is a system-level data type that should not be modified or used directly in any application. + * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility. + * + */ +typedef struct IotTaskPoolJobStorage +{ + IotLink_t link; /**< @brief Placeholder. */ + void * dummy2; /**< @brief Placeholder. */ + void * dummy3; /**< @brief Placeholder. */ + uint32_t dummy4; /**< @brief Placeholder. */ + IotTaskPoolJobStatus_t status; /**< @brief Placeholder. */ +} IotTaskPoolJobStorage_t; + +/** + * @ingroup taskpool_datatypes_handles + * @brief Opaque handle of a Task Pool Job. + * + * This type identifies a Task Pool Job instance, which is valid after a successful call + * to @ref taskpool_function_createjob or @ref taskpool_function_createrecyclablejob. + * + * A call to @ref taskpool_function_recyclejob or @ref taskpool_function_destroyrecyclablejob makes a + * task pool job handle invalid. Once @ref taskpool_function_recyclejob or + * @ref taskpool_function_destroyrecyclablejob returns, the task job handle should no longer be used. + * + * @initializer{IotTaskPoolJob_t,IOT_TASKPOOL_JOB_INITIALIZER} + * + */ +typedef struct _taskPoolJob * IotTaskPoolJob_t; + +/*------------------------- Task pool parameter structs --------------------------*/ + +/** + * @ingroup taskpool_datatypes_functionpointers + * @brief Callback type for a user callback. + * + * This type identifies the user callback signature to execute a task pool job. This callback will be invoked + * by the task pool threads with the `pUserContext` parameter, as specified by the user when + * calling @ref IotTaskPool_Schedule. + * + */ +typedef void ( * IotTaskPoolRoutine_t )( IotTaskPool_t pTaskPool, + IotTaskPoolJob_t pJob, + void * pUserContext ); + +/** + * @ingroup taskpool_datatypes_paramstructs + * @brief Initialization information to create one task pool instance. + * + * @paramfor @ref taskpool_function_createsystemtaskpool @ref taskpool_function_create. + * + * Passed as an argument to @ref taskpool_function_create. + * + * @initializer{IotTaskPoolInfo_t,IOT_TASKPOOL_INFO_INITIALIZER} + */ +typedef struct IotTaskPoolInfo +{ + /** + * @brief Specifies the operating parameters for a task pool. + * + * @attention #IotTaskPoolInfo_t.minThreads MUST be at least 1. + * #IotTaskPoolInfo_t.maxThreads MUST be greater or equal to #IotTaskPoolInfo_t.minThreads. + * If the minimum number of threads is same as the maximum, then the task pool will not try and grow the + * number of worker threads at run time. + */ + + uint32_t minThreads; /**< @brief Minimum number of threads in a task pool. These threads will be created when the task pool is first created with @ref taskpool_function_create. */ + uint32_t maxThreads; /**< @brief Maximum number of threads in a task pool. A task pool may try and grow the number of active threads up to #IotTaskPoolInfo_t.maxThreads. */ + uint32_t stackSize; /**< @brief Stack size for every task pool thread. The stack size for each thread is fixed after the task pool is created and cannot be changed. */ + int32_t priority; /**< @brief priority for every task pool thread. The priority for each thread is fixed after the task pool is created and cannot be changed. */ +} IotTaskPoolInfo_t; + +/*------------------------- TASKPOOL defined constants --------------------------*/ + +/** + * @constants_page{taskpool} + * @constants_brief{task pool library} + * + * @section taskpool_constants_initializers Task pool Initializers + * @brief Provides default values for initializing the data types of the task pool library. + * + * @snippet this define_taskpool_initializers + * + * All user-facing data types of the task pool library can be initialized using + * one of the following. + * + * @warning Failure to initialize a task pool data type with the appropriate initializer + * may result in a runtime error! + * @note The initializers may change at any time in future versions, but their + * names will remain the same. + * + * Example + * @code{c} + * + * IotTaskPool_t * pTaskPool; + * + * const IotTaskPoolInfo_t tpInfo = IOT_TASKPOOL_INFO_INITIALIZER_LARGE; + * + * IotTaskPoolError_t error = IotTaskPool_Create( &tpInfo, &pTaskPool ); + * + * // Use the task pool + * // ... + * + * @endcode + * + */ +/* @[define_taskpool_initializers] */ +/** @brief Initializer for a small #IotTaskPoolInfo_t. */ +#define IOT_TASKPOOL_INFO_INITIALIZER_SMALL { .minThreads = 1, .maxThreads = 1, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } +/** @brief Initializer for a medium #IotTaskPoolInfo_t. */ +#define IOT_TASKPOOL_INFO_INITIALIZER_MEDIUM { .minThreads = 1, .maxThreads = 2, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } +/** @brief Initializer for a large #IotTaskPoolInfo_t. */ +#define IOT_TASKPOOL_INFO_INITIALIZER_LARGE { .minThreads = 2, .maxThreads = 3, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } +/** @brief Initializer for a very large #IotTaskPoolInfo_t. */ +#define IOT_TASKPOOL_INFO_INITIALIZER_XLARGE { .minThreads = 2, .maxThreads = 4, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } +/** @brief Initializer for a typical #IotTaskPoolInfo_t. */ +#define IOT_TASKPOOL_INFO_INITIALIZER IOT_TASKPOOL_INFO_INITIALIZER_MEDIUM +/** @brief Initializer for a #IotTaskPool_t. */ +#define IOT_TASKPOOL_INITIALIZER NULL +/** @brief Initializer for a #IotTaskPoolJobStorage_t. */ +#define IOT_TASKPOOL_JOB_STORAGE_INITIALIZER { { NULL, NULL }, NULL, NULL, 0, IOT_TASKPOOL_STATUS_UNDEFINED } +/** @brief Initializer for a #IotTaskPoolJob_t. */ +#define IOT_TASKPOOL_JOB_INITIALIZER NULL +/* @[define_taskpool_initializers] */ + +/** + * @brief Flag for scheduling a job to execute immediately, even if the maximum number of threads in the + * task pool was reached already. + * + * @warning This flag may cause the task pool to create a worker to serve the job immediately, and + * therefore using this flag may incur in additional memory usage and potentially fail scheduling the job. + */ +#define IOT_TASKPOOL_JOB_HIGH_PRIORITY ( ( uint32_t ) 0x00000001 ) + +/** + * @brief Allows the use of the handle to the system task pool. + * + * @warning The task pool handle is not valid unless @ref IotTaskPool_CreateSystemTaskPool is + * called before the handle is used. + */ +#define IOT_SYSTEM_TASKPOOL ( IotTaskPool_GetSystemTaskPool() ) + +#endif /* ifndef IOT_TASKPOOL_TYPES_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/iot_device_metrics.c b/bsp/aws_libraries/c_sdk/standard/common/iot_device_metrics.c new file mode 100644 index 0000000..dd903ca --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/iot_device_metrics.c @@ -0,0 +1,433 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt_metrics.c + * @brief Source code for generating device metrics for AWS IOT. + * The generated metrics will be included within the username field of MQTT CONNECT message. + */ +#include +#include +#include +#include +#include + +#include "iot_config.h" + +#include "platform/iot_clock.h" +#include "iot_atomic.h" + +/* + * @brief Total length of the hash in bytes. + */ +#define MD5_HASH_LENGTH_BYTES ( 16 ) + +/* + * Encode Length of one byte for the identifier. + */ +#define IDENTIFIER_BYTE_ENCODE_LENGTH ( 2 ) + +/* + * @brief Length in bytes of each chunk used for MD5 hash computation. + */ +#define MD5_CHUNK_LENGTH ( 64 ) + +/* + * @brief Number of bytes used for padding message length to input bytes. + */ +#define MD5_MSGLEN_PADDING_LENGTH ( 8 ) + +/* + * @brief The first byte of the bit padding ( Most significant bit should be 1 ). + */ +#define MD5_BIT_PADDING_FIRST_BYTE ( 0x80 ) + +/* + * @brief Total length of the input after padding. + */ +#define MD5_PADDED_LENGTH( length ) ( ( length + MD5_MSGLEN_PADDING_LENGTH + MD5_CHUNK_LENGTH ) & ~( MD5_CHUNK_LENGTH - 1 ) ) + +/* + * @brief Length of device identifier. + * Device identifier is represented as hex string of MD5 hash of the device certificate. + */ +#define AWS_IOT_DEVICE_IDENTIFIER_LENGTH ( MD5_HASH_LENGTH_BYTES * 2 ) + +/** + * @brief Device metrics name format + */ +#define AWS_IOT_METRICS_FORMAT "?SDK=" IOT_SDK_NAME "&Version=" IOT_SDK_VERSION "&Platform=" IOT_PLATFORM_NAME "&AFRDevID=%.*s" + +/** + * @brief Length of #AWS_IOT_METRICS_FORMAT. + */ +#define AWS_IOT_METRICS_FORMAT_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_METRICS_FORMAT ) + AWS_IOT_DEVICE_IDENTIFIER_LENGTH ) ) + +/* + * @brief Macro for left rotatation at each round of MD5 hash operation. + */ +#define LEFT_ROTATE( x, c ) ( ( x << c ) | ( x >> ( 32 - c ) ) ) + + +/* + * @brief Generates 128-bit MD5 hash from the input data. + * The hash algorithm is adapted from wikipedia and does not dependent on any third party libraries. + * + * @param[in] pData Data on which hash needs to be calculated. + * @param[in] dataLength Length in bytes of the input data + * @param[in] pHash Memory location where the hash value is stored. + * @param[out] hashLength Total size of the memory location for hash storage. + */ +void Utils_generateMD5Hash( const char * pData, + size_t dataLength, + uint8_t * pHash, + size_t hashLength ); + +/* + * @brief Generates a unique identifier string from the input data. + * Uses MD5 hash algorithm to generate a 128-bit unique identifier and + * encodes as a hexadecimal string. + */ + +static void _generateUniqueIdentifier( const char * pInput, + size_t length, + char * pIdentifier, + size_t identifierLength ); + +/* + * @brief generates device metrics from the device identifier + */ +static void _generateDeviceMetrics( const char * pDeviceIdentifier, + size_t deviceIdentifierLength, + char * pDeviceMetrics, + size_t deviceMetricsLength ); + +/* + * @brief Spinlock lock implementation using atomic compare and swap. + */ +static void _atomicSpinlock_lock( uint32_t * lock ); + +/* + * @brief Spinlock unlock implementation using atomic compare and swap. + */ +static void _atomicSpinlock_unlock( uint32_t * lock ); + +/** + * @brief Metrics for the device. + */ +static char deviceMetrics[ AWS_IOT_METRICS_FORMAT_LENGTH + 1 ] = { 0 }; + +/** + * @brief Unique identifier for the device. + */ +static char deviceIdentifier[ AWS_IOT_DEVICE_IDENTIFIER_LENGTH + 1 ] = { 0 }; + +/* + * @brief Constants used for left rotation. + */ +static const unsigned char S[ 64 ] = +{ + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 +}; + +/* + * @brief Constants representing the binary integer part of the sines of integers from 0 to 63. + */ +static const uint32_t K[ 64 ] = +{ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + + +void Utils_generateMD5Hash( const char * pData, + size_t dataLength, + uint8_t * pHash, + size_t hashLength ) +{ + uint8_t chunk[ MD5_CHUNK_LENGTH ] = { 0 }; + uint32_t * pOutput = ( uint32_t * ) pHash; + const uint32_t * pCurrent = NULL; + size_t paddingOffset, bytesConsumed = 0; + size_t paddingLength, totalLength = MD5_PADDED_LENGTH( dataLength ); + uint64_t numBits = ( dataLength * 8 ); + bool isPadding = false; + int i; + + uint32_t A, B, C, D, F, G; + + /*Initialize variables */ + pOutput[ 0 ] = 0x67452301; + pOutput[ 1 ] = 0xefcdab89; + pOutput[ 2 ] = 0x98badcfe; + pOutput[ 3 ] = 0x10325476; + + configASSERT( hashLength >= MD5_HASH_LENGTH_BYTES ); + + while( bytesConsumed < totalLength ) + { + if( ( bytesConsumed + MD5_CHUNK_LENGTH ) <= dataLength ) + { + pCurrent = ( uint32_t * ) pData; + pData += MD5_CHUNK_LENGTH; + bytesConsumed += MD5_CHUNK_LENGTH; + } + else + { + if( bytesConsumed < dataLength ) + { + memcpy( chunk, pData, ( dataLength - bytesConsumed ) ); + paddingOffset = ( dataLength - bytesConsumed ); + } + else + { + paddingOffset = 0; + } + + paddingLength = ( MD5_CHUNK_LENGTH - paddingOffset ); + + if( ( paddingLength >= 1 ) && ( isPadding == false ) ) + { + chunk[ paddingOffset++ ] = MD5_BIT_PADDING_FIRST_BYTE; + paddingLength--; + isPadding = true; + } + + if( paddingLength > MD5_MSGLEN_PADDING_LENGTH ) + { + memset( &chunk[ paddingOffset ], 0x00, ( paddingLength - MD5_MSGLEN_PADDING_LENGTH ) ); + paddingOffset += ( paddingLength - MD5_MSGLEN_PADDING_LENGTH ); + paddingLength = MD5_MSGLEN_PADDING_LENGTH; + } + + if( paddingLength == MD5_MSGLEN_PADDING_LENGTH ) + { + chunk[ paddingOffset++ ] = ( numBits & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 8 ) & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 16 ) & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 24 ) & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 32 ) & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 40 ) & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 48 ) & 0xFF ); + chunk[ paddingOffset++ ] = ( ( numBits >> 56 ) & 0xFF ); + } + + pCurrent = ( uint32_t * ) chunk; + bytesConsumed += MD5_CHUNK_LENGTH; + } + + A = pOutput[ 0 ]; + B = pOutput[ 1 ]; + C = pOutput[ 2 ]; + D = pOutput[ 3 ]; + + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + { + F = ( B & C ) | ( ( ~B ) & D ); + G = i; + } + else if( i < 32 ) + { + F = ( D & B ) | ( ( ~D ) & C ); + G = ( ( 5 * i ) + 1 ) % 16; + } + else if( i < 48 ) + { + F = ( B ^ C ) ^ D; + G = ( ( 3 * i ) + 5 ) % 16; + } + else + { + F = C ^ ( B | ( ~D ) ); + G = ( 7 * i ) % 16; + } + + F = F + A + K[ i ] + pCurrent[ G ]; + A = D; + D = C; + C = B; + B = B + LEFT_ROTATE( F, S[ i ] ); + } + + pOutput[ 0 ] += A; + pOutput[ 1 ] += B; + pOutput[ 2 ] += C; + pOutput[ 3 ] += D; + } +} + +static void _generateDeviceMetrics( const char * pDeviceIdentifier, + size_t deviceIdentifierLength, + char * pDeviceMetrics, + size_t deviceMetricsLength ) +{ + size_t length; + + length = snprintf( pDeviceMetrics, + deviceMetricsLength, + AWS_IOT_METRICS_FORMAT, + deviceIdentifierLength, + pDeviceIdentifier ); + + configASSERT( length > 0 ); +} + +static void _atomicSpinlock_lock( uint32_t * lock ) +{ + uint32_t current = 0; + uint32_t store = 1; + + for( ; ; ) + { + if( Atomic_CompareAndSwap_u32( lock, store, current ) == 1 ) + { + break; + } + + /* Does context switch with negligible delay. */ + IotClock_SleepMs( 1 ); + } +} + +static void _atomicSpinlock_unlock( uint32_t * lock ) +{ + uint32_t current = 1; + uint32_t store = 0; + + for( ; ; ) + { + if( Atomic_CompareAndSwap_u32( lock, store, current ) == 1 ) + { + break; + } + + /* Does context switch with negligible delay. */ + IotClock_SleepMs( 1 ); + } +} + +static void _generateUniqueIdentifier( const char * pInput, + size_t length, + char * pIdentifier, + size_t identifierLength ) +{ + uint8_t hash[ MD5_HASH_LENGTH_BYTES ] = { 0 }; + int i; + size_t ret; + + configASSERT( identifierLength >= ( 2 * MD5_HASH_LENGTH_BYTES ) ); + Utils_generateMD5Hash( pInput, length, hash, MD5_HASH_LENGTH_BYTES ); + + for( i = 0; i < MD5_HASH_LENGTH_BYTES; i++ ) + { + ret = snprintf( pIdentifier, ( IDENTIFIER_BYTE_ENCODE_LENGTH + 1 ), "%02X", hash[ i ] ); + configASSERT( ret > 0 ); + pIdentifier += IDENTIFIER_BYTE_ENCODE_LENGTH; + } +} + +/* + * @brief Retrieves the device identifier. + */ +const char * getDeviceIdentifier( void ) +{ + const char * pCertificate = IOT_DEVICE_CERTIFICATE; + static uint32_t lock = 0; + + if( deviceIdentifier[ 0 ] == '\0' ) + { + _atomicSpinlock_lock( &lock ); + + if( deviceIdentifier[ 0 ] == '\0' ) + { + if( ( pCertificate != NULL ) && + ( strcmp( pCertificate, "" ) != 0 ) ) + { + _generateUniqueIdentifier( pCertificate, strlen( pCertificate ), deviceIdentifier, sizeof( deviceIdentifier ) ); + } + else + { + strncpy( deviceIdentifier, "Unknown", sizeof( deviceIdentifier ) ); + } + } + + _atomicSpinlock_unlock( &lock ); + } + + return deviceIdentifier; +} + +/* + * @brief Retrieves the device metrics. + */ +const char * getDeviceMetrics( void ) +{ + const char * pDeviceIdentifier = NULL; + static uint32_t lock = 0; + + if( deviceMetrics[ 0 ] == '\0' ) + { + _atomicSpinlock_lock( &lock ); + + if( deviceMetrics[ 0 ] == '\0' ) + { + pDeviceIdentifier = getDeviceIdentifier(); + _generateDeviceMetrics( pDeviceIdentifier, strlen( pDeviceIdentifier ), deviceMetrics, sizeof( deviceMetrics ) ); + } + + _atomicSpinlock_unlock( &lock ); + } + + return deviceMetrics; +} + +/* + * @brief Retrieves the device metrics length. + */ +uint16_t getDeviceMetricsLength( void ) +{ + const char * pDeviceMetrics = getDeviceMetrics(); + + return ( uint16_t ) ( strlen( pDeviceMetrics ) ); +} diff --git a/bsp/aws_libraries/c_sdk/standard/common/iot_init.c b/bsp/aws_libraries/c_sdk/standard/common/iot_init.c new file mode 100644 index 0000000..42bc173 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/iot_init.c @@ -0,0 +1,154 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_init.c + * @brief Implements functions for common initialization and cleanup of this SDK. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* SDK initialization include. */ +#include "iot_init.h" + +/* Task pool include. */ +#include "iot_taskpool.h" + +/* Atomic include. */ +#include "iot_atomic.h" + +/* Static memory include (if dynamic memory allocation is disabled). */ +#include "private/iot_static_memory.h" + +/* Error handling include. */ +#include "private/iot_error.h" + +/* Configure logs for the functions in this file. */ +#ifdef IOT_LOG_LEVEL_GLOBAL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL +#else + #define LIBRARY_LOG_LEVEL IOT_LOG_NONE +#endif + +#define LIBRARY_LOG_NAME ( "INIT" ) +#include "iot_logging_setup.h" + +/*-----------------------------------------------------------*/ + +#if IOT_ATOMIC_GENERIC == 1 + +/** + * @brief Provides atomic operations with thread safety. + */ + IotMutex_t IotAtomicMutex; +#endif + +/*-----------------------------------------------------------*/ + +bool IotSdk_Init( void ) +{ + IOT_FUNCTION_ENTRY( bool, true ); + IotTaskPoolError_t taskPoolStatus = IOT_TASKPOOL_SUCCESS; + IotTaskPoolInfo_t taskPoolInfo = IOT_TASKPOOL_INFO_INITIALIZER_LARGE; + + /* Initialize the mutex for generic atomic operations if needed. */ + #if IOT_ATOMIC_GENERIC == 1 + bool genericAtomicInitialized = IotMutex_Create( &IotAtomicMutex, false ); + + if( genericAtomicInitialized == false ) + { + IotLogError( "Failed to initialize atomic operations." ); + IOT_SET_AND_GOTO_CLEANUP( false ); + } + #endif + + /* Initialize static memory if dynamic memory allocation is disabled. */ + #if IOT_STATIC_MEMORY_ONLY == 1 + bool staticMemoryInitialized = IotStaticMemory_Init(); + + if( staticMemoryInitialized == false ) + { + IotLogError( "Failed to initialize static memory." ); + IOT_SET_AND_GOTO_CLEANUP( false ); + } + #endif + + /* Create system task pool. */ + taskPoolStatus = IotTaskPool_CreateSystemTaskPool( &taskPoolInfo ); + + if( taskPoolStatus != IOT_TASKPOOL_SUCCESS ) + { + IotLogError( "Failed to create system task pool." ); + IOT_SET_AND_GOTO_CLEANUP( false ); + } + + IOT_FUNCTION_CLEANUP_BEGIN(); + + if( status == false ) + { + #if IOT_ATOMIC_GENERIC == 1 + if( genericAtomicInitialized == true ) + { + IotMutex_Destroy( &IotAtomicMutex ); + } + #endif + #if IOT_STATIC_MEMORY_ONLY == 1 + if( staticMemoryInitialized == true ) + { + IotStaticMemory_Cleanup(); + } + #endif + } + else + { + IotLogInfo( "SDK successfully initialized." ); + } + + IOT_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +void IotSdk_Cleanup( void ) +{ + IotTaskPool_Destroy( IOT_SYSTEM_TASKPOOL ); + + /* This log message must be printed before static memory management is + * cleaned up. */ + IotLogInfo( "SDK cleanup done." ); + + /* Cleanup static memory if dynamic memory allocation is disabled. */ + #if IOT_STATIC_MEMORY_ONLY == 1 + IotStaticMemory_Cleanup(); + #endif + + /* Clean up the mutex for generic atomic operations if needed. */ + #if IOT_ATOMIC_GENERIC == 1 + IotMutex_Destroy( &IotAtomicMutex ); + #endif +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/c_sdk/standard/common/iot_static_memory_common.c b/bsp/aws_libraries/c_sdk/standard/common/iot_static_memory_common.c new file mode 100644 index 0000000..feee523 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/iot_static_memory_common.c @@ -0,0 +1,208 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_static_memory_common.c + * @brief Implementation of common static memory functions in iot_static_memory.h + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* This file should only be compiled if dynamic memory allocation is forbidden. */ +#if IOT_STATIC_MEMORY_ONLY == 1 + +/* Standard includes. */ + #include + #include + #include + #include + +/* Platform layer includes. */ + #include "platform/iot_threads.h" + +/* Static memory include. */ + #include "private/iot_static_memory.h" + +/*-----------------------------------------------------------*/ + +/** + * @cond DOXYGEN_IGNORE + * Doxygen should ignore this section. + * + * Provide default values for undefined configuration constants. + */ + #ifndef IOT_MESSAGE_BUFFERS + #define IOT_MESSAGE_BUFFERS ( 8 ) + #endif + #ifndef IOT_MESSAGE_BUFFER_SIZE + #define IOT_MESSAGE_BUFFER_SIZE ( 1024 ) + #endif +/** @endcond */ + +/* Validate static memory configuration settings. */ + #if IOT_MESSAGE_BUFFERS <= 0 + #error "IOT_MESSAGE_BUFFERS cannot be 0 or negative." + #endif + #if IOT_MESSAGE_BUFFER_SIZE <= 0 + #error "IOT_MESSAGE_BUFFER_SIZE cannot be 0 or negative." + #endif + +/*-----------------------------------------------------------*/ + +/** + * @brief Guards access to critical sections. + */ + static IotMutex_t _mutex; + +/* + * Static memory buffers and flags, allocated and zeroed at compile-time. + */ + static bool _pInUseMessageBuffers[ IOT_MESSAGE_BUFFERS ] = { 0 }; /**< @brief Message buffer in-use flags. */ + static char _pMessageBuffers[ IOT_MESSAGE_BUFFERS ][ IOT_MESSAGE_BUFFER_SIZE ] = { { 0 } }; /**< @brief Message buffers. */ + +/*-----------------------------------------------------------*/ + + int32_t IotStaticMemory_FindFree( bool * pInUse, + size_t limit ) + { + size_t i = 0; + int32_t freeIndex = -1; + + /* Perform the search for a free buffer in a critical section. */ + IotMutex_Lock( &( _mutex ) ); + + for( i = 0; i < limit; i++ ) + { + if( pInUse[ i ] == false ) + { + /* If a free buffer is found, mark it "in-use" and return its index. */ + pInUse[ i ] = true; + freeIndex = ( int32_t ) i; + break; + } + } + + /* Exit the critical section. */ + IotMutex_Unlock( &( _mutex ) ); + + return freeIndex; + } + +/*-----------------------------------------------------------*/ + + void IotStaticMemory_ReturnInUse( void * ptr, + void * pPool, + bool * pInUse, + size_t limit, + size_t elementSize ) + { + size_t i = 0; + uint8_t * element = NULL; + + /* Clear ptr. */ + ( void ) memset( ptr, 0x00, elementSize ); + + /* Perform a search for ptr to make sure it's part of pPool. This search + * is done in a critical section. */ + IotMutex_Lock( &( _mutex ) ); + + for( i = 0; i < limit; i++ ) + { + /* Calculate address of the i-th element in pPool. */ + element = ( ( uint8_t * ) pPool ) + elementSize * i; + + /* Check for a match. */ + if( ( ( void * ) element == ptr ) && + ( pInUse[ i ] == true ) ) + { + pInUse[ i ] = false; + break; + } + } + + /* Exit the critical section. */ + IotMutex_Unlock( &( _mutex ) ); + } + +/*-----------------------------------------------------------*/ + + bool IotStaticMemory_Init( void ) + { + return IotMutex_Create( &( _mutex ), false ); + } + +/*-----------------------------------------------------------*/ + + void IotStaticMemory_Cleanup( void ) + { + IotMutex_Destroy( &( _mutex ) ); + } + +/*-----------------------------------------------------------*/ + + size_t Iot_MessageBufferSize( void ) + { + return ( size_t ) IOT_MESSAGE_BUFFER_SIZE; + } + +/*-----------------------------------------------------------*/ + + void * Iot_MallocMessageBuffer( size_t size ) + { + int32_t freeIndex = -1; + void * pNewBuffer = NULL; + + /* Check that size is within the fixed message buffer size. */ + if( size <= IOT_MESSAGE_BUFFER_SIZE ) + { + /* Get the index of a free message buffer. */ + freeIndex = IotStaticMemory_FindFree( _pInUseMessageBuffers, + IOT_MESSAGE_BUFFERS ); + + if( freeIndex != -1 ) + { + pNewBuffer = &( _pMessageBuffers[ freeIndex ][ 0 ] ); + } + } + + return pNewBuffer; + } + +/*-----------------------------------------------------------*/ + + void Iot_FreeMessageBuffer( void * ptr ) + { + /* Return the in-use message buffer. */ + IotStaticMemory_ReturnInUse( ptr, + _pMessageBuffers, + _pInUseMessageBuffers, + IOT_MESSAGE_BUFFERS, + IOT_MESSAGE_BUFFER_SIZE ); + } + +/*-----------------------------------------------------------*/ + +#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */ diff --git a/bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool.c b/bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool.c new file mode 100644 index 0000000..c7a877d --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool.c @@ -0,0 +1,1835 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_taskpool.c + * @brief Implements the task pool functions in iot_taskpool.h + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include +#include + +/* Platform layer includes. */ +#include "platform/iot_threads.h" +#include "platform/iot_clock.h" + +/* Task pool internal include. */ +#include "private/iot_taskpool_internal.h" + +/** + * @brief Enter a critical section by locking a mutex. + * + */ +#define TASKPOOL_ENTER_CRITICAL() IotMutex_Lock( &( pTaskPool->lock ) ) + +/** + * @brief Exit a critical section by unlocking a mutex. + * + */ +#define TASKPOOL_EXIT_CRITICAL() IotMutex_Unlock( &( pTaskPool->lock ) ) + +/** + * @brief Maximum semaphore value for wait operations. + */ +#define TASKPOOL_MAX_SEM_VALUE 0xFFFF + +/** + * @brief Reschedule delay in milliseconds for deferred jobs. + */ +#define TASKPOOL_JOB_RESCHEDULE_DELAY_MS ( 10ULL ) + +/* ---------------------------------------------------------------------------------- */ + +/** + * Doxygen should ignore this section. + * + * @brief The system task pool handle for all libraries to use. + * User application can use the system task pool as well knowing that the usage will be shared with + * the system libraries as well. The system task pool needs to be initialized before any library is used or + * before any code that posts jobs to the task pool runs. + */ +_taskPool_t _IotSystemTaskPool = { .dispatchQueue = IOT_DEQUEUE_INITIALIZER }; + +/* -------------- Convenience functions to create/recycle/destroy jobs -------------- */ + +/** + * @brief Initializes one instance of a Task pool cache. + * + * @param[in] pCache The pre-allocated instance of the cache to initialize. + */ +static void _initJobsCache( _taskPoolCache_t * const pCache ); + +/** + * @brief Initialize a job. + * + * @param[in] pJob The job to initialize. + * @param[in] userCallback The user callback for the job. + * @param[in] pUserContext The context tp be passed to the callback. + * @param[in] isStatic A flag to indicate whether the job is statically or dynamically allocated. + */ +static void _initializeJob( _taskPoolJob_t * const pJob, + IotTaskPoolRoutine_t userCallback, + void * pUserContext, + bool isStatic ); + +/** + * @brief Extracts and initializes one instance of a job from the cache or, if there is none available, it allocates and initializes a new one. + * + * @param[in] pCache The instance of the cache to extract the job from. + */ +static _taskPoolJob_t * _fetchOrAllocateJob( _taskPoolCache_t * const pCache ); + +/** + * Recycles one instance of a job into the cache or, if the cache is full, it destroys it. + * + * @param[in] pCache The instance of the cache to recycle the job into. + * @param[in] pJob The job to recycle. + * + */ +static void _recycleJob( _taskPoolCache_t * const pCache, + _taskPoolJob_t * const pJob ); + +/** + * Destroys one instance of a job. + * + * @param[in] pJob The job to destroy. + * + */ +static void _destroyJob( _taskPoolJob_t * const pJob ); + +/* -------------- The worker thread procedure for a task pool thread -------------- */ + +/** + * The procedure for a task pool worker thread. + * + * @param[in] pUserContext The user context. + * + */ +static void _taskPoolWorker( void * pUserContext ); + +/* -------------- Convenience functions to handle timer events -------------- */ + +/** + * Comparer for the time list. + * + * param[in] pTimerEventLink1 The link to the first timer event. + * param[in] pTimerEventLink1 The link to the first timer event. + */ +static int32_t _timerEventCompare( const IotLink_t * const pTimerEventLink1, + const IotLink_t * const pTimerEventLink2 ); + +/** + * Reschedules the timer for handling deferred jobs to the next timeout. + * + * param[in] pTimer The timer to reschedule. + * param[in] pFirstTimerEvent The timer event that carries the timeout and job information. + */ +static void _rescheduleDeferredJobsTimer( IotTimer_t * const pTimer, + _taskPoolTimerEvent_t * const pFirstTimerEvent ); + +/** + * The task pool timer procedure for scheduling deferred jobs. + * + * param[in] pArgument An opaque pointer for timer procedure context. + */ +static void _timerThread( void * pArgument ); + +/* -------------- Convenience functions to create/initialize/destroy the task pool -------------- */ + +/** + * Parameter validation for a task pool initialization. + * + * @param[in] pInfo The initialization information for the task pool. + * + */ +IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPoolInfo_t * const pInfo ); + +/** + * Initializes a pre-allocated instance of a task pool. + * + * @param[in] pInfo The initialization information for the task pool. + * @param[in] pTaskPool The pre-allocated instance of the task pool to initialize. + * + */ +static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_t * const pInfo, + _taskPool_t * const pTaskPool ); + +/** + * Initializes a pre-allocated instance of a task pool. + * + * @param[in] pInfo The initialization information for the task pool. + * @param[out] pTaskPool A pointer to the task pool data structure to initialize. + * + */ +static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo, + _taskPool_t * const pTaskPool ); + +/** + * Destroys one instance of a task pool. + * + * @param[in] pTaskPool The task pool to destroy. + * + */ +static void _destroyTaskPool( _taskPool_t * const pTaskPool ); + +/** + * Check for the exit condition. + * + * @param[in] pTaskPool The task pool to destroy. + * + */ +static bool _IsShutdownStarted( const _taskPool_t * const pTaskPool ); + +/** + * Set the exit condition. + * + * @param[in] pTaskPool The task pool to destroy. + * @param[in] threads The number of threads active in the task pool at shutdown time. + * + */ +static void _signalShutdown( _taskPool_t * const pTaskPool, + uint32_t threads ); + +/** + * Places a job in the dispatch queue. + * + * @param[in] pTaskPool The task pool to schedule the job with. + * @param[in] pJob The job to schedule. + * @param[in] flags The job flags. + * + */ +static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool, + _taskPoolJob_t * const pJob, + uint32_t flags ); + +/** + * Matches a deferred job in the timer queue with its timer event wrapper. + * + * @param[in] pLink A pointer to the timer event link in the timer queue. + * @param[in] pMatch A pointer to the job to match. + * + */ +static bool _matchJobByPointer( const IotLink_t * const pLink, + void * pMatch ); + +/** + * Tries to cancel a job. + * + * @param[in] pTaskPool The task pool to cancel an operation against. + * @param[in] pJob The job to cancel. + * @param[out] pStatus The status of the job at the time of cancellation. + * + */ +static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool, + _taskPoolJob_t * const pJob, + IotTaskPoolJobStatus_t * const pStatus ); + +/** + * Try to safely cancel and/or remove a job from the cache when the user calls API out of order. + * + * @param[in] pTaskPool The task pool to safely extract a job from. + * @param[in] pJob The job to extract. + * @param[in] atCompletion A flag to indicate whether the job is being scheduled or + * was completed already. + * + */ +static IotTaskPoolError_t _trySafeExtraction( _taskPool_t * const pTaskPool, + _taskPoolJob_t * const pJob, + bool atCompletion ); + +/* ---------------------------------------------------------------------------------------------- */ + +IotTaskPool_t IotTaskPool_GetSystemTaskPool( void ) +{ + return &_IotSystemTaskPool; +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + /* Parameter checking. */ + TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) ); + + /* Create the system task pool pool. */ + TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, &_IotSystemTaskPool ) ); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo, + IotTaskPool_t * const pTaskPool ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + _taskPool_t * pTempTaskPool = NULL; + + /* Verify that the task pool storage is valid. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool ); + + /* Parameter checking. */ + TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) ); + + /* Allocate the memory for the task pool */ + pTempTaskPool = ( _taskPool_t * ) IotTaskPool_MallocTaskPool( sizeof( _taskPool_t ) ); + + if( pTempTaskPool == NULL ) + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + + memset( pTempTaskPool, 0x00, sizeof( _taskPool_t ) ); + + TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, pTempTaskPool ) ); + + TASKPOOL_FUNCTION_CLEANUP(); + + if( TASKPOOL_FAILED( status ) ) + { + if( pTempTaskPool != NULL ) + { + IotTaskPool_FreeTaskPool( pTempTaskPool ); + } + } + else + { + *pTaskPool = pTempTaskPool; + } + + TASKPOOL_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + uint32_t count; + bool completeShutdown = true; + + _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + /* Track how many threads the task pool owns. */ + uint32_t activeThreads; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool ); + + /* Destroying the task pool should be safe, and therefore we will grab the task pool lock. + * No worker thread or application thread should access any data structure + * in the task pool while the task pool is being destroyed. */ + TASKPOOL_ENTER_CRITICAL(); + { + IotLink_t * pItemLink; + + /* Record how many active threads in the task pool. */ + activeThreads = pTaskPool->activeThreads; + + /* Destroying a Task pool happens in six (6) stages: First, (1) we clear the job queue and (2) the timer queue. + * Then (3) we clear the jobs cache. We will then (4) wait for all worker threads to signal exit, + * before (5) setting the exit condition and wake up all active worker threads. Finally (6) destroying + * all task pool data structures and release the associated memory. + */ + + /* (1) Clear the job queue. */ + do + { + pItemLink = NULL; + + pItemLink = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue ); + + if( pItemLink != NULL ) + { + _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link ); + + _destroyJob( pJob ); + } + } while( pItemLink ); + + /* (2) Clear the timer queue. */ + { + _taskPoolTimerEvent_t * pTimerEvent; + + /* A deferred job may have fired already. Since deferred jobs will go through the same mutex + * the shutdown sequence is holding at this stage, there is no risk for race conditions. Yet, we + * need to let the deferred job to destroy the task pool. */ + + pItemLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList ); + + if( pItemLink != NULL ) + { + uint64_t now = IotClock_GetTimeMs(); + + pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link ); + + if( pTimerEvent->expirationTime <= now ) + { + IotLogDebug( "Shutdown will be deferred to the timer thread" ); + + /* Timer may have fired already! Let the timer thread destroy + * complete the taskpool destruction sequence. */ + completeShutdown = false; + } + + /* Remove all timers from the timeout list. */ + for( ; ; ) + { + pItemLink = IotListDouble_RemoveHead( &pTaskPool->timerEventsList ); + + if( pItemLink == NULL ) + { + break; + } + + pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link ); + + _destroyJob( pTimerEvent->pJob ); + + IotTaskPool_FreeTimerEvent( pTimerEvent ); + } + } + } + + /* (3) Clear the job cache. */ + do + { + pItemLink = NULL; + + pItemLink = IotListDouble_RemoveHead( &pTaskPool->jobsCache.freeList ); + + if( pItemLink != NULL ) + { + _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link ); + + _destroyJob( pJob ); + } + } while( pItemLink ); + + /* (4) Set the exit condition. */ + _signalShutdown( pTaskPool, activeThreads ); + } + TASKPOOL_EXIT_CRITICAL(); + + /* (5) Wait for all active threads to reach the end of their life-span. */ + for( count = 0; count < activeThreads; ++count ) + { + IotSemaphore_Wait( &pTaskPool->startStopSignal ); + } + + IotTaskPool_Assert( IotSemaphore_GetCount( &pTaskPool->startStopSignal ) == 0 ); + IotTaskPool_Assert( pTaskPool->activeThreads == 0 ); + + /* (6) Destroy all signaling objects. */ + if( completeShutdown == true ) + { + _destroyTaskPool( pTaskPool ); + + /* Do not free the system task pool which is statically allocated. */ + if( pTaskPool != &_IotSystemTaskPool ) + { + IotTaskPool_FreeTaskPool( pTaskPool ); + } + } + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_SetMaxThreads( IotTaskPool_t taskPoolHandle, + uint32_t maxThreads ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + uint32_t count, i; + + _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool ); + TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pTaskPool->minThreads > maxThreads ); + TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( maxThreads < 1UL ); + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS ); + } + + uint32_t previousMaxThreads = pTaskPool->maxThreads; + + /* Reset the max threads counter. */ + pTaskPool->maxThreads = maxThreads; + + count = previousMaxThreads - maxThreads; + + /* If the number of maximum threads in the pool is set to be smaller than the current value, + * then we need to signal all redundant threads to exit. + */ + if( maxThreads < previousMaxThreads ) + { + IotLogDebug( "Setting max threads caused %d thread to exit.", count ); + + i = count; + + while( i > 0UL ) + { + IotSemaphore_Post( &pTaskPool->dispatchSignal ); + + --i; + } + } + } + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback, + void * pUserContext, + IotTaskPoolJobStorage_t * const pJobStorage, + IotTaskPoolJob_t * const ppJob ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJobStorage ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob ); + + /* Build a job around the user-provided storage. */ + _initializeJob( ( _taskPoolJob_t * ) pJobStorage, userCallback, pUserContext, true ); + + *ppJob = ( IotTaskPoolJob_t ) pJobStorage; + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle, + IotTaskPoolRoutine_t userCallback, + void * pUserContext, + IotTaskPoolJob_t * const ppJob ) +{ + _taskPool_t * pTaskPool = NULL; + + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + { + _taskPoolJob_t * pTempJob = NULL; + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS ); + } + + pTempJob = _fetchOrAllocateJob( &pTaskPool->jobsCache ); + } + TASKPOOL_EXIT_CRITICAL(); + + if( pTempJob == NULL ) + { + IotLogInfo( "Failed to allocate a job." ); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + + _initializeJob( pTempJob, userCallback, pUserContext, false ); + + *ppJob = pTempJob; + } + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandle, + IotTaskPoolJob_t pJobHandle ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + _taskPool_t * pTaskPool = NULL; + _taskPoolJob_t * pJob1 = NULL; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJobHandle ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + pJob1 = ( _taskPoolJob_t * ) pJobHandle; + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + status = IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS; + } + /* Do not destroy statically allocated jobs. */ + else if( ( pJob1->flags & IOT_TASK_POOL_INTERNAL_STATIC ) == IOT_TASK_POOL_INTERNAL_STATIC ) + { + IotLogWarn( "Attempt to destroy a statically allocated job." ); + + status = IOT_TASKPOOL_ILLEGAL_OPERATION; + } + else + { + status = _trySafeExtraction( pTaskPool, pJob1, true ); + } + } + TASKPOOL_EXIT_CRITICAL(); + + if( TASKPOOL_SUCCEEDED( status ) ) + { + /* At this point, the job must not be in any queue or list. */ + IotTaskPool_Assert( IotLink_IsLinked( &pJob1->link ) == false ); + + _destroyJob( pJob1 ); + } + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPoolHandle, + IotTaskPoolJob_t pJob ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + _taskPool_t * pTaskPool = NULL; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + status = IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS; + } + /* Do not recycle statically allocated jobs. */ + else if( ( pJob->flags & IOT_TASK_POOL_INTERNAL_STATIC ) == 0UL ) + { + status = _trySafeExtraction( pTaskPool, pJob, true ); + } + else + { + IotLogWarn( "Attempt to recycle a statically allocated job." ); + + status = IOT_TASKPOOL_ILLEGAL_OPERATION; + } + + /* If all safety checks completed, proceed. */ + if( TASKPOOL_SUCCEEDED( status ) ) + { + /* At this point, the job must not be in any queue or list. */ + IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false ); + + _recycleJob( &pTaskPool->jobsCache, pJob ); + } + } + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle, + IotTaskPoolJob_t pJob, + uint32_t flags ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + _taskPool_t * pTaskPool = NULL; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob ); + TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( ( flags != 0UL ) && ( flags != IOT_TASKPOOL_JOB_HIGH_PRIORITY ) ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + status = IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS; + } + else + { + status = _trySafeExtraction( pTaskPool, pJob, false ); + } + + /* If all safety checks completed, proceed. */ + if( TASKPOOL_SUCCEEDED( status ) ) + { + status = _scheduleInternal( pTaskPool, pJob, flags ); + } + } + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle, + IotTaskPoolJob_t pJob, + uint32_t timeMs ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + _taskPool_t * pTaskPool = NULL; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + if( timeMs == 0UL ) + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IotTaskPool_Schedule( pTaskPool, pJob, 0 ) ); + } + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS ); + } + + /* If all safety checks completed, proceed. */ + if( TASKPOOL_SUCCEEDED( _trySafeExtraction( pTaskPool, pJob, false ) ) ) + { + IotLink_t * pTimerEventLink; + uint64_t now; + + _taskPoolTimerEvent_t * pTimerEvent = ( _taskPoolTimerEvent_t * ) IotTaskPool_MallocTimerEvent( sizeof( _taskPoolTimerEvent_t ) ); + + if( pTimerEvent == NULL ) + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + + memset( pTimerEvent, 0x00, sizeof( _taskPoolTimerEvent_t ) ); + + now = IotClock_GetTimeMs(); + + pTimerEvent->link.pNext = NULL; + pTimerEvent->link.pPrevious = NULL; + pTimerEvent->expirationTime = now + timeMs; + pTimerEvent->pJob = ( _taskPoolJob_t * ) pJob; + + /* Append the timer event to the timer list. */ + IotListDouble_InsertSorted( &pTaskPool->timerEventsList, &pTimerEvent->link, _timerEventCompare ); + + /* Update the job status to 'scheduled'. */ + pJob->status = IOT_TASKPOOL_STATUS_DEFERRED; + + /* Peek the first event in the timer event list. There must be at least one, + * since we just inserted it. */ + pTimerEventLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList ); + IotTaskPool_Assert( pTimerEventLink != NULL ); + + /* If the event we inserted is at the front of the queue, then + * we need to reschedule the underlying timer. */ + if( pTimerEventLink == &pTimerEvent->link ) + { + pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pTimerEventLink, link ); + + _rescheduleDeferredJobsTimer( &pTaskPool->timer, pTimerEvent ); + } + } + else + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_ILLEGAL_OPERATION ); + } + } + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle, + IotTaskPoolJob_t pJob, + IotTaskPoolJobStatus_t * const pStatus ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + _taskPool_t * pTaskPool = NULL; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED; + + TASKPOOL_ENTER_CRITICAL(); + { + /* Bail out early if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS ); + } + + *pStatus = pJob->status; + } + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle, + IotTaskPoolJob_t pJob, + IotTaskPoolJobStatus_t * const pStatus ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + _taskPool_t * pTaskPool = NULL; + + /* Parameter checking. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob ); + + pTaskPool = ( _taskPool_t * ) taskPoolHandle; + + if( pStatus != NULL ) + { + *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED; + } + + TASKPOOL_ENTER_CRITICAL(); + { + /* Check again if this task pool is shutting down. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS ); + } + + status = _tryCancelInternal( pTaskPool, pJob, pStatus ); + } + TASKPOOL_EXIT_CRITICAL(); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +IotTaskPoolJobStorage_t * IotTaskPool_GetJobStorageFromHandle( IotTaskPoolJob_t pJob ) +{ + return ( IotTaskPoolJobStorage_t * ) pJob; +} + +const char * IotTaskPool_strerror( IotTaskPoolError_t status ) +{ + const char * pMessage = NULL; + + switch( status ) + { + case IOT_TASKPOOL_SUCCESS: + pMessage = "SUCCESS"; + break; + + case IOT_TASKPOOL_BAD_PARAMETER: + pMessage = "BAD PARAMETER"; + break; + + case IOT_TASKPOOL_ILLEGAL_OPERATION: + pMessage = "ILLEGAL OPERATION"; + break; + + case IOT_TASKPOOL_NO_MEMORY: + pMessage = "NO MEMORY"; + break; + + case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS: + pMessage = "SHUTDOWN IN PROGRESS"; + break; + + case IOT_TASKPOOL_CANCEL_FAILED: + pMessage = "CANCEL FAILED"; + break; + + default: + pMessage = "INVALID STATUS"; + break; + } + + return pMessage; +} + +/* ---------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------------------------- */ + +IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPoolInfo_t * const pInfo ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + /* Check input values for consistency. */ + TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pInfo ); + TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->minThreads > pInfo->maxThreads ); + TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->minThreads < 1UL ); + TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->maxThreads < 1UL ); + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_t * const pInfo, + _taskPool_t * const pTaskPool ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + bool semStartStopInit = false; + bool lockInit = false; + bool semDispatchInit = false; + bool timerInit = false; + + /* Zero out all data structures. */ + memset( ( void * ) pTaskPool, 0x00, sizeof( _taskPool_t ) ); + + /* Initialize a job data structures that require no de-initialization. + * All other data structures carry a value of 'NULL' before initialization. + */ + IotDeQueue_Create( &pTaskPool->dispatchQueue ); + IotListDouble_Create( &pTaskPool->timerEventsList ); + + pTaskPool->minThreads = pInfo->minThreads; + pTaskPool->maxThreads = pInfo->maxThreads; + pTaskPool->stackSize = pInfo->stackSize; + pTaskPool->priority = pInfo->priority; + + _initJobsCache( &pTaskPool->jobsCache ); + + /* Initialize the semaphore to ensure all threads have started. */ + if( IotSemaphore_Create( &pTaskPool->startStopSignal, 0, TASKPOOL_MAX_SEM_VALUE ) == true ) + { + semStartStopInit = true; + + if( IotMutex_Create( &pTaskPool->lock, true ) == true ) + { + lockInit = true; + + /* Initialize the semaphore for waiting for incoming work. */ + if( IotSemaphore_Create( &pTaskPool->dispatchSignal, 0, TASKPOOL_MAX_SEM_VALUE ) == true ) + { + semDispatchInit = true; + + /* Create the timer mutex for a new connection. */ + if( IotClock_TimerCreate( &( pTaskPool->timer ), _timerThread, pTaskPool ) == true ) + { + timerInit = true; + } + else + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + } + else + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + } + else + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + } + else + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + + TASKPOOL_FUNCTION_CLEANUP(); + + if( TASKPOOL_FAILED( status ) ) + { + if( semStartStopInit == true ) + { + IotSemaphore_Destroy( &pTaskPool->startStopSignal ); + } + + if( lockInit == true ) + { + IotMutex_Destroy( &pTaskPool->lock ); + } + + if( semDispatchInit == true ) + { + IotSemaphore_Destroy( &pTaskPool->dispatchSignal ); + } + + if( timerInit == true ) + { + IotClock_TimerDestroy( &pTaskPool->timer ); + } + } + + TASKPOOL_FUNCTION_CLEANUP_END(); +} + +static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo, + _taskPool_t * const pTaskPool ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + uint32_t count; + uint32_t threadsCreated = 0; + bool controlInit = false; + + /* Initialize all internal data structure prior to creating all threads. */ + TASKPOOL_ON_ERROR_GOTO_CLEANUP( _initTaskPoolControlStructures( pInfo, pTaskPool ) ); + + controlInit = true; + + IotTaskPool_Assert( pInfo->minThreads == pTaskPool->minThreads ); + IotTaskPool_Assert( pInfo->maxThreads == pTaskPool->maxThreads ); + + /* The task pool will initialize the minimum number of threads requested by the user upon start. */ + /* When a thread is created, it will signal a semaphore to signify that it is about to wait on incoming */ + /* jobs. A thread can be woken up for exit or for new jobs only at that point in time. */ + /* The exit condition is setting the maximum number of threads to 0. */ + + /* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */ + for( ; threadsCreated < pTaskPool->minThreads; ) + { + /* Create one thread. */ + if( Iot_CreateDetachedThread( _taskPoolWorker, + pTaskPool, + pTaskPool->priority, + pTaskPool->stackSize ) == false ) + { + IotLogError( "Could not create worker thread! Exiting..." ); + + /* If creating one thread fails, set error condition and exit the loop. */ + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + + /* Upon successful thread creation, increase the number of active threads. */ + pTaskPool->activeThreads++; + + ++threadsCreated; + } + + TASKPOOL_FUNCTION_CLEANUP(); + + /* Wait for threads to be ready to wait on the condition, so that threads are actually able to receive messages. */ + for( count = 0; count < threadsCreated; ++count ) + { + IotSemaphore_Wait( &pTaskPool->startStopSignal ); + } + + /* In case of failure, wait on the created threads to exit. */ + if( TASKPOOL_FAILED( status ) ) + { + /* Set the exit condition for the newly created threads. */ + _signalShutdown( pTaskPool, threadsCreated ); + + /* Signal all threads to exit. */ + for( count = 0; count < threadsCreated; ++count ) + { + IotSemaphore_Wait( &pTaskPool->startStopSignal ); + } + + if( controlInit == true ) + { + _destroyTaskPool( pTaskPool ); + } + } + + TASKPOOL_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +static void _destroyTaskPool( _taskPool_t * const pTaskPool ) +{ + IotClock_TimerDestroy( &pTaskPool->timer ); + IotSemaphore_Destroy( &pTaskPool->dispatchSignal ); + IotSemaphore_Destroy( &pTaskPool->startStopSignal ); + IotMutex_Destroy( &pTaskPool->lock ); +} + +/* ---------------------------------------------------------------------------------------------- */ + +static void _taskPoolWorker( void * pUserContext ) +{ + IotTaskPool_Assert( pUserContext != NULL ); + + IotTaskPoolRoutine_t userCallback = NULL; + bool running = true; + + /* Extract pTaskPool pointer from context. */ + _taskPool_t * pTaskPool = ( _taskPool_t * ) pUserContext; + + /* Signal that this worker completed initialization and it is ready to receive notifications. */ + IotSemaphore_Post( &pTaskPool->startStopSignal ); + + /* OUTER LOOP: it controls the lifetime of the worker thread: exit condition for a worker thread + * is setting maxThreads to zero. A worker thread is running until the maximum number of allowed + * threads is not zero and the active threads are less than the maximum number of allowed threads. + */ + do + { + bool jobAvailable; + IotLink_t * pFirst; + _taskPoolJob_t * pJob = NULL; + + /* Wait on incoming notifications. If waiting on the semaphore return with timeout, then + * it means that this thread should consider shutting down for the task pool to fold back + * to its minimum number of threads. */ + jobAvailable = IotSemaphore_TimedWait( &pTaskPool->dispatchSignal, IOT_TASKPOOL_JOB_WAIT_TIMEOUT_MS ); + + /* Acquire the lock to check the exit condition, and release the lock if the exit condition is verified, + * or before waiting for incoming notifications. + */ + TASKPOOL_ENTER_CRITICAL(); + { + /* If the exit condition is verified, update the number of active threads and exit the loop. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + IotLogDebug( "Worker thread exiting because shutdown condition was set." ); + + /* Decrease the number of active threads. */ + pTaskPool->activeThreads--; + + TASKPOOL_EXIT_CRITICAL(); + + /* Signal that this worker is exiting. */ + IotSemaphore_Post( &pTaskPool->startStopSignal ); + + /* On shutdown, abandon the OUTER LOOP immediately. */ + break; + } + + /* Check if this thread needs to exit because 'max threads' quota was exceeded. + * In that case, let it run once, so we can support the case for scheduling 'high priority' + * jobs that causes exceeding the max threads quota for the purpose of executing + * the high-priority task. */ + if( pTaskPool->activeThreads > pTaskPool->maxThreads ) + { + IotLogDebug( "Worker thread will exit because maximum quota was exceeded." ); + + /* Decrease the number of active threads pro-actively. */ + pTaskPool->activeThreads--; + + /* Mark this thread as dead. */ + running = false; + } + /* Check if this thread needs to exit because the worker woke up after a timeout. */ + else if( jobAvailable == false ) + { + /* If there was a timeout, shrink back the task pool to the minimum number of threads. */ + if( pTaskPool->activeThreads > pTaskPool->minThreads ) + { + /* After waking up from a timeout, the thread will try and pick up a new job. + * But if there is no job available, the thread will exit to ensure that + * the taskpool does not have more than minimum number of active threads. */ + IotLogDebug( "Worker will exit because task pool is shrinking." ); + + /* Decrease the number of active threads pro-actively. */ + pTaskPool->activeThreads--; + + /* Mark this thread as dead. */ + running = false; + } + } + + /* Only look for a job if waiting did not timed out. */ + if( jobAvailable == true ) + { + /* Dequeue the first job in FIFO order. */ + pFirst = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue ); + + /* If there is indeed a job, then update status under lock, and release the lock before processing the job. */ + if( pFirst != NULL ) + { + /* Extract the job from its link. */ + pJob = IotLink_Container( _taskPoolJob_t, pFirst, link ); + + /* Update status to 'executing'. */ + pJob->status = IOT_TASKPOOL_STATUS_COMPLETED; + userCallback = pJob->userCallback; + } + } + } + TASKPOOL_EXIT_CRITICAL(); + + /* INNER LOOP: it controls the execution of jobs: the exit condition is the lack of a job to execute. */ + while( pJob != NULL ) + { + /* Process the job by invoking the associated callback with the user context. + * This task pool thread will not be available until the user callback returns. + */ + { + IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false ); + IotTaskPool_Assert( userCallback != NULL ); + + userCallback( pTaskPool, pJob, pJob->pUserContext ); + + /* This job is finished, clear its pointer. */ + pJob = NULL; + userCallback = NULL; + + /* If this thread exceeded the quota, then let it terminate. */ + if( running == false ) + { + /* Abandon the INNER LOOP. Execution will tranfer back to the OUTER LOOP condition. */ + break; + } + } + + /* Acquire the lock before updating the job status. */ + TASKPOOL_ENTER_CRITICAL(); + { + /* Update the number of busy threads, so new requests can be served by creating new threads, up to maxThreads. */ + pTaskPool->activeJobs--; + + /* Try and dequeue the next job in the dispatch queue. */ + IotLink_t * pItem = NULL; + + /* Dequeue the next job from the dispatch queue. */ + pItem = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue ); + + /* If there is no job left in the dispatch queue, update the worker status and leave. */ + if( pItem == NULL ) + { + TASKPOOL_EXIT_CRITICAL(); + + /* Abandon the INNER LOOP. Execution will tranfer back to the OUTER LOOP condition. */ + break; + } + else + { + pJob = IotLink_Container( _taskPoolJob_t, pItem, link ); + + userCallback = pJob->userCallback; + } + + pJob->status = IOT_TASKPOOL_STATUS_COMPLETED; + } + TASKPOOL_EXIT_CRITICAL(); + } + } while( running == true ); +} + +/* ---------------------------------------------------------------------------------------------- */ + +static void _initJobsCache( _taskPoolCache_t * const pCache ) +{ + IotDeQueue_Create( &pCache->freeList ); + + pCache->freeCount = 0; +} + +/*-----------------------------------------------------------*/ + +static void _initializeJob( _taskPoolJob_t * const pJob, + IotTaskPoolRoutine_t userCallback, + void * pUserContext, + bool isStatic ) +{ + pJob->link.pNext = NULL; + pJob->link.pPrevious = NULL; + pJob->userCallback = userCallback; + pJob->pUserContext = pUserContext; + + if( isStatic ) + { + pJob->flags = IOT_TASK_POOL_INTERNAL_STATIC; + pJob->status = IOT_TASKPOOL_STATUS_READY; + } + else + { + pJob->status = IOT_TASKPOOL_STATUS_READY; + } +} + +static _taskPoolJob_t * _fetchOrAllocateJob( _taskPoolCache_t * const pCache ) +{ + _taskPoolJob_t * pJob = NULL; + IotLink_t * pLink = IotListDouble_RemoveHead( &( pCache->freeList ) ); + + if( pLink != NULL ) + { + pJob = IotLink_Container( _taskPoolJob_t, pLink, link ); + } + + /* If there is no available job in the cache, then allocate one. */ + if( pJob == NULL ) + { + pJob = ( _taskPoolJob_t * ) IotTaskPool_MallocJob( sizeof( _taskPoolJob_t ) ); + + if( pJob != NULL ) + { + memset( pJob, 0x00, sizeof( _taskPoolJob_t ) ); + } + else + { + /* Log allocation failure for troubleshooting purposes. */ + IotLogInfo( "Failed to allocate job." ); + } + } + /* If there was a job in the cache, then make sure we keep the counters up-to-date. */ + else + { + IotTaskPool_Assert( pCache->freeCount > 0 ); + + pCache->freeCount--; + } + + return pJob; +} + +/*-----------------------------------------------------------*/ + +static void _recycleJob( _taskPoolCache_t * const pCache, + _taskPoolJob_t * const pJob ) +{ + /* We should never try and recycling a job that is linked into some queue. */ + IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false ); + + /* We will recycle the job if there is space in the cache. */ + if( pCache->freeCount < IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ) + { + /* Destroy user data, for added safety & security. */ + pJob->userCallback = NULL; + pJob->pUserContext = NULL; + + /* Reset the status for added debugability. */ + pJob->status = IOT_TASKPOOL_STATUS_UNDEFINED; + + IotListDouble_InsertTail( &pCache->freeList, &pJob->link ); + + pCache->freeCount++; + + IotTaskPool_Assert( pCache->freeCount >= 1 ); + } + else + { + _destroyJob( pJob ); + } +} + +/*-----------------------------------------------------------*/ + +static void _destroyJob( _taskPoolJob_t * const pJob ) +{ + /* Destroy user data, for added safety & security. */ + pJob->userCallback = NULL; + pJob->pUserContext = NULL; + + /* Reset the status for added debugability. */ + pJob->status = IOT_TASKPOOL_STATUS_UNDEFINED; + + /* Only dispose of dynamically allocated jobs. */ + if( ( pJob->flags & IOT_TASK_POOL_INTERNAL_STATIC ) == 0UL ) + { + IotTaskPool_FreeJob( pJob ); + } +} + +/* ---------------------------------------------------------------------------------------------- */ + +static bool _IsShutdownStarted( const _taskPool_t * const pTaskPool ) +{ + return( pTaskPool->maxThreads == 0UL ); +} + +/*-----------------------------------------------------------*/ + +static void _signalShutdown( _taskPool_t * const pTaskPool, + uint32_t threads ) +{ + uint32_t count; + + /* Set the exit condition. */ + pTaskPool->maxThreads = 0; + + /* Broadcast to all active threads to wake-up. Active threads do check the exit condition right after waking up. */ + for( count = 0; count < threads; ++count ) + { + IotSemaphore_Post( &pTaskPool->dispatchSignal ); + } +} + +/* ---------------------------------------------------------------------------------------------- */ + +static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool, + _taskPoolJob_t * const pJob, + uint32_t flags ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + bool mustGrow = false; + bool shouldGrow = false; + + /* Update the job status to 'scheduled'. */ + pJob->status = IOT_TASKPOOL_STATUS_SCHEDULED; + + /* Update the number of active jobs optimistically, so new requests can be served by creating new threads. */ + pTaskPool->activeJobs++; + + /* If all threads are busy, try and create a new one. Failing to create a new thread + * only has performance implications on correctly executing the scheduled job. + */ + uint32_t activeThreads = pTaskPool->activeThreads; + + if( activeThreads <= pTaskPool->activeJobs ) + { + /* If the job scheduling is tagged as high priority, then we must grow the task pool, + * no matter how many threads are active already. */ + if( ( flags & IOT_TASKPOOL_JOB_HIGH_PRIORITY ) == IOT_TASKPOOL_JOB_HIGH_PRIORITY ) + { + mustGrow = true; + } + + /* Grow the task pool up to the maximum number of threads indicated by the user. + * Growing the taskpool can safely fail, the existing threads will eventually pick up + * the job sometimes later. */ + else if( activeThreads < pTaskPool->maxThreads ) + { + shouldGrow = true; + } + else + { + /* Nothing to do. */ + } + + if( ( mustGrow == true ) || ( shouldGrow == true ) ) + { + IotLogInfo( "Growing a Task pool with a new worker thread..." ); + + if( Iot_CreateDetachedThread( _taskPoolWorker, + pTaskPool, + pTaskPool->priority, + pTaskPool->stackSize ) ) + { + IotSemaphore_Wait( &pTaskPool->startStopSignal ); + + pTaskPool->activeThreads++; + } + else + { + /* Failure to create a worker thread may not hinder functional correctness, but rather just responsiveness. */ + IotLogWarn( "Task pool failed to create a worker thread." ); + + /* Failure to create a worker thread for a high priority job is considered a failure. */ + if( mustGrow ) + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY ); + } + } + } + } + + TASKPOOL_FUNCTION_CLEANUP(); + + if( TASKPOOL_SUCCEEDED( status ) ) + { + /* Append the job to the dispatch queue. + * Put the job at the front, if it is a high priority job. */ + if( mustGrow == true ) + { + IotLogDebug( "High priority job: placing job at the head of the queue." ); + + IotDeQueue_EnqueueHead( &pTaskPool->dispatchQueue, &pJob->link ); + } + else + { + IotDeQueue_EnqueueTail( &pTaskPool->dispatchQueue, &pJob->link ); + } + + /* Signal a worker to pick up the job. */ + IotSemaphore_Post( &pTaskPool->dispatchSignal ); + } + else + { + /* Scheduling can only fail to allocate a new worker, which is an error + * only for high priority tasks. */ + IotTaskPool_Assert( mustGrow == true ); + + /* Revert updating the number of active jobs. */ + pTaskPool->activeJobs--; + } + + TASKPOOL_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +static bool _matchJobByPointer( const IotLink_t * const pLink, + void * pMatch ) +{ + const _taskPoolJob_t * const pJob = ( _taskPoolJob_t * ) pMatch; + + const _taskPoolTimerEvent_t * const pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pLink, link ); + + if( pJob == pTimerEvent->pJob ) + { + return true; + } + + return false; +} + +/*-----------------------------------------------------------*/ + +static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool, + _taskPoolJob_t * const pJob, + IotTaskPoolJobStatus_t * const pStatus ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + bool cancelable = false; + + /* We can only cancel jobs that are either 'ready' (waiting to be scheduled). 'deferred', or 'scheduled'. */ + + IotTaskPoolJobStatus_t currentStatus = pJob->status; + + switch( currentStatus ) + { + case IOT_TASKPOOL_STATUS_READY: + case IOT_TASKPOOL_STATUS_DEFERRED: + case IOT_TASKPOOL_STATUS_SCHEDULED: + case IOT_TASKPOOL_STATUS_CANCELED: + cancelable = true; + break; + + case IOT_TASKPOOL_STATUS_COMPLETED: + /* Log message for debugging purposes. */ + IotLogWarn( "Attempt to cancel a job that is already executing, or canceled." ); + break; + + default: + /* Log message for debugging purposes. */ + IotLogError( "Attempt to cancel a job with an undefined state." ); + break; + } + + /* Update the returned status to the current status of the job. */ + if( pStatus != NULL ) + { + *pStatus = currentStatus; + } + + if( cancelable == false ) + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_CANCEL_FAILED ); + } + else + { + /* Update the status of the job. */ + pJob->status = IOT_TASKPOOL_STATUS_CANCELED; + + /* If the job is cancelable and its current status is 'scheduled' then unlink it from the dispatch + * queue and signal any waiting threads. */ + if( currentStatus == IOT_TASKPOOL_STATUS_SCHEDULED ) + { + /* A scheduled work items must be in the dispatch queue. */ + IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) ); + + IotDeQueue_Remove( &pJob->link ); + } + + /* If the job current status is 'deferred' then the job has to be pending + * in the timeouts queue. */ + else if( currentStatus == IOT_TASKPOOL_STATUS_DEFERRED ) + { + /* Find the timer event associated with the current job. There MUST be one, hence assert if not. */ + IotLink_t * pTimerEventLink = IotListDouble_FindFirstMatch( &pTaskPool->timerEventsList, NULL, _matchJobByPointer, pJob ); + IotTaskPool_Assert( pTimerEventLink != NULL ); + + if( pTimerEventLink != NULL ) + { + bool shouldReschedule = false; + + /* If the job being cancelled was at the head of the timeouts queue, then we need to reschedule the timer + * with the next job timeout */ + IotLink_t * pHeadLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList ); + + if( pHeadLink == pTimerEventLink ) + { + shouldReschedule = true; + } + + /* Remove the timer event associated with the canceled job and free the associated memory. */ + IotListDouble_Remove( pTimerEventLink ); + IotTaskPool_FreeTimerEvent( IotLink_Container( _taskPoolTimerEvent_t, pTimerEventLink, link ) ); + + if( shouldReschedule ) + { + IotLink_t * pNextTimerEventLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList ); + + if( pNextTimerEventLink != NULL ) + { + _rescheduleDeferredJobsTimer( &pTaskPool->timer, IotLink_Container( _taskPoolTimerEvent_t, pNextTimerEventLink, link ) ); + } + } + } + } + else + { + /* A cancelable job status should be either 'scheduled' or 'deferrred'. */ + IotTaskPool_Assert( ( currentStatus == IOT_TASKPOOL_STATUS_READY ) || ( currentStatus == IOT_TASKPOOL_STATUS_CANCELED ) ); + } + } + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static IotTaskPoolError_t _trySafeExtraction( _taskPool_t * const pTaskPool, + _taskPoolJob_t * const pJob, + bool atCompletion ) +{ + TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS ); + + IotTaskPoolJobStatus_t currentStatus = pJob->status; + + /* if the job is executing, we cannot touch it. */ + if( ( atCompletion == false ) && ( currentStatus == IOT_TASKPOOL_STATUS_COMPLETED ) ) + { + TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_ILLEGAL_OPERATION ); + } + /* Do not destroy a job in the dispatch queue or the timer queue without cancelling first. */ + else if( ( currentStatus == IOT_TASKPOOL_STATUS_SCHEDULED ) || ( currentStatus == IOT_TASKPOOL_STATUS_DEFERRED ) ) + { + IotTaskPoolJobStatus_t statusAtCancellation; + + /* Cancellation can fail, e.g. if a job is being executed when we are trying to cancel it. */ + status = _tryCancelInternal( pTaskPool, pJob, &statusAtCancellation ); + + switch( status ) + { + case IOT_TASKPOOL_SUCCESS: + /* Nothing to do. */ + break; + + case IOT_TASKPOOL_CANCEL_FAILED: + IotLogWarn( "Removing a scheduled job failed because the job could not be canceled, error %s.", + IotTaskPool_strerror( status ) ); + status = IOT_TASKPOOL_ILLEGAL_OPERATION; + break; + + default: + /* Nothing to do. */ + break; + } + } + else if( IotLink_IsLinked( &pJob->link ) ) + { + /* If the job is not in the dispatch or timer queue, it must be in the cache. */ + IotTaskPool_Assert( ( pJob->flags & IOT_TASK_POOL_INTERNAL_STATIC ) == 0 ); + + IotListDouble_Remove( &pJob->link ); + } + else + { + /* Nothing to do */ + } + + TASKPOOL_NO_FUNCTION_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static int32_t _timerEventCompare( const IotLink_t * const pTimerEventLink1, + const IotLink_t * const pTimerEventLink2 ) +{ + const _taskPoolTimerEvent_t * const pTimerEvent1 = IotLink_Container( _taskPoolTimerEvent_t, + pTimerEventLink1, + link ); + const _taskPoolTimerEvent_t * const pTimerEvent2 = IotLink_Container( _taskPoolTimerEvent_t, + pTimerEventLink2, + link ); + + if( pTimerEvent1->expirationTime < pTimerEvent2->expirationTime ) + { + return -1; + } + + if( pTimerEvent1->expirationTime > pTimerEvent2->expirationTime ) + { + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------*/ + +static void _rescheduleDeferredJobsTimer( IotTimer_t * const pTimer, + _taskPoolTimerEvent_t * const pFirstTimerEvent ) +{ + uint64_t delta = 0; + uint64_t now = IotClock_GetTimeMs(); + + if( pFirstTimerEvent->expirationTime > now ) + { + delta = pFirstTimerEvent->expirationTime - now; + } + + if( delta < TASKPOOL_JOB_RESCHEDULE_DELAY_MS ) + { + delta = TASKPOOL_JOB_RESCHEDULE_DELAY_MS; /* The job will be late... */ + } + + IotTaskPool_Assert( delta > 0 ); + + if( IotClock_TimerArm( pTimer, ( uint32_t ) delta, 0 ) == false ) + { + IotLogWarn( "Failed to re-arm timer for task pool" ); + } +} + +/*-----------------------------------------------------------*/ + +static void _timerThread( void * pArgument ) +{ + _taskPool_t * pTaskPool = ( _taskPool_t * ) pArgument; + _taskPoolTimerEvent_t * pTimerEvent = NULL; + + IotLogDebug( "Timer thread started for task pool %p.", pTaskPool ); + + /* Attempt to lock the timer mutex. Return immediately if the mutex cannot be locked. + * If this mutex cannot be locked it means that another thread is manipulating the + * timeouts list, and will reset the timer to fire again, although it will be late. + */ + TASKPOOL_ENTER_CRITICAL(); + { + /* Check again for shutdown and bail out early in case. */ + if( _IsShutdownStarted( pTaskPool ) ) + { + TASKPOOL_EXIT_CRITICAL(); + + /* Complete the shutdown sequence. */ + _destroyTaskPool( pTaskPool ); + + IotTaskPool_FreeTaskPool( pTaskPool ); + + return; + } + + /* Dispatch all deferred job whose timer expired, then reset the timer for the next + * job down the line. */ + for( ; ; ) + { + /* Peek the first event in the timer event list. */ + IotLink_t * pLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList ); + + /* Check if the timer misfired for any reason. */ + if( pLink != NULL ) + { + /* Record the current time. */ + uint64_t now = IotClock_GetTimeMs(); + + /* Extract the job from its envelope. */ + pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pLink, link ); + + /* Check if the first event should be processed now. */ + if( pTimerEvent->expirationTime <= now ) + { + /* Remove the timer event for immediate processing. */ + IotListDouble_Remove( &( pTimerEvent->link ) ); + } + else + { + /* The first element in the timer queue shouldn't be processed yet. + * Arm the timer for when it should be processed and leave altogether. */ + _rescheduleDeferredJobsTimer( &pTaskPool->timer, pTimerEvent ); + + break; + } + } + /* If there are no timer events to process, terminate this thread. */ + else + { + IotLogDebug( "No further timer events to process. Exiting timer thread." ); + + break; + } + + IotLogDebug( "Scheduling job from timer event." ); + + /* Queue the job associated with the received timer event. */ + ( void ) _scheduleInternal( pTaskPool, pTimerEvent->pJob, 0 ); + + /* Free the timer event. */ + IotTaskPool_FreeTimerEvent( pTimerEvent ); + } + } + TASKPOOL_EXIT_CRITICAL(); +} diff --git a/bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool_static_memory.c b/bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool_static_memory.c new file mode 100644 index 0000000..516d6e0 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/common/taskpool/iot_taskpool_static_memory.c @@ -0,0 +1,175 @@ +/* + * FreeRTOS Common V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_taskpool_static_memory.c + * @brief Implementation of task pool static memory functions. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* This file should only be compiled if dynamic memory allocation is forbidden. */ +#if IOT_STATIC_MEMORY_ONLY == 1 + +/* Standard includes. */ + #include + #include + #include + +/* Static memory include. */ + #include "private/iot_static_memory.h" + +/* Task pool internal include. */ + #include "private/iot_taskpool_internal.h" + +/*-----------------------------------------------------------*/ + +/* Validate static memory configuration settings. */ + #if IOT_TASKPOOL_JOBS_RECYCLE_LIMIT <= 0 + #error "IOT_TASKPOOL_JOBS_RECYCLE_LIMIT cannot be 0 or negative." + #endif + +/*-----------------------------------------------------------*/ + +/* + * Static memory buffers and flags, allocated and zeroed at compile-time. + */ + static bool _pInUseTaskPools[ IOT_TASKPOOLS ] = { 0 }; /**< @brief Task pools in-use flags. */ + static _taskPool_t _pTaskPools[ IOT_TASKPOOLS ] = { { .dispatchQueue = IOT_DEQUEUE_INITIALIZER } }; /**< @brief Task pools. */ + + static bool _pInUseTaskPoolJobs[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { 0 }; /**< @brief Task pool jobs in-use flags. */ + static _taskPoolJob_t _pTaskPoolJobs[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { { .link = IOT_LINK_INITIALIZER } }; /**< @brief Task pool jobs. */ + + static bool _pInUseTaskPoolTimerEvents[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { 0 }; /**< @brief Task pool timer event in-use flags. */ + static _taskPoolTimerEvent_t _pTaskPoolTimerEvents[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { { .link = { 0 } } }; /**< @brief Task pool timer events. */ + +/*-----------------------------------------------------------*/ + + void * IotTaskPool_MallocTaskPool( size_t size ) + { + int freeIndex = -1; + void * pNewTaskPool = NULL; + + /* Check size argument. */ + if( size == sizeof( _taskPool_t ) ) + { + /* Find a free task pool job. */ + freeIndex = IotStaticMemory_FindFree( _pInUseTaskPools, IOT_TASKPOOLS ); + + if( freeIndex != -1 ) + { + pNewTaskPool = &( _pTaskPools[ freeIndex ] ); + } + } + + return pNewTaskPool; + } + +/*-----------------------------------------------------------*/ + + void IotTaskPool_FreeTaskPool( void * ptr ) + { + /* Return the in-use task pool job. */ + IotStaticMemory_ReturnInUse( ptr, + _pTaskPools, + _pInUseTaskPools, + IOT_TASKPOOLS, + sizeof( _taskPool_t ) ); + } + +/*-----------------------------------------------------------*/ + + void * IotTaskPool_MallocJob( size_t size ) + { + int32_t freeIndex = -1; + void * pNewJob = NULL; + + /* Check size argument. */ + if( size == sizeof( _taskPoolJob_t ) ) + { + /* Find a free task pool job. */ + freeIndex = IotStaticMemory_FindFree( _pInUseTaskPoolJobs, + IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ); + + if( freeIndex != -1 ) + { + pNewJob = &( _pTaskPoolJobs[ freeIndex ] ); + } + } + + return pNewJob; + } + +/*-----------------------------------------------------------*/ + + void IotTaskPool_FreeJob( void * ptr ) + { + /* Return the in-use task pool job. */ + IotStaticMemory_ReturnInUse( ptr, + _pTaskPoolJobs, + _pInUseTaskPoolJobs, + IOT_TASKPOOL_JOBS_RECYCLE_LIMIT, + sizeof( _taskPoolJob_t ) ); + } + +/*-----------------------------------------------------------*/ + + void * IotTaskPool_MallocTimerEvent( size_t size ) + { + int32_t freeIndex = -1; + void * pNewTimerEvent = NULL; + + /* Check size argument. */ + if( size == sizeof( _taskPoolTimerEvent_t ) ) + { + /* Find a free task pool timer event. */ + freeIndex = IotStaticMemory_FindFree( _pInUseTaskPoolTimerEvents, + IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ); + + if( freeIndex != -1 ) + { + pNewTimerEvent = &( _pTaskPoolTimerEvents[ freeIndex ] ); + } + } + + return pNewTimerEvent; + } + +/*-----------------------------------------------------------*/ + + void IotTaskPool_FreeTimerEvent( void * ptr ) + { + /* Return the in-use task pool timer event. */ + IotStaticMemory_ReturnInUse( ptr, + _pTaskPoolTimerEvents, + _pInUseTaskPoolTimerEvents, + IOT_TASKPOOL_JOBS_RECYCLE_LIMIT, + sizeof( _taskPoolTimerEvent_t ) ); + } + +/*-----------------------------------------------------------*/ + +#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */ diff --git a/bsp/aws_libraries/c_sdk/standard/https/include/iot_https_client.h b/bsp/aws_libraries/c_sdk/standard/https/include/iot_https_client.h new file mode 100644 index 0000000..486e0e5 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/https/include/iot_https_client.h @@ -0,0 +1,898 @@ +/* + * FreeRTOS HTTPS Client V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_https_client.h + * @brief User-facing functions of the FreeRTOS HTTPS Client library. + */ + +#ifndef IOT_HTTPS_CLIENT_H_ +#define IOT_HTTPS_CLIENT_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* HTTP types include. */ +#include "types/iot_https_types.h" + +/** + * @functions_page{https_client,HTTPS Client Library} + * @functions_brief{https_client} + * - @function_name{https_client_function_init} + * @function_brief{https_client_function_init} + * - @function_name{https_client_function_cleanup} + * @function_brief{https_client_function_cleanup} + * - @function_name{https_client_function_disconnect} + * @function_brief{https_client_function_disconnect} + * - @function_name{https_client_function_connect} + * @function_brief{https_client_function_connect} + * - @function_name{https_client_function_initializerequest} + * @function_brief{https_client_function_initializerequest} + * - @function_name{https_client_function_addheader} + * @function_brief{https_client_function_addheader} + * - @function_name{https_client_function_writerequestbody} + * @function_brief{https_client_function_writerequestbody} + * - @function_name{https_client_function_sendsync} + * @function_brief{https_client_function_sendsync} + * - @function_name{https_client_function_sendasync} + * @function_brief{https_client_function_sendasync} + * - @function_name{https_client_function_cancelrequestasync} + * @function_brief{https_client_function_cancelrequestasync} + * - @function_name{https_client_function_cancelresponseasync} + * @function_brief{https_client_function_cancelresponseasync} + * - @function_name{https_client_function_readresponsestatus} + * @function_brief{https_client_function_readresponsestatus} + * - @function_name{https_client_function_readcontentlength} + * @function_brief{https_client_function_readcontentlength} + * - @function_name{https_client_function_readheader} + * @function_brief{https_client_function_readheader} + * - @function_name{https_client_function_readresponsebody} + * @function_brief{https_client_function_readresponsebody} + */ + +/** + * @page https_client_function_init IotHttpsClient_Init + * @snippet this declare_https_client_init + * @copydoc IotHttpsClient_Init + * @page https_client_function_cleanup IotHttpsClient_Cleanup + * @snippet this declare_https_client_cleanup + * @copydoc IotHttpsClient_Cleanup + * @page https_client_function_disconnect IotHttpsClient_Disconnect + * @snippet this declare_https_client_disconnect + * @copydoc IotHttpsClient_Disconnect + * @page https_client_function_connect IotHttpsClient_Connect + * @snippet this declare_https_client_connect + * @copydoc IotHttpsClient_Connect + * @page https_client_function_initializerequest IotHttpsClient_InitializeRequest + * @snippet this declare_https_client_initializerequest + * @copydoc IotHttpsClient_InitializeRequest + * @page https_client_function_addheader IotHttpsClient_AddHeader + * @snippet this declare_https_client_addheader + * @copydoc IotHttpsClient_AddHeader + * @page https_client_function_writerequestbody IotHttpsClient_WriteRequestBody + * @snippet this declare_https_client_writerequestbody + * @copydoc IotHttpsClient_WriteRequestBody + * @page https_client_function_sendsync IotHttpsClient_SendSync + * @snippet this declare_https_client_sendsync + * @copydoc IotHttpsClient_SendSync + * @page https_client_function_sendasync IotHttpsClient_SendAsync + * @snippet this declare_https_client_sendasync + * @copydoc IotHttpsClient_SendAsync + * @page https_client_function_cancelrequestasync IotHttpsClient_CancelRequestAsync + * @snippet this declare_https_client_cancelrequestasync + * @copydoc IotHttpsClient_CancelRequestAsync + * @page https_client_function_cancelresponseasync IotHttpsClient_CancelResponseAsync + * @snippet this declare_https_client_cancelresponseasync + * @copydoc IotHttpsClient_CancelResponseAsync + * @page https_client_function_readresponsestatus IotHttpsClient_ReadResponseStatus + * @snippet this declare_https_client_readresponsestatus + * @copydoc IotHttpsClient_ReadResponseStatus + * @page https_client_function_readcontentlength IotHttpsClient_ReadContentLength + * @snippet this declare_https_client_readcontentlength + * @copydoc IotHttpsClient_ReadContentLength + * @page https_client_function_readheader IotHttpsClient_ReadHeader + * @snippet this declare_https_client_readheader + * @copydoc IotHttpsClient_ReadHeader + * @page https_client_function_readresponsebody IotHttpsClient_ReadResponseBody + * @snippet this declare_https_client_readresponsebody + * @copydoc IotHttpsClient_ReadResponseBody + */ + + +/** + * @brief One-time initialization of the IoT HTTPS Client library. + * + * This must be called once before calling any API. + * + * @warning No thread safety guarantees are provided for this function. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the HTTPS library is successfully initialized. + * + * @see @ref https_client_function_cleanup + */ +/* @[declare_https_client_init] */ +IotHttpsReturnCode_t IotHttpsClient_Init( void ); +/* @[declare_https_client_init] */ + +/** + * @brief One time clean up of the IoT HTTPS Client library. + * + * This function frees resources taken in in @ref https_client_function_init. It should be called after + * all HTTPS Connections have been close. HTTPS Connections are represented by #IotHttpsConnectionHandle_t and returned + * by @ref https_client_function_connect. After this function returns @ref https_client_function_init + * must be called again to use this library. + * + * @warning No thread safety guarantees are provided for this function. + */ +/* @[declare_https_client_cleanup] */ +void IotHttpsClient_Cleanup( void ); +/* @[declare_https_client_cleanup] */ + +/** + * @cond DOXYGEN_IGNORE + * + * Backward compatibility function for one time clean up of the IoT HTTPS Client library. + */ +#define IotHttpsClient_Deinit IotHttpsClient_Cleanup +/** @endcond */ + +/** + * @brief Explicitly connect to the HTTPS server given the connection configuration pConnConfig. + * + * This routine blocks until the connection is complete. + * + * This function opens a new HTTPS connection with the server specified in #IotHttpsConnectionInfo_t.pAddress. The + * connection is established by default on top of TLS over TCP. If the application wants to connect over TCP only, then + * it must add the @ref IOT_HTTPS_IS_NON_TLS_FLAG to #IotHttpsConnectionInfo_t.flags. This is done at the application's + * own risk. + * + * When the the last HTTP request sent on the connection is specified as persistent and we want to close the connection, + * @ref https_client_function_disconnect must always be called on the valid #IotHttpsConnectionHandle_t. For more + * information about persistent HTTP connections please see #IotHttpsRequestInfo_t.isNonPersistent. + * + * If the application receives a #IOT_HTTPS_NETWORK_ERROR from @ref https_client_function_sendsync or + * @ref https_client_function_sendasync, on a persistent request, then the connection will be closed. The application + * can call this this function again to reestablish the connection. + * + * If pConnHandle passed in is valid and represents a previously opened connection, this function will disconnect, + * then reconnect. Before calling this function make sure that all outstanding requests on the connection have + * completed. Outstanding requests are completed when @ref https_client_function_sendsync has returned or when + * #IotHttpsClientCallbacks_t.responseCompleteCallback has been invoked for requests scheduled with + * @ref https_client_function_sendasync. + * + * Keep in mind that many HTTP servers will close a connection, if it does not receive any requests, after a certain + * amount of time. Many web servers may close the connection after 30-60 seconds. The state of pConnHandle will still be + * in a connected state if this happens. If the server closed the connection, then the next request on the connection + * will fail to send with a network error and the connection will move to a closed state. + * + * Also keep in mind that some HTTP servers do not accept persistent requests. Some HTTP servers will ignore that the + * request contains the "Connection: keep-alive" header and close the connection immediately after sending the response. + * If this happens, then the next request on the connection will fail to send with a network error and the connection + * will close. + * + * To know if the connection was closed by the server, debug logging can be turned on to view the network error code + * received. Debug logging is configured when @ref IOT_LOG_LEVEL_HTTPS is set to @ref IOT_LOG_DEBUG in iot_config.h. + * + * #IotHttpsConnectionInfo_t.userBuffer is used to store the internal context and therefore, multiple threads + * calling this function simultaneously must ensure to use different #IotHttpsConnectionInfo_t objects. + * + * See @ref connectionUserBufferMinimumSize for information about the user buffer configured in + * #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle. + * + * @param[out] pConnHandle - Handle returned representing the open connection. NULL if the function failed. + * @param[in] pConnInfo - Configurations for the HTTPS connection. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the connection was successful. + * - #IOT_HTTPS_CONNECTION_ERROR if the connection failed. + * - #IOT_HTTPS_INVALID_PARAMETER if NULL parameters were passed in. + * - #IOT_HTTPS_INTERNAL_ERROR if there was an error creating resources for the connection context. + * + * Example + * @code{c} + * // An initialized network interface. + * IotNetworkInterface_t* pNetworkInterface; + * + * // Parameters to HTTPS Client connect. + * IotHttpsConnectionInfo_t connInfo = IOT_HTTPS_CONNECTION_INFO_INITIALIZER; + * IotHttpsConnectionHandle_t connHandle = IOT_HTTPS_CONNECTION_HANDLE_INITIALIZER; + * uint8_t* pConnUserBuffer = (uint8_t*)malloc(connectionUserBufferMinimumSize); + * + * // Set the connection configuration information. + * connInfo.pAddress = "www.amazon.com"; + * connInfo.addressLen = strlen("www.amazon.com"); + * connInfo.port = 443; + * connInfo.flags = 0; + * connInfo.pAlpnProtocols = "alpnproto0,alpnproto1" + * connInfo.pCaCert = HTTPS_TRUSTED_ROOT_CA; // defined elsewhere + * connInfo.caCertLen = sizeof( HTTPS_TRUSTED_ROOT_CA ); + * connInfo.userBuffer.pBuffer = pConnUserBuffer; + * connInfo.userBuffer.bufferLen = connectionUserBufferMinimumSize; + * connInfo.pClientCert = TLS_CLIENT_CERT; + * connInfo.clientCertLen = sizeof( TLS_CLIENT_CERT ); + * connInfo.pPrivateKey = TLS_CLIENT_PRIV_KEY; + * connInfo.privateKeyLen = sizeof( TLS_CLIENT_PRIV_KEY ); + * connInfo.pNetworkInterface = pNetworkInterface; + * + * IotHttpsReturnCode_t returnCode = IotHttpsClient_Connect(&connHandle, &connInfo); + * if( returnCode == IOT_HTTPS_OK ) + * { + * // Do something with the HTTPS connection... + * + * // Clean up and close the HTTPS connection once it's no longer needed. + * IotHttpsClient_Disconnect(connHandle); + * } + * @endcode + */ +/* @[declare_https_client_connect] */ +IotHttpsReturnCode_t IotHttpsClient_Connect( IotHttpsConnectionHandle_t * pConnHandle, + IotHttpsConnectionInfo_t * pConnInfo ); +/* @[declare_https_client_connect] */ + +/** + * @brief Disconnect from the HTTPS server given the connection handle connHandle. + * + * This routine blocks until the disconnect is complete. + * If the connection handle is not valid, the behavior is undefined. + * If the connection handle is already disconnected then this routine will return IOT_HTTPS_OK. + * + * When the HTTP request is specified as persistent and we want to close the connection, this API must always + * be called on the valid #IotHttpsConnectionHandle_t. For more information about persistent HTTP connections please see + * #IotHttpsRequestInfo_t.isNonPersistent. + * + * When the HTTP request is specified as non-persistent, by setting #IotHttpsRequestInfo_t.isNonPersistent to true, then + * this function will be called automatically on the valid IotHttpsConnectionHandle_t after receiving the response. There + * is no need to call this function in case of a non-persistent request. + * + * This will put the internal connection state in #IotHttpsConnectionHandle_t to disconnected. + * + * If the application receives a #IOT_HTTPS_NETWORK_ERROR from @ref https_client_function_sendsync or + * @ref https_client_function_sendasync, on a persistent request, that does not always mean the connection has been + * disconnected. This function MUST be called to close the connection and clean up connection resources taken by + * #IotHttpsConnectionHandle_t. + * + * This function will cancel all pending requests on the connection. If a request currently being sent on the connection, + * then this function will disconnect the connection, but it will not free network connection resource and will return + * with #IOT_HTTPS_BUSY. The application may call this function again later to try again. + * + * Multiple threads must not call this function for the same #IotHttpsConnectionHandle_t. Multiple threads + * can call this function for different #IotHttpsConnectionHandle_t. Make sure that all request/responses + * have finished on the connection before calling this API. Outstanding requests are completed when + * @ref https_client_function_sendsync has returned or when #IotHttpsClientCallbacks_t.responseCompleteCallback + * has been invoked for requests scheduled with @ref https_client_function_sendasync. + * + * @param[in] connHandle - Valid handle representing an open connection. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the disconnect was successful + * - #IOT_HTTPS_INVALID_PARAMETER if NULL parameters were passed in. + * - #IOT_HTTPS_BUSY if the connection is in use and cannot be destroyed. + */ +/* @[declare_https_client_disconnect] */ +IotHttpsReturnCode_t IotHttpsClient_Disconnect( IotHttpsConnectionHandle_t connHandle ); +/* @[declare_https_client_disconnect] */ + +/** + * @brief Initializes the request by adding a formatted Request-Line to the start of HTTPS request header buffer. + * + * This function will initialize the HTTP request context by setting where to write the next headers to the start + * of the configured header buffer in #IotHttpsRequestInfo_t.userBuffer. + * + * The Request-Line will be added to the start of the headers space in #IotHttpsRequestInfo_t.userBuffer. + * The header space follows the request context in the user buffer. See @ref requestUserBufferMinimumSize for more + * information on sizing the #IotHttpsRequestInfo_t.userBuffer so that this function does not fail. + * + * The Request-Line generated is of the following format: + * + * @code + * method path version\r\n + * @endcode + * + * Example: + * + * @code + * GET /path/to/item.file?possible_query HTTP/1.1\r\n + * @endcode + * + * The initial required headers are also added to the #IotHttpsRequestInfo_t.userBuffer. These headers are User-Agent + * and Host. The User-Agent value is configured in iot_config.h using IOT_HTTPS_USER_AGENT. The Host value is the DNS + * resolvable server address. + * + * @param[out] pReqHandle - request handle representing the internal request context is returned. NULL if the function failed. + * @param[in] pReqInfo - HTTPS request information. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the Request-Line was successfully added to the header space in #IotHttpsRequestInfo_t.userBuffer. + * - #IOT_HTTPS_INSUFFICIENT_MEMORY if the Request-Line generated exceeds #IotHttpsUserBuffer_t.bufferLen in #IotHttpsRequestInfo_t.userBuffer. + * - #IOT_HTTPS_INVALID_PARAMETER for NULL parameters. + * - #IOT_HTTPS_INTERNAL_ERROR for library internal errors. + * + * Example + * @code{c} + * // An initialized network interface. + * IotNetworkInterface_t* pNetworkInterface; + * + * // Parameters to HTTPS Client request initialization. + * IotHttpsRequestInfo_t reqInfo = IOT_HTTPS_REQUEST_INFO_INITIALIZER; + * IotHttpsRequestHandle_t reqHandle = IOT_HTTPS_REQUEST_HANDLE_INITIALIZER; + * IotHttpsSyncInfo_t syncInfo = IOT_HTTPS_SYNC_INFO_INITIALIZER; + * // Leave some room for extra headers. + * uint32_t userBufferSize = requestUserBufferMinimumSize + 256; + * uint8_t* pRequestUserBuffer = (uint8_t*)malloc(userBufferSize); + * + * // Set the synchronous information. + * syncInfo.pBody = PREDEFINED_BODY_BUFFER; + * syncInfo.bodyLen = PREDEFINED_BODY_BUFFER_LEN; + * + * // Set the request configuration information. + * reqInfo.pPath = "/path_to_item?query_maybe"; + * reqInfo.pPathLen = strlen("/path_to_item?query_maybe"); + * reqInfo.method = IOT_HTTPS_METHOD_GET; + * reqInfo.pHost = "www.amazon.com"; + * reqInfo.hostLen = strlen("www.amazon.com"); + * reqInfo.isNonPersistent = false; + * reqInfo.userBuffer.pBuffer = pRequestUserBuffer; + * reqInfo.userBuffer.bufferLen = userBufferSize; + * reqInfo.isAsync = false; + * reqInfo.pSyncInfo = &syncInfo; + * + * IotHttpsReturnCode_t returnCode = IotHttpsClient_InitializeRequest(&reqHandle, &reqInfo); + * if( returnCode == IOT_HTTPS_OK ) + * { + * // Handle the error. + * } + * @endcode + */ +/* @[declare_https_client_initializerequest] */ +IotHttpsReturnCode_t IotHttpsClient_InitializeRequest( IotHttpsRequestHandle_t * pReqHandle, + IotHttpsRequestInfo_t * pReqInfo ); +/* @[declare_https_client_initializerequest] */ + +/** + * @brief Add a header to the current HTTPS request represented by reqHandle. + * + * The header line is appended to the request header buffer space in #IotHttpsRequestInfo_t.userBuffer. + * Please see #requestUserBufferMinimumSize for information about sizing the #IotHttpsRequestInfo_t.userBuffer so + * that this function does not fail. + * + * Header lines are appended in the following format: + * @code + * header_field_name: header_value\r\n" + * @endcode + * Example: + * @code + * Range: bytes=1024-2047\r\n + * @endcode + * The last header line must be followed by a "\r\n" to separate the last header line from + * the entity body. These 2 characters are accounted for in #requestUserBufferMinimumSize. + * + * The remaining length, after the header is added, is printed to the system configured standard debug output when + * @ref IOT_LOG_LEVEL_HTTPS is set to @ref IOT_LOG_DEBUG in iot_config.h. + * + * For an asynchronous request, this function can be invoked before the request is sent with + * @ref https_client_function_sendasync, or during #IotHttpsClientCallbacks_t.appendHeaderCallback. It is + * recommended to invoke this function in #IotHttpsClientCallbacks_t.appendHeaderCallback. + * + * Asynchronous Example + * @code{c} + * void _applicationDefined_appendHeaderCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle) + * { + * ... + * char date_in_iso8601[17] = { 0 }; + * GET_DATE_IN_ISO8601(date_in_iso8601); + * const char amz_date_header[] = "x-amz-date"; + * uint32_t amz_date_header_length = strlen(amz_date_header); + * IotHttpsClient_AddHeader(reqHandle, amz_date_header, amz_date_header_length, date_in_iso8601, strlen(date_in_iso8601)); + * ... + * } + * @endcode + * + * For a synchronous request, if extra headers are desired to be added, this function must be invoked before + * @ref https_client_function_sendsync. + * Synchronous Example + * @code{c} + * ... + * char date_in_iso8601[17] = { 0 }; + * GET_DATE_IN_ISO8601(date_in_iso8601); + * const char amz_date_header[] = "x-amz-date"; + * uint32_t amz_date_header_length = strlen(amz_date_header); + * IotHttpsClient_AddHeader(reqHandle, amz_date_header, amz_date_header_length, date_in_iso8601, strlen(date_in_iso8601)); + * ... + * IotHttpsClient_SendSync(connHandle, reqHandle, &respHandle, &respInfo, timeout); + * ... + * @endcode + * + * The following header fields are automatically added to the request header buffer and must NOT be added again with + * this routine: + * - Connection: - This header is added to the request when the headers are being sent on the network. + * - User-agent: - This header is added during @ref https_client_function_initializerequest + * - Host: - This header is added during @ref https_client_function_initializerequest + * - Content-Length: - This header is added to the request when the headers are being sent on the network. + * + * The reqHandle is not thread safe. If two threads have the same reqHandle and attempt to add headers at the same + * time, garbage strings may be written to the reqHandle. + * + * @param[in] reqHandle - HTTPS request to write the header line to. + * @param[in] pName - String header field name to write. + * @param[in] nameLen - The length of the header name to write. + * @param[in] pValue - https header value buffer pointer. Do not include token name. + * @param[in] valueLen - length of header value to write. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the header line was successfully added to the header space in #IotHttpsRequestInfo_t.userBuffer. + * - #IOT_HTTPS_INSUFFICIENT_MEMORY if the header line cannot fit into the header buffer. + * - #IOT_HTTPS_INVALID_PARAMETER for NULL parameters or if an attempt to add automatically added headers is made. + */ +/* @[declare_https_client_addheader] */ +IotHttpsReturnCode_t IotHttpsClient_AddHeader( IotHttpsRequestHandle_t reqHandle, + char * pName, + uint32_t nameLen, + char * pValue, + uint32_t valueLen ); +/* @[declare_https_client_addheader] */ + +/** + * @brief Writes the request body to the network for the request represented by reqHandle. + * + * This function is intended to be used by an asynchronous request. It must be called within the + * #IotHttpsClientCallbacks_t.writeCallback. + * + * In HTTP/1.1 the headers are sent on the network first before any body can be sent. The auto-generated header + * Content-Length is taken from the len parameter and sent first before the data in parameter pBuf is sent. + * This library does not support Transfer-Encoding: chunked or other requests where the Content-Length is unknown, so + * this function cannot be called more than once in #IotHttpsClientCallbacks_t.writeCallback for an HTTP/1.1 request. + * + * isComplete must always be set to 1 in this current version of the HTTPS client library. + * + * If there are network errors in sending the HTTP headers, then the #IotHttpsClientCallbacks_t.errorCallback will be + * invoked following a return from the #IotHttpsClientCallbacks_t.writeCallback. + * + * Example Asynchronous Code + * @code{c} + * void applicationDefined_writeCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle) + * { + * ... + * char * writeData[1024]; + * IotHttpsClient_WriteRequestBody(reqHandle, writeData, 1024, 1); + * ... + * } + * @endcode + * + * @param[in] reqHandle - identifier of the connection. + * @param[in] pBuf - client write data buffer pointer. + * @param[in] len - length of data to write. + * @param[in] isComplete - This parameter parameter must be set to 1. + * + * @return one of the following: + * - #IOT_HTTPS_OK if write successfully, failure code otherwise. + * - #IOT_HTTPS_MESSAGE_FINISHED if this function is called a second time with the same reqHandle. + * - #IOT_HTTPS_NOT_SUPPORTED if isComplete is set to 0. + * - #IOT_HTTPS_INVALID_PARAMETER if this API is used for a synchronous request. + * - #IOT_HTTPS_NETWORK_ERROR if there was an error sending the headers or body on the network. + * - Please see #IotHttpsReturnCode_t for other failure codes. + */ +/* @[declare_https_client_writerequestbody] */ +IotHttpsReturnCode_t IotHttpsClient_WriteRequestBody( IotHttpsRequestHandle_t reqHandle, + uint8_t * pBuf, + uint32_t len, + int isComplete ); +/* @[declare_https_client_writerequestbody] */ + +/** + * @brief Synchronous send of the HTTPS request. + * + * This function blocks waiting for the entirety of sending the request and receiving the response. + * + * If #IotHttpsRequestInfo_t.isNonPersistent is set to true, then the connection will disconnect, close, and clean all + * taken resources automatically after receiving the first response. + * + * See @ref connectionUserBufferMinimumSize for information about the user buffer configured in + * #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle. + * + * To retrieve the response body applications must directly refer #IotHttpsSyncInfo_t.pBody configured in #IotHttpsRequestInfo_t.u. + * + * If the response body does not fit in the configured #IotHttpsSyncInfo_t.pBody, then this function will return with error + * #IOT_HTTPS_MESSAGE_TOO_LARGE. To avoid this issue, the application needs to determine beforehand how large the file + * to download is. This can be done with a HEAD request first, then extracting the "Content-Length" with + * @ref https_client_function_readcontentlength. This could also be done with a GET request with the header + * "Range: bytes=0-0", then extracting the "Content-Range" with @ref https_client_function_readheader. Keep in mind that + * not all HTTP servers support Partial Content responses. + * + * Once a the file size is known, the application can initialize the request with a large + * enough buffer or the application can make a partial content request with the header + * "Range: bytes=N-M", where N is the starting byte requested and M is the ending byte requested. + * + * The response headers as received from the network will be stored in the header buffer space in + * #IotHttpsResponseInfo_t.userBuffer. If the configured #IotHttpsResponseInfo_t.userBuffer is too small + * to fit the headers received, then headers that don't fit will be thrown away. Please see + * #responseUserBufferMinimumSize for information about sizing the #IotHttpsResponseInfo_t.userBuffer. + * To receive feedback on headers discarded, debug logging must be turned on in iot_config.h by setting + * @ref IOT_LOG_LEVEL_HTTPS to @ref IOT_LOG_DEBUG. + * + * Multiple threads must not call this function for the same #IotHttpsRequestHandle_t. Multiple threads can call this + * function for a different #IotHttpsRequestHandle_t, even on the same #IotHttpsConnectionHandle_t. An application must + * wait util a request is fully sent, before scheduling it again. A request is fully sent when this function has returned. + * + * @param[in] connHandle - Handle from an HTTPS connection created with @ref https_client_function_connect. + * @param[in] reqHandle - Handle from a request created with @ref https_client_function_initializerequest. + * @param[out] pRespHandle - HTTPS response handle resulting from a successful send and receive. + * @param[in] pRespInfo - HTTP response configuration information. + * @param[in] timeoutMs - Timeout waiting for the sync request to finish. Set this to 0 to wait forever. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the request was sent and the response was received successfully. + * - #IOT_HTTPS_MESSAGE_TOO_LARGE if the response cannot fit in the configured struct IotHttpsRequestHandle.userBuffer.pBuffer and struct IotHttpsRequestHandle.u.pSyncInfo.pRespData. + * - #IOT_HTTPS_CONNECTION_ERROR if the connection failed. + * - #IOT_HTTPS_INVALID_PARAMETER if there are NULL parameters or the request is asynchronous. + * - #IOT_HTTPS_NETWORK_ERROR if there was an error sending the data on the network. + * - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the HTTP response. + * - #IOT_HTTPS_TIMEOUT_ERROR if the timeoutMs is reached when waiting for a response to the request. + */ +/* @[declare_https_client_sendsync] */ +IotHttpsReturnCode_t IotHttpsClient_SendSync( IotHttpsConnectionHandle_t connHandle, + IotHttpsRequestHandle_t reqHandle, + IotHttpsResponseHandle_t * pRespHandle, + IotHttpsResponseInfo_t * pRespInfo, + uint32_t timeoutMs ); +/* @[declare_https_client_sendsync] */ + +/** + * @brief Asynchronous send of the the HTTPS request. + * + * This function will invoke, as needed, each of the non-NULL callbacks configured in #IotHttpsAsyncInfo_t.callbacks + * when the scheduled asynchronous request is progress. Please see #IotHttpsClientCallbacks_t for information on each of + * the callbacks. + * + * After this API is executed, the scheduled async response will store the response headers as received from + * the network, in the header buffer space configured in #IotHttpsResponseInfo_t.userBuffer. If the + * configured #IotHttpsResponseInfo_t.userBuffer is too small to fit the headers received, then headers that don't + * fit will be thrown away. Please see #responseUserBufferMinimumSize for information about sizing the + * #IotHttpsResponseInfo_t.userBuffer. + * + * If #IotHttpsRequestInfo_t.isNonPersistent is set to true, then the connection will disconnect, close, and clean all + * taken resources automatically after receiving the first response. + * + * See @ref connectionUserBufferMinimumSize for information about the user buffer configured in + * #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle. + * + * A #IotHttpsRequestHandle_t cannot be schedule again or reused until the request has finished sending. The request + * has safely finished sending once #IotHttpsClientCallbacks_t.readReadyCallback is invoked. After the + * #IotHttpsClientCallbacks_t.readReadyCallback is invoked the #IotHttpsRequestInfo_t.userBuffer can freed, + * modified, or reused. + * + * @param[in] connHandle - Handle from an HTTPS connection. + * @param[in] reqHandle - Handle from a request created with IotHttpsClient_initialize_request. + * @param[out] pRespHandle - HTTPS response handle. + * @param[in] pRespInfo - HTTP response configuration information. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the request was sent and the response was received successfully. + * - #IOT_HTTPS_MESSAGE_TOO_LARGE if the response cannot fit in the configured + * IotHttpsRequestHandle_t.response_message.headers and IotHttpsRequestHandle_t.response_message.body. + * - #IOT_HTTPS_CONNECTION_ERROR if the connection failed. + * - #IOT_HTTPS_FATAL if there was a grave error with the last async job finishing. + * - #IOT_HTTPS_ASYNC_SCHEDULING_ERROR if there was an error scheduling the asynchronous request. + * - #IOT_HTTPS_INTERNAL_ERROR if there was an internal error with starting an asynchronous request servicing task. + * - #IOT_HTTPS_INVALID_PARAMETER if there were NULL parameters or the request passed in was a synchronous type. + * + */ +/* @[declare_https_client_sendasync] */ +IotHttpsReturnCode_t IotHttpsClient_SendAsync( IotHttpsConnectionHandle_t connHandle, + IotHttpsRequestHandle_t reqHandle, + IotHttpsResponseHandle_t * pRespHandle, + IotHttpsResponseInfo_t * pRespInfo ); +/* @[declare_https_client_sendasync] */ + +/** + * @brief Cancel an Asynchronous request. + * + * This will stop an asynchronous request. When an asynchronous request is stopped it will not proceed to do any of + * the following: send headers, send body, receive headers, or receive body. This depends on where in the process + * the request is. For example, if the request is cancelled after sending the headers, then it will not attempt tp + * send the body. A cancelled return code will be returned to the application. + * + * If this is called before the scheduled asynchronous request actually runs, then request will not be sent. + * If this is called during any of the asynchronous callbacks, then the library will stop processing the request when + * the callback returns. This is useful for any error conditions, found during the asynchronous callbacks, where the + * application wants to stop the rest of the request processing. + * + * If the asynchronous request stops processing, the buffers in #IotHttpsRequestInfo_t.userBuffer can be safely freed, + * modified, or reused, only once #IotHttpsClientCallbacks_t.readReadyCallback is invoked. + * + * Example Asynchronous Code + * @code{c} + * void _applicationDefined_appendHeaderCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle) + * { + * char token[MAX_TOKEN_LENGTH] = { 0 } + * int len = MAX_TOKEN_LENGTH; + * int status = gen_auth_token(token, &len); + * if( status == GEN_TOKEN_FAIL) + * { + * IotHttpsClient_CancelRequestAsync(reqHandle); + * } + * ... + * } + * + * void _applicationDefined_writeCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle) + * { + * if( application_data_get(writeBuffer, writeBufferLen) == GEN_TOKEN_FAIL) + * { + * IotHttpsClient_CancelRequestAsync(reqHandle); + * } + * ... + * } + * @endcode + * + * @param[in] reqHandle - Request handle associated with the request. + * + * @return One of the following: + * - IOT_HTTPS_OK if the request was successfully cancelled. + */ +/* @[declare_https_client_cancelrequestasync] */ +IotHttpsReturnCode_t IotHttpsClient_CancelRequestAsync( IotHttpsRequestHandle_t reqHandle ); +/* @[declare_https_client_cancelrequestasync] */ + +/** + * @brief Cancel an Asynchronous response. + * + * This will stop an asynchronous response. When an asynchronous response is stopped it will not proceed to do any of + * the following: send headers, send body, receive headers, or receive body. This depends on where in the process + * the response is. For example, if the response is cancelled after receiving the headers, then it will not attempt tp + * receive the body. A cancelled return code will be returned to the application. + * + * If this is called during ANY of the asynchronous callbacks, then the library will stop processing the response when + * the callback returns. This is useful for any error conditions, found during the asynchronous callbacks, where the + * application wants to stop the rest of the response processing. + * + * If the asynchronous response stops processing, the buffers configured in #IotHttpsResponseInfo_t.userBuffer can + * be freed, modified, or reused only after the #IotHttpsClientCallbacks_t.responseCompleteCallback in invoked. + * + * Example Asynchronous Code + * @code{c} + * + * void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status) + * { + * ... + * if (status != IOT_HTTPS_STATUS_OK) + * { + * IotHttpsClient_CancelResponseAsync(NULL, respHandle); + * } + * ... + * } + * @endcode + * + * @param[in] respHandle - Response handle associated with the response. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the response was successfully cancelled. + */ +/* @[declare_https_client_cancelresponseasync] */ +IotHttpsReturnCode_t IotHttpsClient_CancelResponseAsync( IotHttpsResponseHandle_t respHandle ); +/* @[declare_https_client_cancelresponseasync] */ + +/** + * @brief Retrieve the HTTPS response status. + * + * The HTTP response status code is contained in the Status-Line of the response header buffer configured in + * #IotHttpsResponseInfo_t.userBuffer. It is the first line of a standard HTTP response message. If the response + * Status-Line could not fit into #IotHttpsResponseInfo_t.userBuffer, then this function will return an error code. + * Please see #responseUserBufferMinimumSize for information about sizing the #IotHttpsResponseInfo_t.userBuffer. + * + * This routine can be used for both a synchronous and asynchronous response. + * + * Example Synchronous Code + * @code{c} + * ... + * IotHttpsClient_SendSync(connHandle, reqHandle, &respHandle, &respInfo, timeout); + * uint16_t status = 0; + * IotHttpsClient_ReadResponseStatus(respHandle, &status); + * if (status != IOT_HTTPS_STATUS_OK) + * { + * // Handle server response status. + * } + * ... + * @endcode + * + * For an asynchronous response the response status is the status parameter in + * #IotHttpsClientCallbacks_t.readReadyCallback and #IotHttpsClientCallbacks_t.responseCompleteCallback. The application + * should refer to that instead of using this function. + * Example Asynchronous Code + * @code + * void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status) + * { + * ... + * if (status != IOT_HTTPS_STATUS_OK) + * { + * // Handle error server response status. + * } + * ... + * } + * @endcode + * + * @param[in] respHandle - Unique handle representing the HTTPS response. + * @param[out] pStatus - Integer status returned by the server. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the response status was successfully read into *status. + * - #IOT_HTTPS_INVALID_PARAMETER for NULL parameters. + * - #IOT_HTTPS_NOT_FOUND if the HTTP response status was not found in the header buffer. + */ +/* @[declare_https_client_readresponsestatus] */ +IotHttpsReturnCode_t IotHttpsClient_ReadResponseStatus( IotHttpsResponseHandle_t respHandle, + uint16_t * pStatus ); +/* @[declare_https_client_readresponsestatus] */ + +/** + * @brief Retrieve the HTTPS response content length. + * + * If the "Content-Length" header is available in #IotHttpsResponseInfo_t.userBuffer, this routine extracts that + * value. In some cases the "Content-Length" header is not available. This could be because the server sent a multi-part + * encoded response (For example, "Transfer-Encoding: chunked") or the "Content-Length" header was far down in the list + * of response headers and could not fit into the header buffer configured in #IotHttpsResponseInfo_t.userBuffer. + * Please see #responseUserBufferMinimumSize for information about sizing the #IotHttpsResponseInfo_t.userBuffer. + * + * In the asynchronous request process, the Content-Length is not available until the + * #IotHttpsClientCallbacks_t.readReadyCallback. Before the #IotHttpsClientCallbacks_t.readReadyCallback is invoked, the + * headers are read into as much as can fit in in the header buffer space of #IotHttpsResponseInfo_t.userBuffer. + * Example Asynchronous Code + * @code{c} + * void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status) + * { + * uint8_t * readBuffer = NULL; + * uint32_t contentLength = 0; + * IotHttpsClient_ReadContentLength(respHandle, &contentLength); + * readBuffer = (uint8_t*)malloc(contentLength); + * ... + * } + * @endcode + * + * In a synchronous request process, the Content-Length is available after @ref https_client_function_sendsync has + * returned successfully. + * Example Synchronous Code + * @code{c} + * ... + * IotHttpsClient_SendSync(connHandle, reqHandle, &respHandle, &respInfo, timeout); + * uint32_t contentLength = 0; + * IotHttpsClient_ReadContentLength(respHandle, &contentLength); + * printf("Content-Length: %u", (unsigned int)contentLength); + * ... + * @endcode + * + * @param[in] respHandle - Unique handle representing the HTTPS response. + * @param[out] pContentLength - Integer content length from the Content-Length header from the server. If the content + * length is not found this will be 0. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the response body Content-Length was successfully read into contentLength. + * - #IOT_HTTPS_NOT_FOUND if the Content-Length header was not found in the header buffer. + * - #IOT_HTTPS_INVALID_PARAMETER if NULL parameters are passed in. + */ +/* @[declare_https_client_readcontentlength] */ +IotHttpsReturnCode_t IotHttpsClient_ReadContentLength( IotHttpsResponseHandle_t respHandle, + uint32_t * pContentLength ); +/* @[declare_https_client_readcontentlength] */ + +/** + * @brief Retrieve the header of interest from the response represented by respHandle. + * + * The response headers as received from the network will be stored in the header buffer space in + * #IotHttpsResponseInfo_t.userBuffer. If the configured #IotHttpsResponseInfo_t.userBuffer is too small to fit + * the headers received, then headers that don't fit will be thrown away. Please see #responseUserBufferMinimumSize for + * information about sizing the #IotHttpsResponseInfo_t.userBuffer. + * + * This routine parses the formatted HTTPS header lines in the header buffer for the header field name specified. If the + * header is not available, then #IOT_HTTPS_NOT_FOUND is returned. + * + * For an asynchronous response, this routine is to be called during the #IotHttpsClientCallbacks_t.readReadyCallback. + * Before the #IotHttpsClientCallbacks_t.readReadyCallback is invoked, the + * headers are read into as much as can fit in in the header buffer space of #IotHttpsResponseInfo_t.userBuffer. + * Example Asynchronous Code + * @code{c} + * void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status) + * { + * ... + * char valueBuf[64]; + * const char contentTypeName[] = "Content-Type"; + * uint32_t contentTypeNmeLength = strlen(contentTypeName); + * IotHttpsClient_ReadHeader(respHandle, contentTypeName, contentTypeNameLength, valueBuf, sizeof(valueBuf)); + * ... + * } + * @endcode + * + * For a syncrhonous response, this routine is to be called after @ref https_client_function_sendsync has + * returned successfully. + * Example Synchronous Code + * @code{c} + * ... + * IotHttpsClient_SendSync(&connHandle, reqHandle, &respHandle, &respInfo, timeout); + * char valueBuf[10]; + * const char contentTypeName[] = "Content-Type"; + * uint32_t contentTypeNmeLength = strlen(contentTypeName); + * IotHttpsClient_ReadHeader(respHandle, contentTypeName, contentTypeNmeLength, valueBuf, sizeof(valueBuf)); + * uint32_t length = strtoul(valueBuf, NULL, 10); + * ... + * @endcode + * + * @param[in] respHandle - Unique handle representing the HTTPS response. + * @param[in] pName - HTTPS Header field name we want the value of. This must be NULL terminated. + * @param[in] nameLen - The length of the name string. + * @param[out] pValue - Buffer to hold the HTTPS field's value. The returned value will be NULL terminated + * and therfore the buffer must be large enough to hold the terminating NULL character. + * @param[in] valueLen - The length of the value buffer. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the header's corresponding value was read into *pValue. + * - #IOT_HTTPS_NOT_FOUND if the header value was not found. + * - #IOT_HTTPS_INVALID_PARAMETER if the respHandle is not valid, there is no response saved or the handle does not exist. + * - #IOT_HTTPS_INSUFFICIENT_MEMORY if the value is too large to fit into *pValue. + */ +/* @[declare_https_client_readheader] */ +IotHttpsReturnCode_t IotHttpsClient_ReadHeader( IotHttpsResponseHandle_t respHandle, + char * pName, + uint32_t nameLen, + char * pValue, + uint32_t valueLen ); +/* @[declare_https_client_readheader] */ + +/** + * @brief Read the HTTPS response body from the network. + * + * This is intended to be used with an asynchronous response, this is to be invoked during the + * #IotHttpsClientCallbacks_t.readReadyCallback to read data directly from the network into pBuf. + * Example Asynchronous Code + * @code{c} + * void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsRequestHandle_t handle, IotHttpsReturnCode_t rc, uint16_t status) + * { + * ... + * char * myBuf = STORE_ADDRESS; + * uint32_t len = STORE_READ_SIZE; + * IotHttpsClient_ReadResponseBody(handle, myBuf, &len); + * ... + * } + * @endcode + * + * For a syncrhonous response, to retrieve the response body applications must directly refer to the memory configured + * to receive the response body: #IotHttpsSyncInfo_t.pBody in #IotHttpsResponseInfo_t.pSyncInfo. Otherwise this function + * will return an #IOT_HTTPS_INVALID_PARAMETER error code. This function is intended to read the response entity body + * from the network and the synchronous response process handles all of that in @ref https_client_function_sendsync. + * + * @param[in] respHandle - Unique handle representing the HTTPS response. + * @param[out] pBuf - Pointer to the response body memory location. This is not a char* because the body may have binary data. + * @param[in,out] pLen - The length of the response to read. This should not exceed the size of the buffer that we are reading into. This will be replace with the amount of data read upon return. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the response body was successfully retrieved. + * - #IOT_HTTPS_INVALID_PARAMETER if there are NULL parameters or if the response is a synchronous type. + * - #IOT_HTTPS_NETWORK_ERROR if there was an error sending the data on the network. + * - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the HTTP response. + */ +/* @[declare_https_client_readresponsebody] */ +IotHttpsReturnCode_t IotHttpsClient_ReadResponseBody( IotHttpsResponseHandle_t respHandle, + uint8_t * pBuf, + uint32_t * pLen ); +/* @[declare_https_client_readresponsebody] */ + +#endif /* IOT_HTTPS_CLIENT_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/https/include/iot_https_utils.h b/bsp/aws_libraries/c_sdk/standard/https/include/iot_https_utils.h new file mode 100644 index 0000000..638121b --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/https/include/iot_https_utils.h @@ -0,0 +1,95 @@ +/* + * FreeRTOS HTTPS Client V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_https_utils.h + * @brief User facing HTTPS Client library utilities. + */ + +#ifndef IOT_HTTPS_UTILS_H_ +#define IOT_HTTPS_UTILS_H_ + +#include "types/iot_https_types.h" + +/*-----------------------------------------------------------*/ + +/** + * @brief Retrieve the path from the input URL. + * + * This function retrieves the location and length of the path from within the + * input the URL. The query is not included in the length returned. + * + * The URL MUST start with "http://" or "https://" to find the path. + * + * For example, if the URL is: + * pUrl = "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff" + * + * *pPath = "/path/to/item.txt?optionalquery=stuff" + * *pPathLen = 17 + * + * @param[in] pUrl - URL string to parse. + * @param[in] urlLen - The length of the URL string input. + * @param[out] pPath - pointer within input url that the path starts at. + * @param[out] pPathLen - Length of the path. + * + * - #IOT_HTTPS_OK if the path was successfully parsed. + * - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the URL. + * - #IOT_HTTPS_NOT_FOUND if the path was not found. + */ +IotHttpsReturnCode_t IotHttpsClient_GetUrlPath( const char * pUrl, + size_t urlLen, + const char ** pPath, + size_t * pPathLen ); + +/** + * @brief Retrieve the Address from the input URL. + * + * This function retrieves the location and length of the address from within + * the input URL. The path and query are not included in the length returned. + * + * The URL MUST start with "http://" or "https://" to find the address. + * + * For example, if the URL is: + * pUrl = "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff" + * + * *pAddress = "www.somewebsite.com/path/to/item.txt?optionalquery=stuff" + * *pAddressLen = 19 + * + * @param[in] pUrl - URL string to parse. + * @param[in] urlLen - The length of the URL string input. + * @param[out] pAddress - pointer within input url that the address starts at. + * @param[out] pAddressLen - Length of the address. + * + * @return One of the following: + * - #IOT_HTTPS_OK if the path was successfully parsed. + * - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the URL. + * - #IOT_HTTPS_NOT_FOUND if the address was not found. + */ +IotHttpsReturnCode_t IotHttpsClient_GetUrlAddress( const char * pUrl, + size_t urlLen, + const char ** pAddress, + size_t * pAddressLen ); + +#endif /* IOT_HTTPS_UTILS_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/https/include/types/iot_https_types.h b/bsp/aws_libraries/c_sdk/standard/https/include/types/iot_https_types.h new file mode 100644 index 0000000..3fbba57 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/https/include/types/iot_https_types.h @@ -0,0 +1,905 @@ +/* + * FreeRTOS HTTPS Client V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_https_types.h + * @brief Types of the HTTPS Client library. + */ + +#ifndef IOT_HTTPS_TYPES_H_ +#define IOT_HTTPS_TYPES_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* C standard includes. */ +#include +#include +#include + +/*------------------------- HTTPS defined constants --------------------------*/ + +/** + * @constants_page{https_client} + * @constants_brief{HTTPS Client library} + * + * @section https_minimum_user_buffer_sizes HTTPS Client Minimum User Buffer Sizes + * @brief Variables calculating the size of #IotHttpsUserBuffer_t.bufferLen needed for the request, response, and + * connection. + * + * @note These user buffer minimum values may change at any time in future versions, but their names will remain the + * same. + * - @ref requestUserBufferMinimumSize
+ * @copybrief requestUserBufferMinimumSize + * - @ref responseUserBufferMinimumSize
+ * @copybrief responseUserBufferMinimumSize + * - @ref connectionUserBufferMinimumSize
+ * @copybrief connectionUserBufferMinimumSize + * + * @section https_connection_flags HTTPS Client Connection Flags + * @brief Flags that modify the behavior of the HTTPS Connection. + * + * Flags should be bitwise-ORed with each other to change the behavior of @ref https_client_function_sendasync and + * @ref https_client_function_sendsync. These flags are set in #IotHttpsConnectionInfo_t.flags. + * + * @note The values of flags may change at any time in future versions, but their names will remain the same. + * + * @section https_initializers HTTP Initializers + * @brief Provide default values for the data types of the HTTP Client Library. + * + * @snippet this define_https_initializers + * + * All user-facing data types of the HTTPS Client library should be initialized using one of the following. + * + * @warning Failing to initialize an HTTPS Client data type with the appropriate initializer may result in undefined + * behavior. + * @note The initializers may change at any time in future versions, but their names will remain the same. + * + * Example + * @code{c} + * IotHttpsConnectionHandle_t connHandle = IOT_HTTPS_CONNECTION_HANDLE_INITIALIZER; + * IotHttpsRequestHandle_t reqHandle = IOT_HTTPS_REQUEST_HANDLE_INITIALIZER; + * IotHttpsResponseHandle_t respHandle = IOT_HTTPS_RESPONSE_HANDLE_INITIALIZER; + * IotHttpsUserBuffer_t userBuffer = IOT_HTTPS_USER_BUFFER_INITIALIZER; + * IotHttpsSyncInfo_t syncInfoReq = IOT_HTTPS_SYNC_INFO_INITIALIZER; + * IotHttpsSyncInfo_t syncInfoResp = IOT_HTTPS_SYNC_INFO_INITIALIZER; + * IotHttpsConnectionInfo_t connInfo = IOT_HTTPS_CONNECTION_INFO_INITIALIZER; + * IotHttpsRequestInfo_t reqInfo = IOT_HTTPS_REQUEST_INFO_INITIALIZER + * IotHttpsResponseInfo_t respInfo = IOT_HTTPS_RESPONSE_INFO_INITIALIZER + * @endcode + * + * @section http_constants_connection_flags HTTPS Client Connection Flags + * @brief Flags that modify the behavior the HTTPS connection. + * - #IOT_HTTPS_IS_NON_TLS_FLAG
+ * @copybrief IOT_HTTPS_IS_NON_TLS_FLAG + * - #IOT_HTTPS_DISABLE_SNI
+ * @copybrief IOT_HTTPS_DISABLE_SNI + */ + +/** + * @brief The minimum user buffer size for the HTTP request context and headers. + * + * This helps to calculate the size of the buffer needed for #IotHttpsRequestInfo_t.userBuffer. + * + * This buffer size is calculated to fit the HTTP Request-Line and the default headers. It does not account for the + * length of the path in the Request-Line nor does it account for the length of the host name. It also does not account + * for extra headers that the application may add. These sizes need to be accounted for by the application when + * assigning a buffer. + * + * A typical value for sizing the request user buffer for the request context is 512 bytes. See the example below. + * @code{c} + * uint8_t requestUserBuffer[512] = { 0 }; + * IotHttpsRequestInfo_t requestInfo = IOT_HTTPS_REQUEST_INFO_INITIALIZER; + * requestInfo.userBuffer.pBuffer = requestUserBuffer; + * @endcode + * + * By the application providing the memory for the internal context, no memory is needed to be allocated internally to + * the library for the internal context. The application has control over the memory allocation related to the request, + * response, and connection. + */ +extern const uint32_t requestUserBufferMinimumSize; + +/** + * @brief The minimum user buffer size for the HTTP response context and headers. + * + * This helps to calculate the size of the buffer needed for #IotHttpsResponseInfo_t.userBuffer. + * + * The buffer size is calculated to fit the HTTP response context only. It does not account for the HTTP response status + * line. It does not account for any HTTP response headers. If the buffer assigned to + * #IotHttpsResponseInfo_t.userBuffer is of this minimum size, then the response Status-Line and the response headers + * will not be stored. These sizes need to be accounted for by the application when assigning a buffer. + * + * If the response Status-Line and response headers cannot fit into #IotHttpsResponseInfo_t.userBuffer, then after a + * call to @ref https_client_function_sendsync, calls to @ref https_client_function_readresponsestatus, + * @ref https_client_function_readcontentlength, and @ref https_client_function_readheader will return a failure code. + * + * A typical value for sizing the response user buffer for the response context is 512 bytes. See the example below. + * @code{c} + * uint8_t responseUserBuffer[512] = { 0 }; + * IotHttpsResponseInfo_t responseInfo = IOT_HTTPS_RESPONSE_INFO_INITIALIZER; + * responseInfo.userBuffer.pBuffer = responseUserBuffer; + * @endcode + * + * By the application providing the memory for the internal context, no memory is needed to be allocated internally to + * the library for the internal context. The application has control over the memory allocation related to the request, + * response, and connection. + */ +extern const uint32_t responseUserBufferMinimumSize; + +/** + * @brief The minimum user buffer size for the HTTP connection context and headers. + * + * This helps to calculate the size of the buffer needed for #IotHttpsConnectionInfo_t.userBuffer. + * + * The buffer size is calculated to fit the HTTP connection context only. The buffer assigned by the application must be + * at least this size. + * + * A typical value for sizing the request user buffer for the connection context is 512 bytes. See the example below. + * @code{c} + * uint8_t connectionUserBuffer[512] = { 0 }; + * IotHttpsConnectionInfo_t connectionInfo = IOT_HTTPS_CONNECTION_INFO_INITIALIZER; + * connectionInfo.userBuffer.pBuffer = connectionUserBuffer; + * @endcode + * + * By the application providing the memory for the internal context, no memory is needed to be allocated internally to + * the library for the internal context. The application has control over the memory allocation related to the request, + * response, and connection. + */ +extern const uint32_t connectionUserBufferMinimumSize; + +/** + * @brief Flag for #IotHttpsConnectionInfo_t that disables TLS. + * + * Set this bit in #IotHttpsConnectionInfo_t.flags to disable use of TLS when the connection is created. This library + * creates secure connections by default. + */ +#define IOT_HTTPS_IS_NON_TLS_FLAG ( 0x00000001 ) + +/** + * @brief Flag for #IotHttpsConnectionInfo_t that disables Server Name Indication (SNI). + * + * Set this bit #IotHttpsConnectionInfo_t.flags to disable SNI. SNI is enabled by default in this library. When SNI is + * enabled #IotHttpsConnectionInfo_t.pAddress will be used for the server name verification. + */ +#define IOT_HTTPS_DISABLE_SNI ( 0x00000008 ) + +/* @[define_https_initializers] */ +/** @brief Initializer for #IotHttpsConnectionHandle_t. */ +#define IOT_HTTPS_CONNECTION_HANDLE_INITIALIZER NULL +/** @brief Initializer for #IotHttpsRequestHandle_t. */ +#define IOT_HTTPS_REQUEST_HANDLE_INITIALIZER NULL +/** @brief Initializer for #IotHttpsResponseHandle_t. */ +#define IOT_HTTPS_RESPONSE_HANDLE_INITIALIZER NULL +/** @brief Initializer for #IotHttpsUserBuffer_t. */ +#define IOT_HTTPS_USER_BUFFER_INITIALIZER { 0 } +/** @brief Initializer for #IotHttpsSyncInfo_t. */ +#define IOT_HTTPS_SYNC_INFO_INITIALIZER { 0 } +/** @brief Initializer for #IotHttpsAsyncInfo_t. */ +#define IOT_HTTPS_ASYNC_INFO_INITIALIZER { 0 } +/** @brief Initializer for #IotHttpsConnectionInfo_t. */ +#define IOT_HTTPS_CONNECTION_INFO_INITIALIZER { 0 } +/** @brief Initializer for #IotHttpsRequestInfo_t. */ +#define IOT_HTTPS_REQUEST_INFO_INITIALIZER { 0 } +/** @brief Initializer for #IotHttpsResponseInfo_t. */ +#define IOT_HTTPS_RESPONSE_INFO_INITIALIZER { 0 } +/* @[define_https_initializers] */ + +/* Network include for the network types below. */ +#include "platform/iot_network.h" + +/** + * @brief Type for the network interface containing the operations to send, receive, connect, and disconnect from + * the network. + */ +#define IOT_HTTPS_NETWORK_INTERFACE_TYPE const IotNetworkInterface_t * + +/*---------------------------- HTTPS handle types ----------------------------*/ + +/** + * @handles_group{https_client} + * @handles_brief{HTTPS Client library} + */ + +/** + * @ingroup https_client_datatypes_handles + * @brief Opaque handle of an HTTP connection. + * + * A connection handle is needed to send many requests over a single persistent connection. This handle is valid after + * a successful call to @ref https_client_function_connect or @ref https_client_function_sendsync or + * @ref https_client_function_sendasync. A variable of this type is passed to @ref https_client_function_sendsync, + * @ref https_client_function_sendasync, and @ref https_client_function_disconnect to identify which connection that + * function acts on. + * + * A call to @ref https_client_function_disconnect makes a connection handle invalid. Once @ref https_client_function_disconnect + * returns, the connection handle should no longer be used. The application must call @ref https_client_function_connect + * again to retrieve a new handle and a new connection. + * + * Typical web servers disconnect the client in around 30-60 seconds. The application needs to be aware of this, when + * taking time between requests in a persistent connection. + * + * A connection handle is not thread safe. Multiple threads cannot connect and disconnect with the same handle at the + * same time. + * + * Multiple threads can call @ref https_client_function_sendasync or @ref https_client_function_sendsync with the same + * connection handle. + */ +typedef struct _httpsConnection * IotHttpsConnectionHandle_t; + +/** + * @ingroup https_client_datatypes_handles + * @brief Opaque handle of an HTTP request. + * + * Having a separate handle for the HTTP request allows the application to re-use a request. + * + * This handle is valid after a successful call to @ref https_client_function_initializerequest. A variable of this type + * is passed to @ref https_client_function_sendasync or @ref https_client_function_sendsync. + * + * A request handle cannot be sent on multiple connections at the same time. + * + * A request handle is not thread safe. Multiple threads cannot write headers to the same request handle. + */ +typedef struct _httpsRequest * IotHttpsRequestHandle_t; + +/** + * @ingroup https_client_datatypes_handles + * @brief Opaque handle of an HTTP response. + * + * This handle is valid after a successful call to @ref https_client_function_sendsync or + * @ref https_client_function_sendasync. A variable of this type is passed to + * @ref https_client_function_readresponsestatus, @ref https_client_function_readcontentlength, + * @ref https_client_function_readheader, and @ref https_client_function_readresponsebody. + * + * When returned from @ref https_client_function_sendsync or @ref https_client_function_sendasync, there is an + * associated #IotHttpsRequestHandle_t. If the #IotHttpsRequestHandle_t associated with this response is re-initialized + * with @ref https_client_function_initializerequest, then this response handle is no longer valid. + * + * A response handle is not thread safe. Multiple threads cannot read the headers in a response at the same time. + */ +typedef struct _httpsResponse * IotHttpsResponseHandle_t; + +/*-------------------------- HTTPS enumerated types --------------------------*/ + +/** + * @enums_group{https_client} + * @enums_brief{HTTPS Client library} + */ + +/** + * @ingroup https_client_datatypes_enums + * @brief Return codes of [HTTPS Client functions](@ref https_client_functions). + */ +typedef enum IotHttpsReturnCode +{ + /** + * @brief Returned for a successful operation. + */ + IOT_HTTPS_OK = 0, + + /** + * @brief An invalid parameter was passed into an API function. + */ + IOT_HTTPS_INVALID_PARAMETER = 101, + + /** + * @brief Invalid payload. + */ + IOT_HTTPS_INVALID_PAYLOAD = 102, + + /** + * @brief HTTPS message was too large to fit into a configured synchronous body buffer. + */ + IOT_HTTPS_MESSAGE_TOO_LARGE = 103, + + /** + * @brief Overflow occurred somewhere. + */ + IOT_HTTPS_OVERFLOW = 104, + + /** + * @brief A buffer provided could not hold data required by the library. + */ + IOT_HTTPS_INSUFFICIENT_MEMORY = 105, + + /** + * @brief Queue full. + */ + IOT_HTTPS_QUEUE_FULL = 106, + + /** + * @brief Operation retry. + */ + IOT_HTTPS_RETRY = 107, + + /** + * @brief Could not find an item specified by an API. + * + * Returned for not being able to find the address in a URL, the path in a URL, or a header field from the response + * headers. + */ + IOT_HTTPS_NOT_FOUND = 108, + + /** + * @brief The HTTP request message was finished being written and we cannot write more with @ref https_client_function_writerequestbody. + */ + IOT_HTTPS_MESSAGE_FINISHED = 109, + + /** + * @brief An error occurred internally to the library. + */ + IOT_HTTPS_INTERNAL_ERROR = 201, + + /** + * @brief A network error occurred. + */ + IOT_HTTPS_NETWORK_ERROR = 202, + + /** + * @brief A network connection error occurred. + */ + IOT_HTTPS_CONNECTION_ERROR = 203, + + /** + * @brief A stream error occurred. + */ + IOT_HTTPS_STREAM_ERROR = 204, + + /** + * @brief An authentication error occurred. + */ + IOT_HTTPS_AUTHENTICATION_ERROR = 205, + + /** + * @brief A TLS error occurred. + */ + IOT_HTTPS_TLS_ERROR = 206, + + /** + * @brief An error occurred during the user callback. + */ + IOT_HTTPS_USER_CALLBACK_ERROR = 207, + + /** + * @brief The synchronous response could not be received in the specified timeout in @ref https_client_function_sendsync. + */ + IOT_HTTPS_TIMEOUT_ERROR = 208, + + /** + * @brief An error in the HTTP protocol. + */ + IOT_HTTPS_PROTOCOL_ERROR = 209, + + /** + * @brief The HTTPS request send was cancelled. + */ + IOT_HTTPS_SEND_ABORT = 210, + + /** + * @brief The HTTPS response receiving was cancelled. + */ + IOT_HTTPS_RECEIVE_ABORT = 211, + + /** + * @brief The asynchronous request had an error being scheduled. + */ + IOT_HTTPS_ASYNC_SCHEDULING_ERROR = 212, + + /** + * @brief There was an error parsing the HTTP response. + */ + IOT_HTTPS_PARSING_ERROR = 213, + + /** + * @brief Fatal HTTP library error. + */ + IOT_HTTPS_FATAL = 901, + + /** + * @brief The connection is busy and cannot be cleaned up. + * + * The connection was closed, but @ref https_client_function_disconnect must be called again to cleanup connection + * resources. + */ + IOT_HTTPS_BUSY = 902, + + /** + * @brief Try again. + */ + IOT_HTTPS_TRY_AGAIN = 903, + + /** + * @brief Data exists. + */ + IOT_HTTPS_DATA_EXIST = 904, + + /** + * @brief The operation on the public API is not supported. + */ + IOT_HTTPS_NOT_SUPPORTED = 905 +} IotHttpsReturnCode_t; + +/** + * @ingroup https_client_datatypes_enums + * @brief Types of HTTP methods. + * + * The HTTP method is configured in #IotHttpsRequestInfo_t.method. + */ +typedef enum IotHttpsMethod +{ + IOT_HTTPS_METHOD_GET = 0, /* Client-to-server method GET */ + IOT_HTTPS_METHOD_HEAD, /* Client-to-server method HEAD */ + IOT_HTTPS_METHOD_PUT, /* Client-to-server method PUT */ + IOT_HTTPS_METHOD_POST /* Client-to-server method POST. */ +} IotHttpsMethod_t; + +/** + * @ingroup https_client_datatypes_enums + * @brief Types of standard HTTP Response status codes. + * + * These status codes are taken from RFC 2616. Please see RFC 2616 for a description of each response status. + */ +enum IotHttpsResponseStatus +{ + IOT_HTTPS_STATUS_CONTINUE = 100, + IOT_HTTPS_STATUS_SWITCHING_PROTOCOLS, + IOT_HTTPS_STATUS_OK = 200, + IOT_HTTPS_STATUS_CREATED, + IOT_HTTPS_STATUS_ACCEPTED, + IOT_HTTPS_STATUS_NON_AUTHORITIVE_INFORMATION, + IOT_HTTPS_STATUS_NO_CONTENT, + IOT_HTTPS_STATUS_RESET_CONTENT, + IOT_HTTPS_STATUS_PARTIAL_CONTENT, + IOT_HTTPS_STATUS_MULTIPLE_CHOICES = 300, + IOT_HTTPS_STATUS_MOVED_PERMANENTLY, + IOT_HTTPS_STATUS_FOUND, + IOT_HTTPS_STATUS_SEE_OTHER, + IOT_HTTPS_STATUS_NOT_MODIFIED, + IOT_HTTPS_STATUS_USE_PROXY, + IOT_HTTPS_STATUS_UNUSED, + IOT_HTTPS_STATUS_TEMPORARY_REDIRECT, + IOT_HTTPS_STATUS_BAD_REQUEST = 400, + IOT_HTTPS_STATUS_UNAUTHORIZED, + IOT_HTTPS_STATUS_PAYMENT_REQUIRED, + IOT_HTTPS_STATUS_FORBIDDEN, + IOT_HTTPS_STATUS_NOT_FOUND, + IOT_HTTPS_STATUS_METHOD_NOT_ALLOWED, + IOT_HTTPS_STATUS_NOT_ACCEPTABLE, + IOT_HTTPS_STATUS_PROXY_AUTHENTICATION_REQUIRED, + IOT_HTTPS_STATUS_REQUEST_TIMEOUT, + IOT_HTTPS_STATUS_CONFLICT, + IOT_HTTPS_STATUS_GONE, + IOT_HTTPS_STATUS_LENGTH_REQUIRED, + IOT_HTTPS_STATUS_PRECONDITION_FAILED, + IOT_HTTPS_STATUS_REQUEST_ENTITY_TOO_LARGE, + IOT_HTTPS_STATUS_REQUEST_URI_TOO_LONG, + IOT_HTTPS_STATUS_UNSUPPORTED_MEDIA_TYPE, + IOT_HTTPS_STATUS_REQUEST_RANGE_NOT_SATISFIABLE, + IOT_HTTPS_STATUS_EXPECTATION_FAILED, + IOT_HTTPS_STATUS_INTERNAL_SERVER_ERROR = 500, + IOT_HTTPS_STATUS_NOT_IMPLEMENTED, + IOT_HTTPS_STATUS_BAD_GATEWAY, + IOT_HTTPS_STATUS_SERVICE_UNAVAILABLE, + IOT_HTTPS_STATUS_GATEWAY_TIMEOUT, + IOT_HTTPS_STATUS_HTTP_VERSION_NOT_SUPPORTED +}; + +/*------------------------- HTTPS parameter structs --------------------------*/ + +/** + * @paramstructs_group{https_client} + * @paramstructs_brief{https_client,HTTPS Client Libray} + */ + +/** + * @ingroup https_client_datatypes_paramstructs + * + * @brief HTTPS Client library callbacks for asynchronous requests. + * + * @paramfor @ref https_client_function_initializerequest + * + * This type is a parameter in #IotHttpsResponseInfo_t. + * + * If any of the members in this type are set to NULL, then they will not be invoked during the asynchronous + * request/response process. + * + * See @ref Asynchronous_Callback_Order for the order of the order of the callbacks and when they will be invoked. + */ +typedef struct IotHttpsClientCallbacks +{ + /** + * @brief User-provided callback function signature for appending a header to current asynchronous request. + * + * If this is set to NULL, then it will not be invoked. + * See @ref https_client_function_addheader for more information on adding a header in this callback. + * + * Appending the header when request is in progress is good for things like time limited authentication tokens. + * + * @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData + * @param[in] reqHandle - The handle for the current HTTP request in progress. + */ + void ( * appendHeaderCallback )( void * pPrivData, + IotHttpsRequestHandle_t reqHandle ); + + /** + * @brief User-provided callback function signature for writing data to the network for a current asynchronous + * request. + * + * If this is set to NULL, then it will not be invoked. + * See @ref https_client_function_writerequestbody for more information on writing request body. + * + * @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData + * @param[in] reqHandle - The handle for the current HTTP request in progress. + */ + void ( * writeCallback )( void * pPrivData, + IotHttpsRequestHandle_t reqHandle ); + + /** + * @brief User-provided callback function signature for reading data from the network for a current asynchronous + * response. + * + * The network indicated that after sending the associated request, the response is available for reading. + * If this is set to NULL, then it will not be invoked and any response body received will be ignored. + * See @ref https_client_function_readresponsebody for more information about reading the response body in this + * callback. + * + * @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData + * @param[in] respHandle - The handle for the current HTTP response in progress. + * @param[in] rc - A return code indicating any errors before this callback was invoked. + * @param[in] status - The HTTP response status code of the current response in progress. + */ + void ( * readReadyCallback )( void * pPrivData, + IotHttpsResponseHandle_t respHandle, + IotHttpsReturnCode_t rc, + uint16_t status ); + + /** + * @brief User-provided callback function signature to indicate that the asynchronous response is completed. + * + * If this is set to NULL, then it will not be invoked. + * + * This callback is invoked when the response is fully received from the network and the request/response pair is + * complete. + * If there was an error in sending the request or an error in receiving the associated response, this callback will + * be invoked, if the error caused the request or associated response to finish. + * #IotHttpsClientCallbacks_t.errorCallback will be invoked first before this callback. + * This callback is invoked to let the application know that memory used by #IotHttpsRequestInfo_t.userBuffer and + * #IotHttpsResponseInfo_t.userBuffer can be freed, modified, or reused. + * + * For a non-persistent connection, the connection will be closed first before invoking this callback. + * + * @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData + * @param[in] respHandle - The handle for the current HTTP response in progress. + * @param[in] rc - A return code indicating any errors before this callback was invoked. + * @param[in] status - The HTTP response status code of the current response in progress. + */ + void ( * responseCompleteCallback )( void * pPrivData, + IotHttpsResponseHandle_t respHandle, + IotHttpsReturnCode_t rc, + uint16_t status ); + + /** + * @brief User-provided callback function signature to indicate that the connection has been close in an asynchronous + * request process. + * + * If this is set to NULL, then it will not be invoked. + * If there are errors during sending/receiving in the asynchronous process, the connection is not automatically + * closed. If the server closes the connection during the asynchronous process, this callback is not invoked. + * This callback is invoked only if the connection was flagged as non-persistent in + * #IotHttpsConnectionInfo_t.flags. + * + * @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData + * @param[in] connHandle - The handle for the current HTTP connection. + * @param[in] rc - A return code indicating any errors before this callback was invoked. + */ + void ( * connectionClosedCallback )( void * pPrivData, + IotHttpsConnectionHandle_t connHandle, + IotHttpsReturnCode_t rc ); + + /** + * @brief User-provided callback function signature to indicate that an error occurred during the asynchronous + * request process. + * + * If respHandle is NULL, then reqHandle will not be NULL and vise-versa. This signals which handle the error + * occurred and if it is during the sending or receiving. + * + * @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData + * @param[in] respHandle - The handle for the current HTTP response. + * @param[in] reqHandle - The handle for the current HTTP request. + * @param[in] rc - A return code indicating any errors before this callback was invoked. + */ + void ( * errorCallback )( void * pPrivData, + IotHttpsRequestHandle_t reqHandle, + IotHttpsResponseHandle_t respHandle, + IotHttpsReturnCode_t rc ); +} IotHttpsClientCallbacks_t; + +/** + * @ingroup https_client_datatypes_paramstructs + * @brief User-provided buffer for storing the HTTPS headers and library internal context. + * + * @paramfor @ref https_client_function_initializerequest. + * + * The user buffer is configured in #IotHttpsConnectionInfo_t.userBuffer, #IotHttpsRequestInfo_t.userBuffer and + * #IotHttpsResponseInfo_t.userBuffer. + * + * The minimum size that the buffer must be configured to is indicated by requestUserBufferMinimumSize, + * responseUserBufferMinimumSize, connectionUserBufferMinimumSize. + */ +typedef struct IotHttpsUserBuffer +{ + uint8_t * pBuffer; /**< @brief Application provided buffer pointer. */ + uint32_t bufferLen; /**< @brief The length of the application provided buffer. */ +} IotHttpsUserBuffer_t; + +/** + * @ingroup https_client_datatypes_paramstructs + * @brief HTTPS Client synchronous request information. + * + * @paramfor @ref https_client_function_initializerequest, @ref https_client_function_sendsync, + * @ref https_client_function_sendasync + * + * This structure is configured in #IotHttpsRequestInfo_t.u and #IotHttpsResponseInfo_t. + * + * A synchronous request will block until the response is fully received from the network. + * This structure defines memory locations to store the response body. + */ +typedef struct IotHttpsSyncRequestInfo +{ + /** + * Pointer to the HTTP message body. + * + * For a request this is the file or data we want to send. The data is separated from the headers for the + * flexibility to point to an already established file elsewhere in memory. + * + * For a response this is where to receive the response entity body. + * If the length of the buffer provided to store the response body is smaller than the amount of body received, + * then @ref https_client_function_sendsync will return a IOT_HTTPS_INSUFFICIENT_MEMORY error code. Although an error + * was returned, the first #IotHttpsSyncInfo_t.bodyLen of the response received on the network will + * still be available in the buffer. + */ + uint8_t * pBody; + uint32_t bodyLen; /**< @brief The length of the HTTP message body. */ +} IotHttpsSyncInfo_t; + +/** + * @ingroup https_client_datatypes_paramstructs + * @brief HTTPS Client asynchronous request information. + * + * @paramfor @ref https_client_function_initializerequest. + * + * This is parameter in #IotHttpsRequestInfo_t.u. + * + * An asynchronous request will ask the application for headers and body right before the request is ready + * to be sent onto the network. + * An asynchronous request will have the application read headers and body as soon as the response is received + * on the network. + */ +typedef struct IotHttpsAsyncInfo +{ + /** + * @brief Callbacks are used for an asynchronous request. + * See #IotHttpsClientCallbacks_t for more information. + */ + IotHttpsClientCallbacks_t callbacks; + void * pPrivData; /**< @brief User private data to provide context to the asynchronous callbacks. */ +} IotHttpsAsyncInfo_t; + +/** + * @ingroup https_client_datatypes_paramstructs + * @brief HTTP connection configuration. + * + * @paramfor @ref https_client_function_connect or @ref https_client_function_sendsync or + * @ref https_client_function_sendasync. + * + * This parameter is used to connection in @ref https_client_function_connect. + * + * @note The lengths of the strings in this struct should not include the NULL + * terminator. Strings in this struct do not need to be NULL-terminated. + */ +typedef struct IotHttpsConnectionInfo +{ + /** + * @brief Remote server address that is DNS discoverable. + * + * For example: avs-alexa-na.amazon.com. + */ + const char * pAddress; + uint32_t addressLen; /**< @brief remote address length. */ + + uint16_t port; /**< @brief Remote port number */ + + /** + * @brief Flags to configure the HTTPS connection. + * + * See @ref https_connection_flags for the available flags. + * + * Unknown flags are ignored. + */ + uint32_t flags; /**< @brief Flags to configure the HTTPS connection. */ + + /** + * @brief Timeout waiting for a response from the network in milliseconds. + * + * If this is set to zero, it will default to @ref IOT_HTTPS_RESPONSE_WAIT_MS. + */ + uint32_t timeout; + + const char * pCaCert; /**< @brief Server trusted certificate store for this connection. */ + uint32_t caCertLen; /**< @brief Server trusted certificate store size. */ + + const char * pClientCert; /**< @brief Client certificate store for this connection. */ + uint32_t clientCertLen; /**< @brief Client certificate store size. */ + + const char * pPrivateKey; /**< @brief Client private key store for this connection. */ + uint32_t privateKeyLen; /**< @brief Client private key store size. */ + + /** + * @brief String of all the ALPN protocols separated by commas needed for this connection. + * + * For the protocols needed for the AWS Iot Message broker endpoint please see: + * https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html + */ + char * pAlpnProtocols; + uint32_t alpnProtocolsLen; /**< @brief ALPN protocol string length. */ + + /** + * @brief User buffer to store the internal connection context. + * + * See @ref connectionUserBufferMinimumSize for information about the user buffer configured in + * #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle. + */ + IotHttpsUserBuffer_t userBuffer; + + /** + * @brief The IOT network abstraction interface. + * + * This contains the interface to connect, disconnect, send data, and receive data from the network. + * + * In FreeRTOS this should be of the type @ref IotNetworkInterface_t. + */ + IOT_HTTPS_NETWORK_INTERFACE_TYPE pNetworkInterface; +} IotHttpsConnectionInfo_t; + +/** + * @ingroup https_client_datatypes_paramstructs + * @brief HTTP request configuration. + * + * @paramfor @ref https_client_function_initializerequest. + * + * This parameter is used to configure the request in https_client_function_initializerequest. + * + * @note The lengths of the strings in this struct should not include the NULL + * terminator. Strings in this struct do not need to be NULL-terminated. + */ +typedef struct IotHttpsRequestInfo +{ + /** + * @brief The absolute path to the HTTP request object. + * + * The absolute path includes the path to the file AND the optional query. + * An example URI path: "/v20160207/directives?query". + * + * If this is NULL, a "/" will be added to the Request-Line automatically. + * + * This is used to generate the Request-Line in the HTTP request message, see + * @ref https_client_function_initializerequest for more information. + */ + const char * pPath; + uint32_t pathLen; /**< @brief URI path length */ + + /** + * @brief On of the HTTP method tokens defined in #IotHttpsMethod_t. + * + * This is used to generate the Request-Line in the HTTP request message, see + * @ref https_client_function_initializerequest for more information. + */ + IotHttpsMethod_t method; + + /** + * @brief Host address this request is intended for, e.g., "awsamazon.com". + * + * This is the same as the address in #IotHttpsConnectionInfo_t.pAddress. This is here in the request structure to + * automatically generate the "Host" header field in the header buffer space configured in + * #IotHttpsRequestInfo_t.userBuffer. See @ref https_client_function_initializerequest for more information. + */ + const char * pHost; + uint32_t hostLen; /**< @brief Host address length. */ + + /** + * @brief Flag denoting if the connection should be non-persistent. + * + * If this flag is set to false, then the connection is persistent. When the connection is persistent, the HTTP + * header "Connection: keep-alive" is automatically added to the headers to send to the server. This header + * asks the server to not close the connection after sending the response. + * + * If this flag is set to true, then the connection is non-persistent. When the connection is non-persistent, then + * HTTP header "Connection: close" is automatically added to the headers to send to the server. This header asks + * the server to close the connection after sending the response. + * + * Please see https://tools.ietf.org/html/rfc2616#section-8.1.1 for more details. + */ + bool isNonPersistent; + + /** + * @brief Application owned buffer for storing the request headers and internal request context. + * + * For an asynchronous request, if the application owns the memory for this buffer, then it must not be modified, + * freed, or reused until the the #IotHttpsClientCallbacks_t.responseCompleteCallback is invoked. + * + * Please see #IotHttpsUserBuffer_t for more information. + */ + IotHttpsUserBuffer_t userBuffer; + + /** + * @brief Indicator if this request is sync or async. + * + * Set this to false to use a synchronous request. Set this to true to use an asynchronous request. + */ + bool isAsync; + + /** + * @brief Specific information for either a synchronous request or an asynchronous request. + * + * See #IotHttpsAsyncInfo_t for information on pAsyncInfo. + * See #IotHttpsSyncInfo_t for information on u.pSyncInfo. + */ + union + { + IotHttpsAsyncInfo_t * pAsyncInfo; /**< @brief Information specifically for Asynchronous requests. */ + IotHttpsSyncInfo_t * pSyncInfo; /**< @brief Information specifically for synchronous requests. */ + } u; +} IotHttpsRequestInfo_t; + +/** + * @ingroup https_client_datatypes_paramstructs + * @brief HTTP request configuration. + * + * @paramfor @ref https_client_function_sendsync and @ref https_client_function_sendasync + * + * A separate response info is defined so that the application can re-initialize a request for re-use while still + * processing a response that was already completed. + */ +typedef struct IotHttpsResponseInfo +{ + /** + * The application owned buffer for storing the response headers and internal response context. + * + * For an asynchronous request, if the application owns the memory for this buffer, then it must not be modified, + * freed, or reused until the the #IotHttpsClientCallbacks_t.responseCompleteCallback is invoked. + * + * Please see #IotHttpsUserBuffer_t for more information. + */ + IotHttpsUserBuffer_t userBuffer; + + /** + * @brief Specific information for a synchronously received response. + * + * Set this to NULL if the response is to be received asynchronously. + * + * See #IotHttpsSyncInfo_t for more information. + */ + IotHttpsSyncInfo_t * pSyncInfo; +} IotHttpsResponseInfo_t; + +#endif /* ifndef IOT_HTTPS_TYPES_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/https/src/iot_https_client.c b/bsp/aws_libraries/c_sdk/standard/https/src/iot_https_client.c new file mode 100644 index 0000000..2891c1a --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/https/src/iot_https_client.c @@ -0,0 +1,3403 @@ +/* + * FreeRTOS HTTPS Client V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_https_client.c + * @brief Implementation of the user-facing functions of the FreeRTOS HTTPS Client library. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* HTTPS Client library private includes. */ +#include "private/iot_https_internal.h" + +/*-----------------------------------------------------------*/ + +/** + * @brief Partial HTTPS request first line. + * + * This is used for the calculation of the requestUserBufferMinimumSize. + * The minimum path is "/" because we cannot know how long the application requested path is is going to be. + * CONNECT is the longest string length HTTP method according to RFC 2616. + */ +#define HTTPS_PARTIAL_REQUEST_LINE HTTPS_CONNECT_METHOD " " HTTPS_EMPTY_PATH " " HTTPS_PROTOCOL_VERSION + +/** + * @brief The User-Agent header line string. + * + * This is of the form: + * "User-Agent: \r\n" + * This is used for the calculation of the requestUserBufferMinimumSize. + */ +#define HTTPS_USER_AGENT_HEADER_LINE HTTPS_USER_AGENT_HEADER HTTPS_HEADER_FIELD_SEPARATOR IOT_HTTPS_USER_AGENT HTTPS_END_OF_HEADER_LINES_INDICATOR + +/** + * @brief The Host header line with the field only and not the value. + * + * This is of the form: + * "Host: \r\n" + * This is used for the calculation of the requestUserBufferMinimumSize. The Host value is not specified because we + * cannot anticipate what server the client is making requests to. + */ +#define HTTPS_PARTIAL_HOST_HEADER_LINE HTTPS_HOST_HEADER HTTPS_HEADER_FIELD_SEPARATOR HTTPS_END_OF_HEADER_LINES_INDICATOR + +/** + * Indicates for the http-parser parsing execution function to tell it to keep parsing or to stop parsing. + * + * A value of 0 means the parser should keep parsing if there is more unparsed length. + * A value greater than 0 tells the parser to stop parsing. + */ +#define KEEP_PARSING ( ( int ) 0 ) /**< @brief Indicator in the http-parser callback to keep parsing when the function returns. */ +#define STOP_PARSING ( ( int ) 1 ) /**< @brief Indicator in the http-parser callback to stop parsing when the function returns. */ + +/*-----------------------------------------------------------*/ + + +/** + * @brief Definition of HTTP method enum to strings array. + */ +const char * _pHttpsMethodStrings[] = +{ + "GET", + "HEAD", + "PUT", + "POST" +}; + +/** + * @brief Minimum size of the request user buffer. + * + * The request user buffer is configured in IotHttpsClientRequestInfo_t.userBuffer. This buffer stores the internal context + * of the request and then the request headers right after. The minimum size for the buffer is the total size of the + * internal request context, the HTTP formatted request line, the User-Agent header line, and the part of the Host + * header line. + */ +const uint32_t requestUserBufferMinimumSize = sizeof( _httpsRequest_t ) + + sizeof( HTTPS_PARTIAL_REQUEST_LINE ) + + sizeof( HTTPS_USER_AGENT_HEADER_LINE ) + + sizeof( HTTPS_PARTIAL_HOST_HEADER_LINE ); + +/** + * @brief Minimum size of the response user buffer. + * + * The response user buffer is configured in IotHttpsClientRequestInfo_t.userBuffer. This buffer stores the internal context + * of the response and then the response headers right after. This minimum size is calculated for the case if no bytes + * from the HTTP response headers are to be stored. + */ +const uint32_t responseUserBufferMinimumSize = sizeof( _httpsResponse_t ); + +/** + * @brief Minimum size of the connection user buffer. + * + * The connection user buffer is configured in IotHttpsConnectionInfo_t.userBuffer. This buffer stores the internal context of the + * connection. + */ +const uint32_t connectionUserBufferMinimumSize = sizeof( _httpsConnection_t ); + +/*-----------------------------------------------------------*/ + +/** + * @brief Callback from http-parser to indicate the start of the HTTP response message is reached. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_message_begin. + */ +static int _httpParserOnMessageBeginCallback( http_parser * pHttpParser ); + +/** + * @brief Callback from http-parser to indicate it found the HTTP response status code. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * @param[in] pLoc - Pointer to the HTTP response status code string in the response message buffer. + * @param[in] length - The length of the HTTP response status code string. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_status. + */ +static int _httpParserOnStatusCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ); + +/** + * @brief Callback from http-parser to indicate it found an HTTP response header field. + * + * If only part of the header field was returned here in this callback, then this callback will be invoked again the + * next time the parser executes on the next part of the header field. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * @param[in] pLoc - Pointer to the header field string in the response message buffer. + * @param[in] length - The length of the header field. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_header_field. + */ +static int _httpParserOnHeaderFieldCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ); + +/** + * @brief Callback from http-parser to indicate it found an HTTP response header value. + * + * This value corresponds to the field that was found in the _httpParserOnHeaderFieldCallback() called immediately + * before this callback was called. + * + * If only part of the header value was returned here in this callback, then this callback will be invoked again the + * next time the parser executes on the next part of the header value. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * @param[in] pLoc - Pointer to the header value string in the response message buffer. + * @param[in] length - The length of the header value. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_header_value. + */ +static int _httpParserOnHeaderValueCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ); + +/** + * @brief Callback from http-parser to indicate it reached the end of the headers in the HTTP response message. + * + * The end of the headers is signalled in a HTTP response message by another "\r\n" after the final header line. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_headers_complete. + */ +static int _httpParserOnHeadersCompleteCallback( http_parser * pHttpParser ); + +/** + * @brief Callback from http-parser to indicate it found HTTP response body. + * + * This callback will be invoked multiple times if the response body is of "Transfer-Encoding: chunked". + * _httpParserOnChunkHeaderCallback() will be invoked first, then _httpParserOnBodyCallback(), then + * _httpParserOnChunkCompleteCallback(), then repeated back to _httpParserOnChunkHeaderCallback() if there are more + * "chunks". + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * @param[in] pLoc - Pointer to the body string in the response message buffer. + * @param[in] length - The length of the body found. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_body. + */ +static int _httpParserOnBodyCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ); + +/** + * @brief Callback from http-parser to indicate it reached the end of the HTTP response message. + * + * The end of the message is signalled in a HTTP response message by another "\r\n" after the final header line, with no + * entity body; or it is signaled by "\r\n" at the end of the entity body. + * + * For a Transfer-Encoding: chunked type of response message, the end of the message is signalled by a terminating + * chunk header with length zero. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_message_complete. + */ +static int _httpParserOnMessageCompleteCallback( http_parser * pHttpParser ); + +/* This code prints debugging information and is, therefore, compiled only when + * log level is set to IOT_LOG_DEBUG. */ +#if ( LIBRARY_LOG_LEVEL == IOT_LOG_DEBUG ) + +/** + * @brief Callback from http-parser to indicate it found an HTTP Transfer-Encoding: chunked header. + * + * Transfer-Encoding: chunked headers are embedded in the HTTP response entity body by a "\r\n" followed by the size of + * the chunk followed by another "\r\n". + * + * If only part of the header field was returned here in this callback, then this callback will be invoked again the + * next time the parser executes on the next part of the header field. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_chunk_header. + */ + static int _httpParserOnChunkHeaderCallback( http_parser * pHttpParser ); + +/** + * @brief Callback from http-parser to indicate it reached the end of an HTTP response message "chunk". + * + * A chunk is complete when the chunk header size is read fully in the body. + * + * See https://github.com/nodejs/http-parser for more information. + * + * @param[in] pHttpParser - http-parser state structure. + * + * @return 0 to tell http-parser to keep parsing. + * 1 to tell http-parser that parsing should stop return from http_parser_execute with error HPE_CB_chunk_complete. + */ + static int _httpParserOnChunkCompleteCallback( http_parser * pHttpParser ); +#endif + +/** + * @brief Network receive callback for the HTTPS Client library. + * + * This function is called by the network layer whenever data is available for the HTTP library. + * + * @param[in] pNetworkConnection - The network connection with the HTTPS connection, passed by the network stack. + * @param[in] pReceiveContext - A pointer to the HTTPS Client connection handle for which the packet was received. + */ +static void _networkReceiveCallback( void * pNetworkConnection, + void * pReceiveContext ); + +/** + * @brief Connects to HTTPS server and initializes the connection context. + * + * @param[out] pConnHandle - The out parameter to return handle representing the open connection. + * @param[in] pConnInfo - The connection configuration. + * + * @return #IOT_HTTPS_OK if the connection context initialization was successful. + * #IOT_HTTPS_CONNECTION_ERROR if the connection failed. + * #IOT_HTTPS_INTERNAL_ERROR if the context initialization failed. + */ +static IotHttpsReturnCode_t _createHttpsConnection( IotHttpsConnectionHandle_t * pConnHandle, + IotHttpsConnectionInfo_t * pConnInfo ); + +/** + * @brief Disconnects from the network. + * + * @param[in] pHttpsConnection - HTTPS connection handle. + */ +static void _networkDisconnect( _httpsConnection_t * pHttpsConnection ); + +/** + * @brief Destroys the network connection. + * + * @param[in] pHttpsConnection - HTTPS connection handle. + */ +static void _networkDestroy( _httpsConnection_t * pHttpsConnection ); + +/** + * @brief Receive data on the network. + * + * @param[in] pHttpsConnection - HTTP connection context. + * @param[in] pBuf - The buffer to receive the data into. + * @param[in] bufLen - The length of the data to receive. + * @param[in] numBytesRecv - The number of bytes read from the network. + * + * @return #IOT_HTTPS_OK if the data was received successfully. + * #IOT_HTTPS_NETWORK_ERROR if we timedout trying to receive data from the network. + */ +static IotHttpsReturnCode_t _networkRecv( _httpsConnection_t * pHttpsConnection, + uint8_t * pBuf, + size_t bufLen, + size_t * numBytesRecv ); + +/** + * @brief Parse the HTTP response message in pBuf. + * + * @param[in] pHttpParserInfo - Pointer to the information containing the instance of the http-parser and the execution function. + * @param[in] pBuf - The buffer containing the data to parse. + * @param[in] len - The length of data to parse. + * + * @return #IOT_HTTPS_OK if the data was parsed successfully. + * #IOT_HTTPS_PARSING_ERROR if there was an error with parsing the data. + */ +static IotHttpsReturnCode_t _parseHttpsMessage( _httpParserInfo_t * pHttpParserInfo, + char * pBuf, + size_t len ); + +/** + * @brief Receive any part of an HTTP response. + * + * This function is used for both receiving the body into the body buffer and receiving the header into the header + * buffer. + * + * @param[in] pHttpsConnection - HTTP Connection context. + * @param[in] pParser - Pointer to the instance of the http-parser. + * @param[in] pCurrentParserState - The current state of what has been parsed in the HTTP response. + * @param[in] finalParserState - The final state of the parser expected after this function finishes. + * @param[in] currentBufferProcessingState - The current buffer that is the HTTPS message is being received into. + * @param[in] pBufCur - Pointer to the next location to write data into the buffer pBuf. This is a double pointer to update the response context buffer pointers. + * @param[in] pBufEnd - Pointer to the end of the buffer to receive the HTTP response into. + * + * @return #IOT_HTTPS_OK if we received the HTTP response message part successfully. + * #IOT_HTTPS_PARSING_ERROR if there was an error with parsing the data. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _receiveHttpsMessage( _httpsConnection_t * pHttpsConnection, + _httpParserInfo_t * pParser, + IotHttpsResponseParserState_t * pCurrentParserState, + IotHttpsResponseParserState_t finalParserState, + IotHttpsResponseBufferState_t currentBufferProcessingState, + uint8_t ** pBufCur, + uint8_t ** pBufEnd ); + +/** + * @brief Receive the HTTP response headers. + * + * Receiving the response headers is always the first step in receiving the response, therefore the + * pHttpsResponse->httpParserInfo will be initialized to a starting state when this function is called. + * + * This function also sets internal states to indicate that the header buffer is being processed now for a new response. + * + * @param[in] pHttpsConnection - HTTP connection context. + * @param[in] pHttpsResponse - HTTP response context. + * + * @return #IOT_HTTPS_OK if we received the HTTP headers successfully. + * #IOT_HTTPS_PARSING_ERROR if there was an error with parsing the header buffer. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _receiveHttpsHeaders( _httpsConnection_t * pHttpsConnection, + _httpsResponse_t * pHttpsResponse ); + +/** + * @brief Receive the HTTP response body. + * + * Sets internal states to indicate that the the body buffer is being processed now for a new response. + * + * @param[in] pHttpsConnection - HTTP connection context. + * @param[in] pHttpsResponse - HTTP response context. + * + * @return #IOT_HTTPS_OK if we received the HTTP body successfully. + * #IOT_HTTPS_PARSING_ERROR if there was an error with parsing the body buffer. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _receiveHttpsBody( _httpsConnection_t * pHttpsConnection, + _httpsResponse_t * pHttpsResponse ); + +/** + * @brief Read the rest of any HTTP response that may be on the network. + * + * This reads the rest of any left over response data that might still be on the network buffers. We do not want this + * data left over because it will spill into the header and body buffers of next response that we try to receive. + * + * If we performed a request without a body and the headers received exceeds the size of the + * pHttpsResponse->pHeaders buffer, then we need to flush the network buffer. + * + * If the application configured the body buffer as null in IotHttpsResponseInfo_t.syncInfo.respData and the server + * sends body in the response, but it exceeds the size of pHttpsResponse->pHeaders buffer, then we need to flush the + * network buffer. + * + * If the amount of body received on the network does not fit into a non-null IotHttpsResponseInfo_t.syncInfo.respData, + * then we need to flush the network buffer. + * + * If an asynchronous request cancels in the middle of a response process, after already sending the request message, + * then we need to flush the network buffer. + * + * @param[in] pHttpsConnection - HTTP connection context. + * @param[in] pHttpsResponse - HTTP response context. + * + * @return #IOT_HTTPS_OK if we successfully flushed the network data. + * #IOT_HTTPS_PARSING_ERROR if there was an error with parsing the data. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _flushHttpsNetworkData( _httpsConnection_t * pHttpsConnection, + _httpsResponse_t * pHttpsResponse ); + +/** + * @brief Send an HTTP request from the dispatch queue. + * + * @param[in] pHttpsRequest - Pointer to an HTTP request. + */ +static void _sendHttpsRequest( _httpsRequest_t * pHttpsRequest ); + +/** + * @brief Receive the HTTPS body specific to an asynchronous type of response. + * + * @param[in] pHttpsResponse - HTTP response context. + * + * @return #IOT_HTTPS_OK if the the response body was received with no issues. + * #IOT_HTTPS_RECEIVE_ABORT if the request was cancelled by the Application + * #IOT_HTTPS_PARSING_ERROR if there was an issue parsing the HTTP response body. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _receiveHttpsBodyAsync( _httpsResponse_t * pHttpsResponse ); + +/** + * @brief Receive the HTTPS body specific to a synchronous type of response. + * + * @param[in] pHttpsResponse - HTTP response context. + * + * @return #IOT_HTTPS_OK if the the response body was received with no issues. + * #IOT_HTTPS_MESSAGE_TOO_LARGE if the body from the network is too large to fit into the configured body buffer. + * #IOT_HTTPS_PARSING_ERROR if there was an issue parsing the HTTP response body. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _receiveHttpsBodySync( _httpsResponse_t * pHttpsResponse ); + +/** + * @brief A dummy function for the transport interface receive. + * + * HTTP V1 library handles receiving from the network and hence the transport + * implementation for receive is called by the coreHTTP library. However, it + * will always returns all bytes as successfully read so that `HTTPClient_Send` + * can return a successful status if there are no errors from sending the request. + * + * @param[in] pNetworkContext Implementation-defined network context. + * @param[in] pBuffer Buffer to receive the data into. + * @param[in] bytesToRecv Number of bytes requested from the network. + * + * @return Always returns bytesToRecv or INT32_MAX if bytesToRecv > INT32_MAX. + */ +static int32_t transportRecv( NetworkContext_t * pNetworkContext, + void * pBuffer, + size_t bytesToRecv ); + +/** + * @brief Function for sending data over the network. + * + * @param[in] pNetworkContext Implementation-defined network context. + * @param[in] pBuffer Buffer containing the bytes to send over the network stack. + * @param[in] bytesToSend Number of bytes to send over the network. + * + * @return The number of bytes sent or a negative error code. + */ +static int32_t transportSend( NetworkContext_t * pNetworkContext, + const void * pMessage, + size_t bytesToSend ); + +/** + * @brief A task handle that sends an HTTPS request. + */ +static TaskHandle_t httpsDispatchTask[ IOT_HTTPS_DISPATCH_TASK_COUNT ]; + +/** + * @brief A queue that holds requests that are ready to be sent to the server. + */ +static QueueHandle_t dispatchQueue; + +/** + * @brief Sends requests from the dispatch queue. + * + * @param[in] pParameters User-provided parameters that are left unused. + */ +static void _dispatchTaskRoutine( void * pParameters ); + +/** + * @brief Schedule the task to send the the HTTP request. + * + * @param[in] pHttpsRequest - HTTP request context. + * + * @return #IOT_HTTPS_OK if the task to send the HTTP request was successfully scheduled. + * #IOT_HTTPS_INTERNAL_ERROR if the dispatch queue was full. + * #IOT_HTTPS_ASYNC_SCHEDULING_ERROR if there was an error scheduling the job. + */ +IotHttpsReturnCode_t _scheduleHttpsRequestSend( _httpsRequest_t * pHttpsRequest ); + +/** + * @brief Add the request to the connection's request queue. + * + * This will schedule a task if the request is first and only request in the queue. + * + * @param[in] pHttpsRequest - HTTP request context. + * + * @return #IOT_HTTPS_OK if the request was successfully added to the connection's request queue. + * #IOT_HTTPS_INTERNAL_ERROR if the dispatch queue was full. + * #IOT_HTTPS_ASYNC_SCHEDULING_ERROR if there was an error scheduling the job. + */ +IotHttpsReturnCode_t _addRequestToConnectionReqQ( _httpsRequest_t * pHttpsRequest ); + +/** + * @brief Cancel the HTTP request's processing. + * + * pHttpsRequest->cancelled will be checked and the request cancelled if specified so at the following intervals: + * - Before sending the HTTPS headers at the start of the scheduled sending of the HTTPS request. + * - After Sending the HTTPS headers. + * - After Sending the HTTPS body. + * + * @param[in] pHttpsRequest - HTTP request context. + */ +static void _cancelRequest( _httpsRequest_t * pHttpsRequest ); + +/** + * @brief Cancel the HTTP response's processing. + * + * pHttpsResponse->cancelled will be checked and the response cancelled if specified so at the following intervals: + * - At the start of the network receive callback. + * - After receiving the HTTPS headers. + * - After Receiving the HTTPS body. + * + * @param[in] pHttpsResponse - HTTP response context. + */ +static void _cancelResponse( _httpsResponse_t * pHttpsResponse ); + +/** + * @brief Initialize the input pHttpsResponse with pRespInfo. + * + * @param[in] pRespHandle - Non-null HTTP response context. + * @param[in] pRespInfo - Response configuration information. + * @param[in] pHttpsRequest - HTTP request to grab async information, persistence, and method from. + * + * @return #IOT_HTTPS_OK if the request was successfully added to the connection's request queue. + * #IOT_HTTPS_INSUFFICIENT_MEMORY if the user-provided buffer was on insufficient size. + * #IOT_HTTPS_INVALID_PARAMETER if a parameter was NULL. + */ +static IotHttpsReturnCode_t _initializeResponse( IotHttpsResponseHandle_t * pRespHandle, + IotHttpsResponseInfo_t * pRespInfo, + _httpsRequest_t * pHttpsRequest ); + +/** + * @brief Convert a status code from coreHTTP to an equivalent status code in the HTTP V1 Library. + * + * @param[in] coreHttpStatus - The status code from coreHTTP. + * + * @return #IOT_HTTPS_OK if the coreHTTP status was #HTTPSuccess. + * #IOT_HTTPS_INVALID_PARAMETER if the coreHTTP status was #HTTPInvalidParameter. + * #IOT_HTTPS_NETWORK_ERROR if the coreHTTP status was #HTTPNetworkError. + * #IOT_HTTPS_INSUFFICIENT_MEMORY if the coreHTTP status was #HTTPInsufficientMemory. + * #IOT_HTTPS_NOT_FOUND if the coreHTTP status was #HTTPHeaderNotFound. + */ +static IotHttpsReturnCode_t _shimConvertStatus( HTTPStatus_t coreHttpStatus ); + +/** + * @brief Increment the pointer stored in pBufCur depending on the character found in there. + * + * This function increments the pHeadersCur pointer further if the message ended with a header line delimiter. + * + * @param[in] pBufCur - Pointer to the next location to write data into the buffer pBuf. This is a double pointer to update the response context buffer pointers. + * @param[in] pBufEnd - Pointer to the end of the buffer to receive the HTTP response into. + */ +static void _incrementNextLocationToWriteBeyondParsed( uint8_t ** pBufCur, + uint8_t ** pBufEnd ); + +/** + * @brief Send the HTTPS headers and body referenced in pHttpsRequest. + * + * Sends both the headers and body over the network. + * + * @param[in] pHttpsConnection - HTTPS connection context. + * @param[in] pHttpsRequest - HTTPS request context. + * + * @return #IOT_HTTPS_OK if the headers were fully sent successfully. + * #IOT_HTTPS_NETWORK_ERROR if there was an error receiving the data on the network. + */ +static IotHttpsReturnCode_t _sendHttpsHeadersAndBody( _httpsConnection_t * pHttpsConnection, + _httpsRequest_t * pHttpsRequest ); + +/*-----------------------------------------------------------*/ + +/** + * @brief Definition of the http-parser settings. + * + * The http_parser_settings holds all of the callbacks invoked by the http-parser. + */ +static http_parser_settings _httpParserSettings = { 0 }; + +/*-----------------------------------------------------------*/ + +static int _httpParserOnMessageBeginCallback( http_parser * pHttpParser ) +{ + int retVal = KEEP_PARSING; + + IotLogDebug( "Parser: Start of HTTPS Response message." ); + + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + /* Set the state of the parser. The headers are at the start of the message always. */ + pHttpsResponse->parserState = PARSER_STATE_IN_HEADERS; + return retVal; +} + +/*-----------------------------------------------------------*/ + +static int _httpParserOnStatusCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ) +{ + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + + IotLogDebug( "Parser: Status %.*s retrieved from HTTPS response.", length, pLoc ); + + /* Save the status code so it can be retrieved with IotHttpsClient_ReadResponseStatus(). */ + pHttpsResponse->status = ( uint16_t ) ( pHttpParser->status_code ); + + /* If we are parsing the network data received in the header buffer then we + * increment pHttpsResponse->pHeadersCur. The status line in the response is + * part of the data stored in header buffer _httpResponse->pHeaders. */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_FILLING_HEADER_BUFFER ) + { + /* pHeadersCur will never exceed the pHeadersEnd here because PROCESSING_STATE_FILLING_HEADER_BUFFER + * indicates we are currently in the header buffer and the total size of the header buffer is passed + * into http_parser_execute() as the maximum length to parse. */ + pHttpsResponse->pHeadersCur = ( uint8_t * ) ( pLoc += length ); + } + + return KEEP_PARSING; +} + +/*-----------------------------------------------------------*/ + +static int _httpParserOnHeaderFieldCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ) +{ + IotLogDebug( "Parser: HTTPS header field parsed %.*s", length, pLoc ); + + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + + /* If we are parsing the network data received in the header buffer then we can increment + * pHttpsResponse->pHeadersCur. */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_FILLING_HEADER_BUFFER ) + { + pHttpsResponse->pHeadersCur = ( uint8_t * ) ( pLoc += length ); + } + + /* If the IotHttpsClient_ReadHeader() was called, then we check for the header field of interest. */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_SEARCHING_HEADER_BUFFER ) + { + if( pHttpsResponse->readHeaderFieldLength != length ) + { + pHttpsResponse->foundHeaderField = false; + } + else if( strncmp( pHttpsResponse->pReadHeaderField, pLoc, length ) == 0 ) + { + pHttpsResponse->foundHeaderField = true; + } + } + + return KEEP_PARSING; +} + +/*-----------------------------------------------------------*/ + +static int _httpParserOnHeaderValueCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ) +{ + int retVal = KEEP_PARSING; + + IotLogDebug( "Parser: HTTPS header value parsed %.*s", length, pLoc ); + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + + /* If we are parsing the network data received in the header buffer then we can increment + * pHttpsResponse->pHeadersCur. */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_FILLING_HEADER_BUFFER ) + { + pHttpsResponse->pHeadersCur = ( uint8_t * ) ( pLoc += length ); + } + + /* If the IotHttpsClient_ReadHeader() was called, then we check if we found the header field of interest. */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_SEARCHING_HEADER_BUFFER ) + { + if( pHttpsResponse->foundHeaderField ) + { + pHttpsResponse->pReadHeaderValue = ( char * ) ( pLoc ); + pHttpsResponse->readHeaderValueLength = length; + /* We found a header field so we don't want to keep parsing.*/ + retVal = STOP_PARSING; + } + } + + return retVal; +} + +/*-----------------------------------------------------------*/ + +static int _httpParserOnHeadersCompleteCallback( http_parser * pHttpParser ) +{ + IotLogDebug( "Parser: End of the headers reached." ); + + int retVal = KEEP_PARSING; + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + pHttpsResponse->parserState = PARSER_STATE_HEADERS_COMPLETE; + + /* If the IotHttpsClient_ReadHeader() was called, we return after finishing looking through all of the headers. + * Returning a non-zero value exits the http parsing. */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_SEARCHING_HEADER_BUFFER ) + { + retVal = STOP_PARSING; + } + + /* When in this callback the pHeaderCur pointer is at the first "\r" in the last header line. HTTP/1.1 + * headers end with another "\r\n" at the end of the last line. This means we must increment + * the headerCur pointer to the length of "\r\n\r\n". */ + if( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_FILLING_HEADER_BUFFER ) + { + pHttpsResponse->pHeadersCur += ( 2 * HTTPS_END_OF_HEADER_LINES_INDICATOR_LENGTH ); + } + + /* This if-case is not incrementing any pHeaderCur pointers, so this case is safe to call when flushing the + * network buffer. Flushing the network buffer needs the logic below to reach PARSER_STATE_BODY_COMPLETE if the + * response is for a HEAD request. Before flushing the network buffer the bufferProcessingState is set to + * PROCESSING_STATE_FINISHED so that other callback functions don't update header or body current pointers in the + * response context. We don't want those pointers incremented because flushing the network uses a different buffer + * to receive the rest of the response. */ + if( pHttpsResponse->bufferProcessingState <= PROCESSING_STATE_FINISHED ) + { + /* For a HEAD method, there is no body expected in the response, so we return 1 to skip body parsing. */ + if( ( pHttpsResponse->method == IOT_HTTPS_METHOD_HEAD ) ) + { + retVal = STOP_PARSING; + + /* Since the message is considered complete now for a HEAD response, then we set the parser state + * to the completed state. */ + pHttpsResponse->parserState = PARSER_STATE_BODY_COMPLETE; + } + + /* If this is NOT a HEAD method and there is body configured, but the server does not send a body in the + * response, then the body buffer will be filled with the zeros from rest of the header buffer. http-parser + * will invoke the on_body callback and consider the zeros following the headers as body. */ + + /* If there is not body configured for a synchronous response, we do not stop the parser from continueing. */ + + /* Skipping the body will cause the parser to invoke the _httpParserOnMessageComplete() callback. This is + * not desired when there is actually HTTP response body sent by the server because this will set the parser + * state to PARSER_STATE_BODY_COMPLETE. If this state is set then the rest of possible body will not be + * flushed out. The network flush looks for the state being PARSER_STATE_BODY_COMPLETE to finish flushing. */ + } + + return retVal; +} + +/*-----------------------------------------------------------*/ + +static int _httpParserOnBodyCallback( http_parser * pHttpParser, + const char * pLoc, + size_t length ) +{ + IotLogDebug( "Parser: Reached the HTTPS message body. It is of length: %d", length ); + + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + pHttpsResponse->parserState = PARSER_STATE_IN_BODY; + + /* If the header buffer is currently being processed, but HTTP response body was found, then for an asynchronous + * request this if-case saves where the body is located. In the asynchronous case, the body buffer is not available + * until the readReadyCallback is invoked, which happens after the headers are processed. */ + if( ( pHttpsResponse->bufferProcessingState == PROCESSING_STATE_FILLING_HEADER_BUFFER ) && ( pHttpsResponse->isAsync ) ) + { + /* For an asynchronous response, the buffer to store the body will be available after the headers + * are read first. We may receive part of the body in the header buffer. We will want to leave this here + * and copy it over when the body buffer is available in the _readReadyCallback(). + */ + if( pHttpsResponse->pBodyInHeaderBuf == NULL ) + { + pHttpsResponse->pBodyInHeaderBuf = ( uint8_t * ) ( pLoc ); + pHttpsResponse->pBodyCurInHeaderBuf = pHttpsResponse->pBodyInHeaderBuf; + } + + /* If there is a chunk encoded body in the header buffer, we will want to overwrite the chunk headers with the + * actual body. This is so that when the application calls IotHttpsClient_ReadResponseBody(), in the + * readReadyCallback(), we can pass the body into the body buffer provided right away. */ + if( pHttpsResponse->pBodyCurInHeaderBuf != ( uint8_t * ) pLoc ) + { + memcpy( pHttpsResponse->pBodyCurInHeaderBuf, pLoc, length ); + } + + pHttpsResponse->pBodyCurInHeaderBuf += length; + } + else if( pHttpsResponse->bufferProcessingState < PROCESSING_STATE_FINISHED ) + { + /* Has the user provided a buffer and is it large enough to fit the body? The + * case of body buffer not being large enough can happen if the body was received + * in the header buffer and the body buffer can not fit in all the body. */ + if( ( pHttpsResponse->pBodyCur != NULL ) && ( pHttpsResponse->pBodyEnd - pHttpsResponse->pBodyCur > 0 ) ) + { + /* There are two scenarios when we need to copy data around: + * 1. Some or all of the response body may have been received in the header + * buffer. If that is the case, we copy the response body received in the + * header buffer to the user provided body buffer. + * 2. When we receive chunked header, the actual body is separated in + * multiple chunks which are preceeded by length. For example, a chunked + * body may look like: + * + * 7\r\n + * Mozilla\r\n + * 9\r\n + * Developer\r\n + * 7\r\n + * Network\r\n + * 0\r\n + * \r\n + * + * In this case, we want the parsed body buffer to contain actual body only + * (MozillaDeveloperNetwork in the above example). + */ + + /* If the response body found by the parser (pLoc) is not equal to the + * current writable location in the body buffer (_httpsResponse->pBodyCur), + * it indicates that: + * - Either the data is in the header buffer and needs to be copied into the + * body buffer. + * - Or it is a chunked response and the data needs to be moved up in the + * body buffer. */ + if( ( pHttpsResponse->pBodyCur + length ) <= pHttpsResponse->pBodyEnd ) + { + if( pHttpsResponse->pBodyCur != ( uint8_t * ) pLoc ) + { + memcpy( pHttpsResponse->pBodyCur, pLoc, length ); + } + + pHttpsResponse->pBodyCur += length; + } + } + } + + return KEEP_PARSING; +} + +/*-----------------------------------------------------------*/ + +static int _httpParserOnMessageCompleteCallback( http_parser * pHttpParser ) +{ + IotLogDebug( "Parser: End of the HTTPS message reached." ); + + _httpsResponse_t * pHttpsResponse = ( _httpsResponse_t * ) ( pHttpParser->data ); + pHttpsResponse->parserState = PARSER_STATE_BODY_COMPLETE; + + /* This callback is invoked when the complete HTTP response has been received. + * We tell the parser to parse the whole body buffer as opposed to the size of + * the response body. For example, if the size of the body buffer is 1000 but + * the size of the actual body is 500, we tell the parser to parse the whole + * buffer of length 1000. We do zero out the buffer in the beginning so that all + * the buffer after the actual body contains zeros. We return greater than zero to stop parsing + * since the end of the HTTP message has been reached. Any data beyond the end of the message is + * ignored. */ + return STOP_PARSING; +} + +/*-----------------------------------------------------------*/ + +/* This code prints debugging information and is, therefore, compiled only when + * log level is set to IOT_LOG_DEBUG. */ +#if ( LIBRARY_LOG_LEVEL == IOT_LOG_DEBUG ) + static int _httpParserOnChunkHeaderCallback( http_parser * pHttpParser ) + { + ( void ) pHttpParser; + IotLogDebug( "Parser: HTTPS message Chunked encoding header callback." ); + IotLogDebug( "Parser: HTTPS message Chunk size: %d", pHttpParser->content_length ); + return 0; + } + +/*-----------------------------------------------------------*/ + + static int _httpParserOnChunkCompleteCallback( http_parser * pHttpParser ) + { + ( void ) pHttpParser; + IotLogDebug( "End of a HTTPS message Chunk complete callback." ); + return 0; + } +#endif /* if ( LIBRARY_LOG_LEVEL == IOT_LOG_DEBUG ) */ + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _receiveHttpsBodyAsync( _httpsResponse_t * pHttpsResponse ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + if( pHttpsResponse->pCallbacks->readReadyCallback ) + { + /* If there is still more body that has not been passed back to the user, then this callback is invoked again. */ + do + { + IotLogDebug( "Invoking the readReadyCallback for response %p.", pHttpsResponse ); + pHttpsResponse->pCallbacks->readReadyCallback( pHttpsResponse->pUserPrivData, + pHttpsResponse, + pHttpsResponse->bodyRxStatus, + pHttpsResponse->status ); + + if( pHttpsResponse->cancelled == true ) + { + IotLogDebug( "Cancelled HTTP response %p.", pHttpsResponse ); + status = IOT_HTTPS_RECEIVE_ABORT; + + /* We break out of the loop and do not goto clean up because we want to print debugging logs for + * the parser state and the networks status. */ + break; + } + } while( ( pHttpsResponse->parserState < PARSER_STATE_BODY_COMPLETE ) && ( pHttpsResponse->bodyRxStatus == IOT_HTTPS_OK ) ); + + if( HTTPS_FAILED( pHttpsResponse->bodyRxStatus ) ) + { + IotLogError( "Error receiving the HTTP response body for response %p. Error code: %d", + pHttpsResponse, + pHttpsResponse->bodyRxStatus ); + /* An error in the network or the parser takes precedence */ + status = pHttpsResponse->bodyRxStatus; + } + + if( pHttpsResponse->parserState < PARSER_STATE_BODY_COMPLETE ) + { + IotLogDebug( "Did not receive all of the HTTP response body for response %p.", + pHttpsResponse ); + } + } + + /* This GOTO cleanup is here for compiler warnings about using HTTPS_FUNCTION_EXIT_NO_CLEANUP() without a + * corresponding goto. */ + HTTPS_GOTO_CLEANUP(); + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _receiveHttpsBodySync( _httpsResponse_t * pHttpsResponse ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + _httpsConnection_t * pHttpsConnection = pHttpsResponse->pHttpsConnection; + + /* The header buffer is now filled or the end of the headers has been reached already. If part of the response + * body was read from the network into the header buffer, then it was already copied to the body buffer in the + * _httpParserOnBodyCallback(). */ + if( pHttpsResponse->pBody != NULL ) + { + /* If there is room left in the body buffer and we have not received the whole response body, + * then try to receive more. */ + if( ( ( pHttpsResponse->pBodyEnd - pHttpsResponse->pBodyCur ) > 0 ) && + ( pHttpsResponse->parserState < PARSER_STATE_BODY_COMPLETE ) ) + { + status = _receiveHttpsBody( pHttpsConnection, + pHttpsResponse ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error receiving the HTTPS response body for response %p. Error code: %d.", + pHttpsResponse, + status ); + HTTPS_GOTO_CLEANUP(); + } + } + else + { + IotLogDebug( "Received the maximum amount of HTTP body when filling the header buffer for response %p.", + pHttpsResponse ); + } + + /* If we don't reach the end of the HTTPS body in the parser, then we only received part of the body. + * The rest of body will be on the network socket. */ + if( HTTPS_SUCCEEDED( status ) && ( pHttpsResponse->parserState < PARSER_STATE_BODY_COMPLETE ) ) + { + IotLogError( "HTTPS response body does not fit into application provided response buffer at location %p " + "with length: %d", + pHttpsResponse->pBody, + pHttpsResponse->pBodyEnd - pHttpsResponse->pBody ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_MESSAGE_TOO_LARGE ); + } + } + else + { + IotLogDebug( "No response body was configure for response %p.", pHttpsResponse ); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Defining a network context for sending packets through the network interface. + * The declaration of the structure is mentioned in the transport_interface.h file. + */ +struct NetworkContext +{ + void * pNetworkConnection; /**< @brief The network connection used for sending packets on the network. */ + const IotNetworkInterface_t * pNetworkInterface; /**< @brief The network interface used to send packets on the network using the above network connection. */ +}; + +/*-----------------------------------------------------------*/ + +static int32_t transportRecv( NetworkContext_t * pNetworkContext, + void * pBuffer, + size_t bytesToRecv ) +{ + int32_t bytesReceived = -1; + + /* This dummy implementation is used for passing a non-NULL parameter. */ + ( void ) pNetworkContext; + ( void ) pBuffer; + ( void ) bytesToRecv; + + /* Always return the number of bytes requested or as many bytes as we can. */ + if( bytesToRecv > ( size_t ) INT32_MAX ) + { + bytesReceived = INT32_MAX; + } + else + { + bytesReceived = bytesToRecv; + } + + return bytesReceived; +} + +/*-----------------------------------------------------------*/ + +static int32_t transportSend( NetworkContext_t * pNetworkContext, + const void * pMessage, + size_t bytesToSend ) +{ + int32_t bytesSent = 0; + + /* Sending the bytes on the network using the network interface. */ + bytesSent = pNetworkContext->pNetworkInterface->send( pNetworkContext->pNetworkConnection, + ( const uint8_t * ) pMessage, + bytesToSend ); + + /* 0 bytes returned for the old HTTP library implied a network error. However, + * #HTTPClient_Send from coreHTTP will block while the return value is 0, so + * the return value must be manually set to -1 to also denote a network error. */ + if( bytesSent == 0 ) + { + bytesSent = -1; + } + + return bytesSent; +} + +/*-----------------------------------------------------------*/ + +static void _networkReceiveCallback( void * pNetworkConnection, + void * pReceiveContext ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + IotHttpsReturnCode_t flushStatus = IOT_HTTPS_OK; + IotHttpsReturnCode_t disconnectStatus = IOT_HTTPS_OK; + IotHttpsReturnCode_t scheduleStatus = IOT_HTTPS_OK; + _httpsConnection_t * pHttpsConnection = ( _httpsConnection_t * ) pReceiveContext; + _httpsResponse_t * pCurrentHttpsResponse = NULL; + _httpsRequest_t * pNextHttpsRequest = NULL; + IotLink_t * pQItem = NULL; + bool fatalDisconnect = false; + + /* The network connection is already in the connection context. */ + ( void ) pNetworkConnection; + + /* Get the response from the response queue. */ + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + pQItem = IotDeQueue_PeekHead( &( pHttpsConnection->respQ ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + /* If the receive callback is invoked and there is no response expected, then this a violation of the HTTP/1.1 + * protocol. */ + if( pQItem == NULL ) + { + IotLogError( "Received data on the network, when no response was expected..." ); + fatalDisconnect = true; + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_NETWORK_ERROR ); + } + + /* Set the current HTTP response context to use. */ + pCurrentHttpsResponse = IotLink_Container( _httpsResponse_t, pQItem, link ); + + /* If the receive callback has invoked, but the request associated with this response has not finished sending + * to the server, then this is a violation of the HTTP/1.1 protocol. */ + if( pCurrentHttpsResponse->reqFinishedSending == false ) + { + IotLogError( "Received response data on the network when the request was not finished sending. This is unexpected." ); + fatalDisconnect = true; + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_NETWORK_ERROR ); + } + + /* If the current response was cancelled, then don't bother receiving the headers and body. */ + if( pCurrentHttpsResponse->cancelled ) + { + IotLogDebug( "Response ID: %p was cancelled.", pCurrentHttpsResponse ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_RECEIVE_ABORT ); + } + + /* Reset the http-parser state to an initial state. This is done so that a new response can be parsed from the + * beginning. */ + pCurrentHttpsResponse->parserState = PARSER_STATE_NONE; + + /* Receive the response from the network. */ + /* Receive the headers first. */ + status = _receiveHttpsHeaders( pHttpsConnection, pCurrentHttpsResponse ); + + if( HTTPS_FAILED( status ) ) + { + if( status == IOT_HTTPS_PARSING_ERROR ) + { + /* There was an error parsing the HTTPS response body. This may be an indication of a server that does + * not adhere to protocol correctly. We should disconnect. */ + IotLogError( "Failed to parse the HTTPS headers for response %p, Error code: %d.", + pCurrentHttpsResponse, + status ); + fatalDisconnect = true; + } + else if( status == IOT_HTTPS_NETWORK_ERROR ) + { + /* Given the function signature of IotNetworkInterface_t.receive, we can only receive 0 to the number of bytes + * requested. Receiving less than the number of bytes requests is OK since we do not how much data is expected, so + * we ask for the full size of the receive buffer. Therefore, the only error that can be returned from receiving + * the headers or body is a timeout. We always disconnect from the network when there is a timeout because the + * server may be slow to respond. If the server happens to send the response later at the same time another response + * is waiting in the queue, then the workflow is corrupted. Pipelining is not current supported in this library. */ + IotLogError( "Network error receiving the HTTPS headers for response %p. Error code: %d", + pCurrentHttpsResponse, + status ); + fatalDisconnect = true; + } + else /* Any other error. */ + { + IotLogError( "Failed to retrive the HTTPS body for response %p. Error code: %d", pCurrentHttpsResponse, status ); + } + + HTTPS_GOTO_CLEANUP(); + } + + /* Check if we received all of the headers into the header buffer. */ + if( pCurrentHttpsResponse->parserState < PARSER_STATE_HEADERS_COMPLETE ) + { + IotLogDebug( "Headers received on the network did not all fit into the configured header buffer for response %p." + " The length of the headers buffer is: %d", + pCurrentHttpsResponse, + pCurrentHttpsResponse->pHeadersEnd - pCurrentHttpsResponse->pHeaders ); + /* It is not error if the headers did not all fit into the buffer. */ + } + + /* Receive the body. */ + if( pCurrentHttpsResponse->isAsync ) + { + status = _receiveHttpsBodyAsync( pCurrentHttpsResponse ); + } + else + { + /* Otherwise receive synchronously. */ + status = _receiveHttpsBodySync( pCurrentHttpsResponse ); + } + + if( HTTPS_FAILED( status ) ) + { + if( status == IOT_HTTPS_RECEIVE_ABORT ) + { + /* If the request was cancelled, this is logged, but does not close the connection. */ + IotLogDebug( "User cancelled during the async readReadyCallback() for response %p.", + pCurrentHttpsResponse ); + } + else if( status == IOT_HTTPS_PARSING_ERROR ) + { + /* There was an error parsing the HTTPS response body. This may be an indication of a server that does + * not adhere to protocol correctly. We should disconnect. */ + IotLogError( "Failed to parse the HTTPS body for response %p, Error code: %d.", + pCurrentHttpsResponse, + status ); + fatalDisconnect = true; + } + else if( status == IOT_HTTPS_NETWORK_ERROR ) + { + /* We always disconnect for a network error because failure to receive the HTTPS body will result in a + * corruption of the workflow. */ + IotLogError( "Network error receiving the HTTPS body for response %p. Error code: %d", + pCurrentHttpsResponse, + status ); + fatalDisconnect = true; + } + else /* Any other error. */ + { + IotLogError( "Failed to retrieve the HTTPS body for response %p. Error code: %d", pCurrentHttpsResponse, status ); + } + + HTTPS_GOTO_CLEANUP(); + } + + IOT_FUNCTION_CLEANUP_BEGIN(); + + /* Disconnect and return in the event of an out-of-order response. If a response is received out of order + * pCurrentHttpsResponse will be NULL because there will be no response in the connection's response queue. + * If a response is received out of order that is an indication of a rogue server. */ + if( fatalDisconnect && !pCurrentHttpsResponse ) + { + IotLogError( "An out-of-order response was received. The connection will be disconnected." ); + disconnectStatus = IotHttpsClient_Disconnect( pHttpsConnection ); + + if( HTTPS_FAILED( disconnectStatus ) ) + { + IotLogWarn( "Failed to disconnect after an out of order response. Error code: %d.", disconnectStatus ); + } + + /* In this case this routine returns immediately after to avoid further uses of pCurrentHttpsResponse. */ + return; + } + + /* Report errors back to the application. */ + if( HTTPS_FAILED( status ) ) + { + if( pCurrentHttpsResponse->isAsync && pCurrentHttpsResponse->pCallbacks->errorCallback ) + { + pCurrentHttpsResponse->pCallbacks->errorCallback( pCurrentHttpsResponse->pUserPrivData, NULL, pCurrentHttpsResponse, status ); + } + + pCurrentHttpsResponse->syncStatus = status; + } + + /* If this is not a persistent request, the server would have closed it after sending a response, but we + * disconnect anyways. If we are disconnecting there is is no point in wasting time + * flushing the network. If the network is being disconnected we also do not schedule any pending requests. */ + if( fatalDisconnect || pCurrentHttpsResponse->isNonPersistent ) + { + IotLogDebug( "Disconnecting response %p.", pCurrentHttpsResponse ); + disconnectStatus = IotHttpsClient_Disconnect( pHttpsConnection ); + + if( ( pCurrentHttpsResponse != NULL ) && pCurrentHttpsResponse->isAsync && pCurrentHttpsResponse->pCallbacks->connectionClosedCallback ) + { + pCurrentHttpsResponse->pCallbacks->connectionClosedCallback( pCurrentHttpsResponse->pUserPrivData, pHttpsConnection, disconnectStatus ); + } + + if( HTTPS_FAILED( disconnectStatus ) ) + { + IotLogWarn( "Failed to disconnect response %p. Error code: %d.", pCurrentHttpsResponse, disconnectStatus ); + } + + /* If we disconnect, we do not process anymore requests. */ + } + else + { + /* Set the processing state of the buffer to finished for completeness. This is also to prevent the parsing of the flush + * data from incrementing any pointer in the HTTP response context. */ + pCurrentHttpsResponse->bufferProcessingState = PROCESSING_STATE_FINISHED; + + /* Flush the socket of the rest of the data if there is data left from this response. We need to do this + * so that for the next request on this connection, there is not left over response from this request in + * the next response buffer. + * + * If a continuous stream of data is coming in from the connection, with an unknown end, we may not be able to + * flush the network data. It may sit here forever. A continuous stream should be ingested with the async workflow. + * + * All network errors are ignore here because network read will have read the data from network buffer despite + * errors. */ + flushStatus = _flushHttpsNetworkData( pHttpsConnection, pCurrentHttpsResponse ); + + if( flushStatus == IOT_HTTPS_PARSING_ERROR ) + { + IotLogWarn( "There an error parsing the network flush data. The network buffer might not be fully flushed." ); + } + else if( flushStatus != IOT_HTTPS_OK ) + { + IotLogDebug( "Network error when flushing the https network data: %d", flushStatus ); + } + + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + /* Get the next request to process. */ + pQItem = IotDeQueue_PeekHead( &( pHttpsConnection->reqQ ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + /* If there is a next request to process, then add a dispatch task to the queue. */ + if( pQItem != NULL ) + { + /* Set this next request to send. */ + pNextHttpsRequest = IotLink_Container( _httpsRequest_t, pQItem, link ); + + if( pNextHttpsRequest->scheduled == false ) + { + IotLogDebug( "Request %p is next in the queue. Now scheduling a task to send the request.", pNextHttpsRequest ); + scheduleStatus = _scheduleHttpsRequestSend( pNextHttpsRequest ); + + /* If there was an error with scheduling the new task, then report it. */ + if( HTTPS_FAILED( scheduleStatus ) ) + { + IotLogError( "Error scheduling HTTPS request %p. Error code: %d", pNextHttpsRequest, scheduleStatus ); + + if( pNextHttpsRequest->isAsync && pNextHttpsRequest->pCallbacks->errorCallback ) + { + pNextHttpsRequest->pCallbacks->errorCallback( pNextHttpsRequest->pUserPrivData, pNextHttpsRequest, NULL, scheduleStatus ); + } + else + { + pNextHttpsRequest->pHttpsResponse->syncStatus = scheduleStatus; + } + } + } + } + else + { + IotLogDebug( "Network receive callback found the request queue empty. A network send task was not scheduled." ); + } + } + + /* Dequeue response from the response queue now that it is finished. */ + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + + /* There could be a scenario where the request fails to send and the network server still responds, + * In this case, the failed response will have been cancelled and removed from the queue. If the network + * server still got a response, then the safest way to remove the current response is to remove it explicitly + * from the queue instead of dequeuing the header of the queue which might not be the current response. */ + if( IotLink_IsLinked( &( pCurrentHttpsResponse->link ) ) ) + { + IotDeQueue_Remove( &( pCurrentHttpsResponse->link ) ); + } + + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + /* The first if-case below notifies IotHttpsClient_SendSync() that the response is finished receiving. When + * IotHttpsClient_SendSync() returns the user is allowed to modify the user buffer used for the response context. + * In the asynchronous case, the responseCompleteCallback notifies the application that the user buffer used for the + * response context can be modified. Posting to the respFinishedSem or calling the responseCompleteCallback MUST be + * mutually exclusive by wrapping in an if/else. If these were separate if-cases, then there could be a context + * switch in between where the application modifies the buffer causing the next if-case to be executed. */ + if( pCurrentHttpsResponse->isAsync == false ) + { + IotSemaphore_Post( &( pCurrentHttpsResponse->respFinishedSem ) ); + } + else if( pCurrentHttpsResponse->pCallbacks->responseCompleteCallback ) + { + /* Signal to a synchronous response that the response is complete. */ + pCurrentHttpsResponse->pCallbacks->responseCompleteCallback( pCurrentHttpsResponse->pUserPrivData, pCurrentHttpsResponse, status, pCurrentHttpsResponse->status ); + } +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _createHttpsConnection( IotHttpsConnectionHandle_t * pConnHandle, + IotHttpsConnectionInfo_t * pConnInfo ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + IotNetworkError_t networkStatus = IOT_NETWORK_SUCCESS; + + /* The maximum string length of the ALPN protocols is configured in IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH. + * The +1 is for the NULL terminator needed by IotNetworkCredentials_t.pAlpnProtos. */ + char pAlpnProtos[ IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH + 1 ] = { 0 }; + + /* The maximum string length of the Server host name is configured in IOT_HTTPS_MAX_HOST_NAME_LENGTH. + * This +1 is for the NULL terminator needed by IotNetworkServerInfo_t.pHostName. */ + char pHostName[ IOT_HTTPS_MAX_HOST_NAME_LENGTH + 1 ] = { 0 }; + bool connectionMutexCreated = false; + IotNetworkServerInfo_t networkServerInfo = { 0 }; + IotNetworkCredentials_t networkCredentials = { 0 }; + _httpsConnection_t * pHttpsConnection = NULL; + IotNetworkCredentials_t * pNetworkCredentials = NULL; + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pConnInfo->userBuffer.pBuffer ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pConnInfo->pNetworkInterface ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pConnInfo->pAddress ); + HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( pConnInfo->addressLen > 0 ); + + /* Make sure the connection context can fit in the user buffer. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( pConnInfo->userBuffer.bufferLen >= connectionUserBufferMinimumSize, + IOT_HTTPS_INSUFFICIENT_MEMORY, + "Buffer size is too small to initialize the connection context. User buffer size: %d, required minimum size; %d.", + ( *pConnInfo ).userBuffer.bufferLen, + connectionUserBufferMinimumSize ); + + /* Make sure that the server address does not exceed the maximum permitted length. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( pConnInfo->addressLen <= IOT_HTTPS_MAX_HOST_NAME_LENGTH, + IOT_HTTPS_INVALID_PARAMETER, + "IotHttpsConnectionInfo_t.addressLen has a host name length %d that exceeds maximum length %d.", + pConnInfo->addressLen, + IOT_HTTPS_MAX_HOST_NAME_LENGTH ); + + /* Make sure that the ALPN protocols does not exceed the maximum permitted length. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( pConnInfo->alpnProtocolsLen <= IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH, + IOT_HTTPS_INVALID_PARAMETER, + "IotHttpsConnectionInfo_t.alpnProtocolsLen of %d exceeds the configured maximum protocol length %d. See IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH for more information.", + pConnInfo->alpnProtocolsLen, + IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH ); + + pHttpsConnection = ( _httpsConnection_t * ) ( pConnInfo->userBuffer.pBuffer ); + + /* Start with the disconnected state. */ + pHttpsConnection->isConnected = false; + + /* Initialize disconnection state keeper. */ + pHttpsConnection->isDestroyed = false; + + /* Initialize the queue of responses and requests. */ + IotDeQueue_Create( &( pHttpsConnection->reqQ ) ); + IotDeQueue_Create( &( pHttpsConnection->respQ ) ); + + /* This timeout is used to wait for a response on the connection as well as + * for the timeout for the connect operation. */ + if( pConnInfo->timeout == 0 ) + { + pHttpsConnection->timeout = IOT_HTTPS_RESPONSE_WAIT_MS; + } + else + { + pHttpsConnection->timeout = pConnInfo->timeout; + } + + /* pNetworkInterface contains all the routines to be able to send/receive data on the network. */ + pHttpsConnection->pNetworkInterface = pConnInfo->pNetworkInterface; + + /* The address from the connection configuration information is copied to a local buffer because a NULL pointer + * is required in IotNetworkServerInfo_t.pHostName. IotNetworkServerInfo_t contains the server information needed + * by the network interface to create the connection. */ + memcpy( pHostName, pConnInfo->pAddress, pConnInfo->addressLen ); + pHostName[ pConnInfo->addressLen ] = '\0'; + /* Set it in the IOT network abstractions server information parameter. */ + networkServerInfo.pHostName = pHostName; + networkServerInfo.port = pConnInfo->port; + + /* If this is TLS connection, then set the network credentials. */ + if( ( pConnInfo->flags & IOT_HTTPS_IS_NON_TLS_FLAG ) == 0 ) + { + if( pConnInfo->flags & IOT_HTTPS_DISABLE_SNI ) + { + networkCredentials.disableSni = true; + } + else + { + networkCredentials.disableSni = false; + } + + if( pConnInfo->pAlpnProtocols != NULL ) + { + /* The alpn protocol strings in IotNetworkCredentials_t require a NULL terminator, so the alpn protocol + * string in the connection configuration information is copied to a local buffer to append the NULL + * terminator. */ + memcpy( pAlpnProtos, pConnInfo->pAlpnProtocols, pConnInfo->alpnProtocolsLen ); + pAlpnProtos[ pConnInfo->alpnProtocolsLen ] = '\0'; + networkCredentials.pAlpnProtos = pAlpnProtos; + } + else + { + networkCredentials.pAlpnProtos = NULL; + } + + /* If any of these are NULL a network error will result when trying to make the connection. Because there is + * no invalid memory access resulting from these configurations being NULL, it is not check at the start + * of the function. */ + networkCredentials.pRootCa = pConnInfo->pCaCert; + networkCredentials.rootCaSize = pConnInfo->caCertLen; + networkCredentials.pClientCert = pConnInfo->pClientCert; + networkCredentials.clientCertSize = pConnInfo->clientCertLen; + networkCredentials.pPrivateKey = pConnInfo->pPrivateKey; + networkCredentials.privateKeySize = pConnInfo->privateKeyLen; + + pNetworkCredentials = &networkCredentials; + } + else + { + /* create() takes a NULL if there is no TLS configuration. */ + pNetworkCredentials = NULL; + } + + /* create() will connect to the server specified in addition to creating other network layer + * specific resources. */ + networkStatus = pHttpsConnection->pNetworkInterface->create( &networkServerInfo, + pNetworkCredentials, + &( pHttpsConnection->pNetworkConnection ) ); + + /* Check to see if the network connection succeeded. If it did not succeed, + * then the output parameter pConnHandle will be used to return NULL and the + * function returns an error. */ + if( networkStatus != IOT_NETWORK_SUCCESS ) + { + IotLogError( "Failed to connect to the server at %.*s on port %d with error: %d", + pConnInfo->addressLen, + pConnInfo->pAddress, + pConnInfo->port, + networkStatus ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_CONNECTION_ERROR ); + } + + /* The connection succeeded so set the state to connected. */ + pHttpsConnection->isConnected = true; + + /* The receive callback is invoked by the network layer when data is ready + * to be read from the network. */ + networkStatus = pHttpsConnection->pNetworkInterface->setReceiveCallback( pHttpsConnection->pNetworkConnection, + _networkReceiveCallback, + pHttpsConnection ); + + if( networkStatus != IOT_NETWORK_SUCCESS ) + { + IotLogError( "Failed to connect to set the HTTPS receive callback. " ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + + /* Connection was successful, so create synchronization primitives. */ + + connectionMutexCreated = IotMutex_Create( &( pHttpsConnection->connectionMutex ), false ); + + if( !connectionMutexCreated ) + { + IotLogError( "Failed to create an internal mutex." ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + + /* Return the new connection information. */ + *pConnHandle = pHttpsConnection; + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + /* If we failed anywhere in the connection process, then destroy the semaphores created. */ + if( HTTPS_FAILED( status ) ) + { + /* If there was a connect was successful, disconnect from the network. */ + if( ( pHttpsConnection != NULL ) && ( pHttpsConnection->isConnected ) ) + { + _networkDisconnect( pHttpsConnection ); + _networkDestroy( pHttpsConnection ); + } + + if( connectionMutexCreated ) + { + IotMutex_Destroy( &( pHttpsConnection->connectionMutex ) ); + } + + /* Set the connection handle as NULL if everything failed. */ + *pConnHandle = NULL; + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +static void _networkDisconnect( _httpsConnection_t * pHttpsConnection ) +{ + IotNetworkError_t networkStatus = IOT_NETWORK_SUCCESS; + + networkStatus = pHttpsConnection->pNetworkInterface->close( pHttpsConnection->pNetworkConnection ); + + if( networkStatus != IOT_NETWORK_SUCCESS ) + { + IotLogWarn( "Failed to shutdown the socket with error code: %d", networkStatus ); + } +} + +/*-----------------------------------------------------------*/ + +static void _networkDestroy( _httpsConnection_t * pHttpsConnection ) +{ + IotNetworkError_t networkStatus = IOT_NETWORK_SUCCESS; + + networkStatus = pHttpsConnection->pNetworkInterface->destroy( pHttpsConnection->pNetworkConnection ); + + if( networkStatus != IOT_NETWORK_SUCCESS ) + { + IotLogWarn( "Failed to shutdown the socket with error code: %d", networkStatus ); + } +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _networkRecv( _httpsConnection_t * pHttpsConnection, + uint8_t * pBuf, + size_t bufLen, + size_t * numBytesRecv ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + /* The HTTP server could send the header and the body in two separate TCP packets. If that is the case, then + * receiveUpTo will return return the full headers first. Then on a second call, the body will be returned. + * If the http parser receives just the headers despite the content length being greater than */ + *numBytesRecv = pHttpsConnection->pNetworkInterface->receiveUpto( pHttpsConnection->pNetworkConnection, + pBuf, + bufLen ); + + IotLogDebug( "The network interface receive returned %d.", *numBytesRecv ); + + /* We return IOT_HTTPS_NETWORK_ERROR only if we receive nothing. Receiving less + * data than requested is okay because it is not known in advance how much data + * we are going to receive and therefore we request for the available buffer + * size. */ + if( *numBytesRecv == 0 ) + { + IotLogError( "Error in receiving the HTTPS response message. Socket Error code %d", *numBytesRecv ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_NETWORK_ERROR ); + + /* A network error is returned when zero is received because that would indicate that either there + * was a network error or there was a timeout reading data. If there was timeout reading data, then + * the server was too slow to respond. If the server is too slow to respond, then a network error must + * be returned to trigger a connection close. The connection must close after the network error so + * that the response from this request does not piggyback on the response from the next request. */ + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _parseHttpsMessage( _httpParserInfo_t * pHttpParserInfo, + char * pBuf, + size_t len ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + size_t parsedBytes = 0; + const char * pHttpParserErrorDescription = NULL; + http_parser * pHttpParser = &( pHttpParserInfo->responseParser ); + + /* Disable -Wunused-but-set-variable for local variables used for logging. */ + ( void ) parsedBytes; + ( void ) pHttpParserErrorDescription; + + IotLogDebug( "Now parsing HTTP message buffer to process a response." ); + parsedBytes = pHttpParserInfo->parseFunc( pHttpParser, &_httpParserSettings, pBuf, len ); + IotLogDebug( "http-parser parsed %d bytes out of %d specified.", parsedBytes, len ); + + /* If the parser fails with HPE_CLOSED_CONNECTION or HPE_INVALID_CONSTANT that simply means there + * was data beyond the end of the message. We do not fail in this case because we give the whole + * header buffer or body buffer to the parser even if it is only partly filled with data. + * Errors <= HPE_CB_chunk_complete means that a non-zero number was returned from some callback. + * A nonzero number is returned from some callbacks when we want to stop the parser early + * for example - a HEAD request or the user explicitly asked to ignore the body by not + * providing the body buffer. */ + if( ( pHttpParser->http_errno != 0 ) && + ( HTTP_PARSER_ERRNO( pHttpParser ) != HPE_CLOSED_CONNECTION ) && + ( HTTP_PARSER_ERRNO( pHttpParser ) != HPE_INVALID_CONSTANT ) && + ( HTTP_PARSER_ERRNO( pHttpParser ) > HPE_CB_chunk_complete ) ) + { + pHttpParserErrorDescription = http_errno_description( HTTP_PARSER_ERRNO( pHttpParser ) ); + IotLogError( "http_parser failed on the http response with error: %s", pHttpParserErrorDescription ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_PARSING_ERROR ); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static void _incrementNextLocationToWriteBeyondParsed( uint8_t ** pBufCur, + uint8_t ** pBufEnd ) +{ + /* There is an edge case where the final one or two character received in the header buffer is part of + * the header field separator ": " or part of the header line end "\r\n" delimiters. When this + * happens, pHeadersCur in the response will point not the end of the buffer, but to a character in + * the delimiter. For example: + * Let's say this is our current header buffer after receiving and parsing: + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1: value1\r\n"] + * pHeadersCur will point to \r because the http-parser does not invoke a callback on the + * delimiters. Since no callback is invoked, pHeadersCur is not incremented. pHeadersEnd points to + * the end of the header buffer which is the unwritable memory location right after the final '\n'. + * Because pHeadersCur is less than pHeaderEnd we loop again and receive on the network causing the + * buffer to look like this: + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1: value1he"] + * Which will cause an incorrect header1 value to be read if the application decides to read it with + * IotHttpsClient_ReadHeader(). + * + * If our header buffer looks like: + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1: "] + * then pHeaderCur will point to the colon. + * + * If our header buffer looks like: + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1:"] + * then pHeaderCur will point to the colon. + * + * If our header buffer looks like + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1: value1 "] + * then http-parser will consider that space as part of value1. + * + * If our header buffer looks like + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1: value1\r"] + * then pHeaderCur will point to the carriage return. + * + * If our header buffer looks like + * ["HTTP/1.1 200 OK\r\n\header0: value0\r\nheader1: value1\r\n"] + * As explained in the example above, pHeaderCur will point to the carriage return. + * + * If we somehow receive a partial HTTP response message in our zeroed-out header buffer: + * case 1: ["HTTP/1.1 200 OK\r\nheader0: value0\r\nheader1: value1\r\0\0\0\0\0\0\0"] + * case 2: ["HTTP/1.1 200 OK\r\nheader0: value0\r\nheader1: value1\r\n\0\0\0\0\0\0"] + * case 3: ["HTTP/1.1 200 OK\r\nheader0: value0\r\nheader1:\0\0\0\0\0\0\0\0\0\0\0"] + * case 4: ["HTTP/1.1 200 OK\r\nheader0: value0\r\nheader1: \0\0\0\0\0\0\0\0\0\0\0"] + * then parser may fail or append all of the NULL characters to a header field name or value. */ + while( *pBufCur < *pBufEnd ) + { + if( **pBufCur == CARRIAGE_RETURN_CHARACTER ) + { + ( *pBufCur )++; + } + else if( **pBufCur == NEWLINE_CHARACTER ) + { + ( *pBufCur )++; + break; + } + else if( **pBufCur == COLON_CHARACTER ) + { + ( *pBufCur )++; + } + else if( ( **pBufCur == SPACE_CHARACTER ) && ( *( *pBufCur - 1 ) == COLON_CHARACTER ) ) + { + ( *pBufCur )++; + break; + } + else + { + break; + } + } +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _receiveHttpsMessage( _httpsConnection_t * pHttpsConnection, + _httpParserInfo_t * pHttpParserInfo, + IotHttpsResponseParserState_t * pCurrentParserState, + IotHttpsResponseParserState_t finalParserState, + IotHttpsResponseBufferState_t currentBufferProcessingState, + uint8_t ** pBufCur, + uint8_t ** pBufEnd ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + size_t numBytesRecv = 0; + + /* The final parser state is either the end of the header lines or the end of the entity body. This state is set in + * the http-parser callbacks. */ + while( ( *pCurrentParserState < finalParserState ) && ( *pBufEnd - *pBufCur > 0 ) ) + { + status = _networkRecv( pHttpsConnection, + *pBufCur, + *pBufEnd - *pBufCur, + &numBytesRecv ); + + /* A network error in _networkRecv is returned only when we received zero bytes. In that case, there is + * no point in parsing we return immediately with the network error. */ + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Network error receiving the HTTPS response headers. Error code: %d", status ); + break; + } + + status = _parseHttpsMessage( pHttpParserInfo, ( char * ) ( *pBufCur ), numBytesRecv ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to parse the message buffer with error: %d", pHttpParserInfo->responseParser.http_errno ); + break; + } + + /* If the current buffer being filled is the header buffer, then \r\n header line separators should not get + * overwritten on the next network read. See _incrementNextLocationToWriteBeyondParsed() for more + * information. */ + if( currentBufferProcessingState == PROCESSING_STATE_FILLING_HEADER_BUFFER ) + { + _incrementNextLocationToWriteBeyondParsed( pBufCur, pBufEnd ); + } + + /* The _httpsResponse->pHeadersCur pointer is updated in the http_parser callbacks. */ + IotLogDebug( "There is %d of space left in the buffer.", *pBufEnd - *pBufCur ); + } + + /* If we did not reach the end of the headers or body in the parser callbacks, then the buffer configured does not + * fit all of that part of the HTTP message. */ + if( *pCurrentParserState < finalParserState ) + { + IotLogDebug( "There are still more data on the network. It could not fit into the specified length %d.", + *pBufEnd - *pBufCur ); + } + + HTTPS_GOTO_CLEANUP(); + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _receiveHttpsHeaders( _httpsConnection_t * pHttpsConnection, + _httpsResponse_t * pHttpsResponse ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + pHttpsResponse->bufferProcessingState = PROCESSING_STATE_FILLING_HEADER_BUFFER; + + IotLogDebug( "Now attempting to receive the HTTP response headers into a buffer with length %d.", + pHttpsResponse->pHeadersEnd - pHttpsResponse->pHeadersCur ); + + status = _receiveHttpsMessage( pHttpsConnection, + &( pHttpsResponse->httpParserInfo ), + &( pHttpsResponse->parserState ), + PARSER_STATE_HEADERS_COMPLETE, + PROCESSING_STATE_FILLING_HEADER_BUFFER, + &( pHttpsResponse->pHeadersCur ), + &( pHttpsResponse->pHeadersEnd ) ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error receiving the HTTP headers. Error code %d", status ); + HTTPS_GOTO_CLEANUP(); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +/* _receiveHttpsHeaders() must be called first before this function is called. */ +static IotHttpsReturnCode_t _receiveHttpsBody( _httpsConnection_t * pHttpsConnection, + _httpsResponse_t * pHttpsResponse ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + IotLogDebug( "Now attempting to receive the HTTP response body into a buffer with length %d.", + pHttpsResponse->pBodyEnd - pHttpsResponse->pBodyCur ); + + pHttpsResponse->bufferProcessingState = PROCESSING_STATE_FILLING_BODY_BUFFER; + + status = _receiveHttpsMessage( pHttpsConnection, + &( pHttpsResponse->httpParserInfo ), + &( pHttpsResponse->parserState ), + PARSER_STATE_BODY_COMPLETE, + PROCESSING_STATE_FILLING_BODY_BUFFER, + &( pHttpsResponse->pBodyCur ), + &( pHttpsResponse->pBodyEnd ) ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error receiving the HTTP body. Error code %d", status ); + HTTPS_GOTO_CLEANUP(); + } + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + IotLogDebug( "The remaining content length on the network is %llu.", + pHttpsResponse->httpParserInfo.responseParser.content_length ); + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _flushHttpsNetworkData( _httpsConnection_t * pHttpsConnection, + _httpsResponse_t * pHttpsResponse ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + static uint8_t flushBuffer[ IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE ] = { 0 }; + const char * pHttpParserErrorDescription = NULL; + IotHttpsReturnCode_t parserStatus = IOT_HTTPS_OK; + IotHttpsReturnCode_t networkStatus = IOT_HTTPS_OK; + size_t numBytesRecv = 0; + + /* Disable -Wunused-but-set-variable for local variables used for logging. */ + ( void ) pHttpParserErrorDescription; + + /* Even if there is not body, the parser state will become body complete after the headers finish. */ + while( pHttpsResponse->parserState < PARSER_STATE_BODY_COMPLETE ) + { + IotLogDebug( "Now clearing the rest of the response data on the socket. " ); + networkStatus = _networkRecv( pHttpsConnection, flushBuffer, IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE, &numBytesRecv ); + + /* Run this through the parser so that we can get the end of the HTTP message, instead of simply timing out the socket to stop. + * If we relied on the socket timeout to stop reading the network socket, then the server may close the connection. */ + parserStatus = _parseHttpsMessage( &( pHttpsResponse->httpParserInfo ), ( char * ) flushBuffer, numBytesRecv ); + + if( HTTPS_FAILED( parserStatus ) ) + { + pHttpParserErrorDescription = http_errno_description( HTTP_PARSER_ERRNO( &pHttpsResponse->httpParserInfo.responseParser ) ); + IotLogError( "Network Flush: Failed to parse the response body buffer with error: %d, %s", + pHttpsResponse->httpParserInfo.responseParser.http_errno, + pHttpParserErrorDescription ); + break; + } + + /* If there is a network error then we want to stop clearing out the buffer. */ + if( HTTPS_FAILED( networkStatus ) ) + { + IotLogWarn( "Network Flush: Error receiving the rest of the HTTP response. Error code: %d", + networkStatus ); + break; + } + } + + /* All network errors except timeouts are returned. */ + if( HTTPS_FAILED( networkStatus ) ) + { + status = networkStatus; + } + else + { + status = parserStatus; + } + + HTTPS_GOTO_CLEANUP(); + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _sendHttpsHeadersAndBody( _httpsConnection_t * pHttpsConnection, + _httpsRequest_t * pHttpsRequest ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPStatus_t coreHttpStatus = HTTPSuccess; + HTTPRequestHeaders_t coreHttpRequestHeaders; + HTTPResponse_t coreHttpResponse; + TransportInterface_t transportInterface; + NetworkContext_t networkContext; + char pHttpsMinimalMockedResponse[ FAST_MACRO_STRLEN( HTTPS_MINIMAL_MOCKED_RESPONSE ) + 1 ] = HTTPS_MINIMAL_MOCKED_RESPONSE; + uint32_t sendFlags = 0; + + coreHttpRequestHeaders.pBuffer = pHttpsRequest->pHeaders; + coreHttpRequestHeaders.bufferLen = ( size_t ) ( pHttpsRequest->pHeadersEnd - pHttpsRequest->pHeaders ); + coreHttpRequestHeaders.headersLen = ( size_t ) ( pHttpsRequest->pHeadersCur - pHttpsRequest->pHeaders ); + + networkContext.pNetworkConnection = pHttpsConnection->pNetworkConnection; + networkContext.pNetworkInterface = pHttpsConnection->pNetworkInterface; + + transportInterface.send = transportSend; + transportInterface.recv = transportRecv; + transportInterface.pNetworkContext = &networkContext; + + /* Fill buffer with a mocked response so that http-parser returns successfully. */ + memset( &coreHttpResponse, 0, sizeof( HTTPResponse_t ) ); + coreHttpResponse.pBuffer = ( uint8_t * ) pHttpsMinimalMockedResponse; + coreHttpResponse.bufferLen = FAST_MACRO_STRLEN( HTTPS_MINIMAL_MOCKED_RESPONSE ); + + coreHttpStatus = HTTPClient_Send( &transportInterface, + &coreHttpRequestHeaders, + pHttpsRequest->pBody, + ( size_t ) pHttpsRequest->bodyLength, + &coreHttpResponse, + sendFlags ); + status = _shimConvertStatus( coreHttpStatus ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error sending the HTTPS request with error code: %d", status ); + HTTPS_GOTO_CLEANUP(); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static void _sendHttpsRequest( _httpsRequest_t * pHttpsRequest ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + _httpsConnection_t * pHttpsConnection = pHttpsRequest->pHttpsConnection; + _httpsResponse_t * pHttpsResponse = pHttpsRequest->pHttpsResponse; + IotHttpsReturnCode_t disconnectStatus = IOT_HTTPS_OK; + IotHttpsReturnCode_t scheduleStatus = IOT_HTTPS_OK; + IotLink_t * pQItem = NULL; + _httpsRequest_t * pNextHttpsRequest = NULL; + + IotLogDebug( "Task with request ID: %p started.", pHttpsRequest ); + + if( pHttpsRequest->cancelled == true ) + { + IotLogDebug( "Request ID: %p was cancelled.", pHttpsRequest ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_SEND_ABORT ); + } + + /* To protect against out of order network data from a rouge server, signal that the request is + * not finished sending. */ + pHttpsResponse->reqFinishedSending = false; + + /* Queue the response to expect from the network. */ + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + IotDeQueue_EnqueueTail( &( pHttpsConnection->respQ ), &( pHttpsResponse->link ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + /* Get the headers from the application. For a synchronous request the application should have appended extra + * headers before this point. */ + if( pHttpsRequest->isAsync && pHttpsRequest->pCallbacks->appendHeaderCallback ) + { + pHttpsRequest->pCallbacks->appendHeaderCallback( pHttpsRequest->pUserPrivData, pHttpsRequest ); + } + + if( pHttpsRequest->cancelled == true ) + { + IotLogDebug( "Request ID: %p was cancelled.", pHttpsRequest ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_SEND_ABORT ); + } + + /* Ask the user for data to write body to the network. We only ask the user once. This is so that + * we can calculate the Content-Length to send.*/ + if( pHttpsRequest->isAsync && pHttpsRequest->pCallbacks->writeCallback ) + { + /* If there is data, then a Content-Length header value will be provided and we send the headers + * before that user data. */ + pHttpsRequest->pCallbacks->writeCallback( pHttpsRequest->pUserPrivData, pHttpsRequest ); + } + + if( HTTPS_FAILED( pHttpsRequest->bodyTxStatus ) ) + { + IotLogError( "Failed to send the headers and body over the network during the writeCallback. Error code: %d.", + status ); + HTTPS_SET_AND_GOTO_CLEANUP( pHttpsRequest->bodyTxStatus ); + } + + if( pHttpsRequest->cancelled == true ) + { + IotLogDebug( "Request ID: %p was cancelled.", pHttpsRequest ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_SEND_ABORT ); + } + + /* If this is a synchronous request then the header and body were configured beforehand. The header and body + * are sent now. For an asynchronous request, the header and body are sent in IotHttpsClient_WriteRequestBody() + * which is to be invoked in #IotHttpsClientCallbacks_t.writeCallback(). If the application never invokes + * IotHttpsClient_WriteRequestBody(), then pHttpsRequest->pBody will be NULL. In this case we still want to + * send whatever headers we have. */ + if( ( pHttpsRequest->isAsync == false ) || + ( ( pHttpsRequest->isAsync ) && ( pHttpsRequest->pBody == NULL ) ) ) + { + status = _sendHttpsHeadersAndBody( pHttpsConnection, pHttpsRequest ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to send the headers and body on the network. Error code: %d", status ); + HTTPS_GOTO_CLEANUP(); + } + } + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + /* The request has finished sending. This indicates to the network receive callback that the request was + * finished, so a response received on the network is valid. This also lets a possible application called + * IotHttpsClient_Disconnect() know that the connection is not busy, so the connection can be destroyed. */ + pHttpsResponse->reqFinishedSending = true; + + if( HTTPS_FAILED( status ) ) + { + /* If the headers or body failed to send, then there should be no response expected from the server. */ + /* Cancel the response incase there is a response from the server. */ + _cancelResponse( pHttpsResponse ); + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + + if( IotLink_IsLinked( &( pHttpsResponse->link ) ) ) + { + IotDeQueue_Remove( &( pHttpsResponse->link ) ); + } + + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + /* Set the error status in the sync workflow. */ + pHttpsResponse->syncStatus = status; + + /* Return the error status or cancel status to the application for an asynchronous workflow. */ + if( pHttpsRequest->isAsync && pHttpsRequest->pCallbacks->errorCallback ) + { + pHttpsRequest->pCallbacks->errorCallback( pHttpsRequest->pUserPrivData, pHttpsRequest, NULL, status ); + } + + /* We close the connection on all network errors. All network errors in receiving the response, close the + * connection. For consistency in behavior, if there is a network error in send, the connection should also be + * closed. */ + if( status == IOT_HTTPS_NETWORK_ERROR ) + { + IotLogDebug( "Disconnecting request %p.", pHttpsRequest ); + disconnectStatus = IotHttpsClient_Disconnect( pHttpsConnection ); + + if( pHttpsRequest->isAsync && pHttpsRequest->pCallbacks->connectionClosedCallback ) + { + pHttpsRequest->pCallbacks->connectionClosedCallback( pHttpsRequest->pUserPrivData, + pHttpsConnection, + disconnectStatus ); + } + + if( HTTPS_FAILED( disconnectStatus ) ) + { + IotLogWarn( "Failed to disconnect request %p. Error code: %d.", pHttpsRequest, disconnectStatus ); + } + } + else + { + /* Because this request failed, the network receive callback may never be invoked to schedule other possible + * requests in the queue. In order to avoid requests never getting scheduled on a connected connection, + * the first item in the queue is scheduled if it can be. */ + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + + /* Get the next item in the queue by removing this current (which is the first) and peeking at the head + * again. */ + IotDeQueue_Remove( &( pHttpsRequest->link ) ); + pQItem = IotDeQueue_PeekHead( &( pHttpsConnection->reqQ ) ); + /* This current request is put back because it is removed again for all cases at the end of this routine. */ + IotDeQueue_EnqueueHead( &( pHttpsConnection->reqQ ), &( pHttpsRequest->link ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + if( pQItem != NULL ) + { + /* Set this next request to send. */ + pNextHttpsRequest = IotLink_Container( _httpsRequest_t, pQItem, link ); + + if( pNextHttpsRequest->scheduled == false ) + { + IotLogDebug( "Request %p is next in the queue. Now scheduling a task to send the request.", pNextHttpsRequest ); + scheduleStatus = _scheduleHttpsRequestSend( pNextHttpsRequest ); + + /* If there was an error with scheduling the new task, then report it. */ + if( HTTPS_FAILED( scheduleStatus ) ) + { + IotLogError( "Error scheduling HTTPS request %p. Error code: %d", pNextHttpsRequest, scheduleStatus ); + + if( pNextHttpsRequest->isAsync && pNextHttpsRequest->pCallbacks->errorCallback ) + { + pNextHttpsRequest->pCallbacks->errorCallback( pNextHttpsRequest->pUserPrivData, pNextHttpsRequest, NULL, scheduleStatus ); + } + else + { + pNextHttpsRequest->pHttpsResponse->syncStatus = scheduleStatus; + } + } + } + } + } + + /* Post to the response finished semaphore to unlock the application waiting on a synchronous request. */ + if( pHttpsRequest->isAsync == false ) + { + IotSemaphore_Post( &( pHttpsResponse->respFinishedSem ) ); + } + else if( pHttpsRequest->pCallbacks->responseCompleteCallback ) + { + /* Call the response complete callback. We always call this even if we did not receive the response to + * let the application know that the request has completed. */ + pHttpsRequest->pCallbacks->responseCompleteCallback( pHttpsRequest->pUserPrivData, NULL, status, 0 ); + } + } + + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + /* Now that the current request is finished, we dequeue the current request from the queue. */ + IotDeQueue_DequeueHead( &( pHttpsConnection->reqQ ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + /* This routine returns a void so there is no HTTPS_FUNCTION_CLEANUP_END();. */ +} + +/*-----------------------------------------------------------*/ + +static void _dispatchTaskRoutine( void * pParameters ) +{ + ( void ) pParameters; + + _httpsRequest_t * pHttpsRequest = NULL; + + for( ; ; ) + { + /* If there are no requests in the dispatch queue, try again. */ + if( xQueueReceive( dispatchQueue, + &pHttpsRequest, + IOT_HTTPS_QUEUE_RECV_TICKS ) == pdFALSE ) + { + IotLogDebug( "No requests to send. Trying again." ); + continue; + } + + _sendHttpsRequest( pHttpsRequest ); + } +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t _scheduleHttpsRequestSend( _httpsRequest_t * pHttpsRequest ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + BaseType_t queueStatus = pdTRUE; + + /* Set the request to scheduled even if scheduling fails. */ + pHttpsRequest->scheduled = true; + + queueStatus = xQueueSendToBack( dispatchQueue, &pHttpsRequest, IOT_HTTPS_QUEUE_SEND_TICKS ); + + /* Occurs when the queue remains full for #IOT_HTTPS_QUEUE_SEND_TICKS. */ + if( queueStatus != pdTRUE ) + { + IotLogError( "Failed to add request to full dispatch queue of size %u. Error code: %d", + IOT_HTTPS_DISPATCH_QUEUE_SIZE, + ( int ) queueStatus ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t _addRequestToConnectionReqQ( _httpsRequest_t * pHttpsRequest ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + _httpsConnection_t * pHttpsConnection = pHttpsRequest->pHttpsConnection; + bool scheduleRequest = false; + + /* Log information about the request*/ + IotLogDebug( "Now queueing request %p.", pHttpsRequest ); + + if( pHttpsRequest->isNonPersistent ) + { + IotLogDebug( "Request %p is non-persistent.", pHttpsRequest ); + } + else + { + IotLogDebug( "Request %p is persistent. ", pHttpsRequest ); + } + + if( pHttpsRequest->isAsync ) + { + IotLogDebug( " Request %p is asynchronous.", pHttpsRequest ); + } + else + { + IotLogDebug( " Request %p is synchronous.", pHttpsRequest ); + } + + /* This is a new request and has not been scheduled if this routine is called. */ + pHttpsRequest->scheduled = false; + + /* Place the request into the queue. */ + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + + /* If there is an active response, scheduling the next request at the same time may corrupt the workflow. Part of + * the next response for the next request may be present in the currently receiving response's buffers. To avoid + * this, check if there are pending responses to determine if this request should be scheduled right away or not. + * + * If there are other requests in the queue, and there are responses in the queue, then the network receive callback + * will handle scheduling the next requests (or is already scheduled and currently sending). */ + if( ( IotDeQueue_IsEmpty( &( pHttpsConnection->reqQ ) ) ) && + ( IotDeQueue_IsEmpty( &( pHttpsConnection->respQ ) ) ) ) + { + IotLogDebug( "Both the request and response queue are empty, so schedule the request to run in the dispatch queue." ); + scheduleRequest = true; + } + + /* Place into the connection's request to have a dispatch task serve it later. */ + IotDeQueue_EnqueueTail( &( pHttpsConnection->reqQ ), &( pHttpsRequest->link ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + if( scheduleRequest ) + { + /* This routine schedules a dispatch task to send the request. If a task is available immediately, then + * the request is sent right away. */ + status = _scheduleHttpsRequestSend( pHttpsRequest ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to schedule the request in the queue for request %p. Error code: %d", pHttpsRequest, status ); + + /* If we fail to schedule the only request in the queue we should remove it. */ + IotMutex_Lock( &( pHttpsConnection->connectionMutex ) ); + IotDeQueue_Remove( &( pHttpsRequest->link ) ); + IotMutex_Unlock( &( pHttpsConnection->connectionMutex ) ); + + HTTPS_GOTO_CLEANUP(); + } + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +static void _cancelRequest( _httpsRequest_t * pHttpsRequest ) +{ + pHttpsRequest->cancelled = true; +} + +/*-----------------------------------------------------------*/ + +static void _cancelResponse( _httpsResponse_t * pHttpsResponse ) +{ + pHttpsResponse->cancelled = true; +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_Init( void ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + uint8_t dispatchTaskIndex = 0; + + /* Allocate the dispatch queue. */ + #if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 + /* An array that holds the TCB of each dispatch task. */ + static StaticTask_t dispatchTaskBuffer[ IOT_HTTPS_DISPATCH_TASK_COUNT ]; + + /* An array that holds the stack of each dispatch task. + * The size of StackType_t is dependent on the RTOS port. */ + static StackType_t dispatchTaskStack[ IOT_HTTPS_DISPATCH_TASK_COUNT ][ IOT_HTTPS_DISPATCH_TASK_STACK_SIZE ]; + + /* A data structure to contain a statically allocated queue. */ + static StaticQueue_t dispatchQueueBuffer; + + /* A buffer to hold static memory for the dispatch queue. */ + static uint8_t dispatchQueueStorageBuffer[ IOT_HTTPS_DISPATCH_QUEUE_SIZE * sizeof( _httpsRequest_t * ) ]; + + dispatchQueue = xQueueCreateStatic( IOT_HTTPS_DISPATCH_QUEUE_SIZE, + sizeof( _httpsRequest_t * ), + dispatchQueueStorageBuffer, + &dispatchQueueBuffer ); + #else /* if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 */ + BaseType_t taskCreationResult = pdFALSE; + + dispatchQueue = xQueueCreate( IOT_HTTPS_DISPATCH_QUEUE_SIZE, sizeof( _httpsRequest_t * ) ); + #endif /* if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 */ + + if( dispatchQueue == NULL ) + { + /* Queue was not created and must not be used. */ + IotLogError( "Failed to allocate resources for dispatch queue.", status ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + + /* Start tasks that send requests from the dispatch queue. */ + for( dispatchTaskIndex = 0; dispatchTaskIndex < IOT_HTTPS_DISPATCH_TASK_COUNT; ++dispatchTaskIndex ) + { + #if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 + httpsDispatchTask[ dispatchTaskIndex ] = xTaskCreateStatic( _dispatchTaskRoutine, + "iot_thread", + IOT_HTTPS_DISPATCH_TASK_STACK_SIZE, + NULL, + IOT_HTTPS_DISPATCH_TASK_PRIORITY, + dispatchTaskStack[ dispatchTaskIndex ], + &dispatchTaskBuffer[ dispatchTaskIndex ] ); + + if( httpsDispatchTask[ dispatchTaskIndex ] == NULL ) + { + IotLogError( "Failed to allocate static memory for request task.", status ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + #else /* ifdef IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY */ + taskCreationResult = xTaskCreate( _dispatchTaskRoutine, + "iot_thread", + IOT_HTTPS_DISPATCH_TASK_STACK_SIZE, + NULL, + IOT_HTTPS_DISPATCH_TASK_PRIORITY, + &httpsDispatchTask[ dispatchTaskIndex ] ); + + if( taskCreationResult != pdPASS ) + { + IotLogError( "Failed to allocate dynamic memory for request task.", status ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + #endif /* ifdef IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY */ + } + + /* This sets all member in the _httpParserSettings to zero. It does not return any errors. */ + http_parser_settings_init( &_httpParserSettings ); + + /* Set the http-parser callbacks. */ + _httpParserSettings.on_message_begin = _httpParserOnMessageBeginCallback; + _httpParserSettings.on_status = _httpParserOnStatusCallback; + _httpParserSettings.on_header_field = _httpParserOnHeaderFieldCallback; + _httpParserSettings.on_header_value = _httpParserOnHeaderValueCallback; + _httpParserSettings.on_headers_complete = _httpParserOnHeadersCompleteCallback; + _httpParserSettings.on_body = _httpParserOnBodyCallback; + _httpParserSettings.on_message_complete = _httpParserOnMessageCompleteCallback; + + /* This code prints debugging information and is, therefore, compiled only when + * log level is set to IOT_LOG_DEBUG. */ + #if ( LIBRARY_LOG_LEVEL == IOT_LOG_DEBUG ) + _httpParserSettings.on_chunk_header = _httpParserOnChunkHeaderCallback; + _httpParserSettings.on_chunk_complete = _httpParserOnChunkCompleteCallback; + #endif + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + /* Upon error, reset to original state, freeing up any dynamic memory. */ + if( HTTPS_FAILED( status ) ) + { + #if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY != 1 + /* Free memory used for the dispatch queue. */ + if( dispatchQueue != NULL ) + { + vQueueDelete( dispatchQueue ); + } + #endif /* if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY != 1 */ + dispatchQueue = NULL; + + /* Delete the tasks that send requests from the dispatch queue. */ + for( dispatchTaskIndex = 0; dispatchTaskIndex < IOT_HTTPS_DISPATCH_TASK_COUNT; ++dispatchTaskIndex ) + { + if( httpsDispatchTask[ dispatchTaskIndex ] != NULL ) + { + #if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 + vTaskSuspend( httpsDispatchTask[ dispatchTaskIndex ] ); + #else + vTaskDelete( httpsDispatchTask[ dispatchTaskIndex ] ); + #endif + httpsDispatchTask[ dispatchTaskIndex ] = NULL; + } + } + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _initializeResponse( IotHttpsResponseHandle_t * pRespHandle, + IotHttpsResponseInfo_t * pRespInfo, + _httpsRequest_t * pHttpsRequest ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + _httpsResponse_t * pHttpsResponse = NULL; + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pRespInfo->userBuffer.pBuffer ); + + /* Check of the user buffer is large enough for the response context + default headers. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( pRespInfo->userBuffer.bufferLen >= responseUserBufferMinimumSize, + IOT_HTTPS_INSUFFICIENT_MEMORY, + "Buffer size is too small to initialize the response context. User buffer size: %d, required minimum size; %d.", + pRespInfo->userBuffer.bufferLen, + responseUserBufferMinimumSize ); + + /* Initialize the corresponding response to this request. */ + pHttpsResponse = ( _httpsResponse_t * ) ( pRespInfo->userBuffer.pBuffer ); + + /* Clear out the response user buffer. This is important because we + * give the whole buffer to the parser as opposed to the actual content + * length and rely on the parser to stop when a complete HTTP response + * is found. To make sure that any data in the buffer which is not part + * of the received HTTP response, does not get interpreted as part of + * the HTTP repose, we zero out the buffer here. */ + memset( pRespInfo->userBuffer.pBuffer, 0, pRespInfo->userBuffer.bufferLen ); + + pHttpsResponse->pHeaders = ( uint8_t * ) ( pHttpsResponse ) + sizeof( _httpsResponse_t ); + pHttpsResponse->pHeadersEnd = ( uint8_t * ) ( pHttpsResponse ) + pRespInfo->userBuffer.bufferLen; + pHttpsResponse->pHeadersCur = pHttpsResponse->pHeaders; + + if( pHttpsRequest->isAsync ) + { + pHttpsResponse->isAsync = true; + + /* For an asynchronous request the response body is provided by the application in the + * IotHttpsCallbacks_t.readReadyCallback(). These pointers will be updated when IotHttpsClient_ReadResponseBody() + * is invoked. */ + pHttpsResponse->pBody = NULL; + pHttpsResponse->pBodyCur = NULL; + pHttpsResponse->pBodyEnd = NULL; + + pHttpsResponse->pCallbacks = pHttpsRequest->pCallbacks; + pHttpsResponse->pUserPrivData = pHttpsRequest->pUserPrivData; + } + else + { + pHttpsResponse->isAsync = false; + /* The request body pointer is allowed to be NULL. u.pSyncInfo was checked for NULL earlier in this function. */ + pHttpsResponse->pBody = pRespInfo->pSyncInfo->pBody; + pHttpsResponse->pBodyCur = pHttpsResponse->pBody; + pHttpsResponse->pBodyEnd = pHttpsResponse->pBody + pRespInfo->pSyncInfo->bodyLen; + + /* Clear out the body bufffer. This is important because we give the + * whole buffer to the parser as opposed to the actual content length and + * rely on the parser to stop when a complete HTTP response is found. To + * make sure that any data in the buffer which is not part of the received + * HTTP response, does not get interpreted as part of the HTTP repose, we + * zero out the buffer here. */ + memset( pRespInfo->pSyncInfo->pBody, 0, pRespInfo->pSyncInfo->bodyLen ); + } + + /* Reinitialize the parser and set the fill buffer state to empty. This does not return any errors. */ + http_parser_init( &( pHttpsResponse->httpParserInfo.responseParser ), HTTP_RESPONSE ); + http_parser_init( &( pHttpsResponse->httpParserInfo.readHeaderParser ), HTTP_RESPONSE ); + /* Set the third party http parser function. */ + pHttpsResponse->httpParserInfo.parseFunc = http_parser_execute; + pHttpsResponse->httpParserInfo.readHeaderParser.data = ( void * ) ( pHttpsResponse ); + pHttpsResponse->httpParserInfo.responseParser.data = ( void * ) ( pHttpsResponse ); + + pHttpsResponse->status = 0; + pHttpsResponse->method = pHttpsRequest->method; + pHttpsResponse->parserState = PARSER_STATE_NONE; + pHttpsResponse->bufferProcessingState = PROCESSING_STATE_NONE; + pHttpsResponse->pReadHeaderField = NULL; + pHttpsResponse->readHeaderFieldLength = 0; + pHttpsResponse->pReadHeaderValue = NULL; + pHttpsResponse->readHeaderValueLength = 0; + pHttpsResponse->foundHeaderField = 0; + pHttpsResponse->pHttpsConnection = NULL; + + pHttpsResponse->pBodyInHeaderBuf = NULL; + pHttpsResponse->pBodyCurInHeaderBuf = NULL; + pHttpsResponse->bodyRxStatus = IOT_HTTPS_OK; + pHttpsResponse->cancelled = false; + pHttpsResponse->syncStatus = IOT_HTTPS_OK; + /* There is no request associated with this response right now, so it is finished sending. */ + pHttpsResponse->reqFinishedSending = true; + pHttpsResponse->isNonPersistent = pHttpsRequest->isNonPersistent; + + /* Set the response handle to return. */ + *pRespHandle = pHttpsResponse; + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + if( HTTPS_FAILED( status ) ) + { + pRespHandle = NULL; + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +static IotHttpsReturnCode_t _shimConvertStatus( HTTPStatus_t coreHttpStatus ) +{ + IotHttpsReturnCode_t returnStatus = IOT_HTTPS_OK; + + /* Note that coreHTTP will not receive any data so status codes relating + * to receiving a response are not mapped. */ + switch( coreHttpStatus ) + { + case HTTPSuccess: + returnStatus = IOT_HTTPS_OK; + break; + + case HTTPInvalidParameter: + returnStatus = IOT_HTTPS_INVALID_PARAMETER; + break; + + case HTTPNetworkError: + returnStatus = IOT_HTTPS_NETWORK_ERROR; + break; + + case HTTPInsufficientMemory: + returnStatus = IOT_HTTPS_INSUFFICIENT_MEMORY; + break; + + case HTTPHeaderNotFound: + returnStatus = IOT_HTTPS_NOT_FOUND; + break; + + default: + returnStatus = IOT_HTTPS_FATAL; + break; + } + + return returnStatus; +} + +/* --------------------------------------------------------- */ + +void IotHttpsClient_Cleanup( void ) +{ + uint8_t dispatchTaskIndex = 0; + + #if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY != 1 + /* Free memory used for the dispatch queue. */ + if( dispatchQueue != NULL ) + { + vQueueDelete( dispatchQueue ); + } + #endif /* if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY != 1 */ + dispatchQueue = NULL; + + /* Delete the tasks that send requests from the dispatch queue. */ + for( dispatchTaskIndex = 0; dispatchTaskIndex < IOT_HTTPS_DISPATCH_TASK_COUNT; ++dispatchTaskIndex ) + { + if( httpsDispatchTask[ dispatchTaskIndex ] != NULL ) + { + #if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 + vTaskSuspend( httpsDispatchTask[ dispatchTaskIndex ] ); + #else + vTaskDelete( httpsDispatchTask[ dispatchTaskIndex ] ); + #endif + httpsDispatchTask[ dispatchTaskIndex ] = NULL; + } + } +} + +/* --------------------------------------------------------- */ + +IotHttpsReturnCode_t IotHttpsClient_Connect( IotHttpsConnectionHandle_t * pConnHandle, + IotHttpsConnectionInfo_t * pConnInfo ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + /* Check for NULL parameters in a public API. */ + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pConnHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pConnInfo ); + + /* If a valid connection handle is passed in. */ + if( *pConnHandle != NULL ) + { + /* If the handle in a connected state, then we want to disconnect before reconnecting. The ONLY way to put the + * handle is a disconnect state is to call IotHttpsClient_Disconnect(). */ + if( ( *pConnHandle )->isConnected ) + { + status = IotHttpsClient_Disconnect( *pConnHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error disconnecting a connected *pConnHandle passed to IotHttpsClient_Connect(). Error code %d", status ); + *pConnHandle = NULL; + HTTPS_GOTO_CLEANUP(); + } + } + } + + /* Connect to the server now. Initialize all resources needed for the connection context as well here. */ + status = _createHttpsConnection( pConnHandle, pConnInfo ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error in IotHttpsClient_Connect(). Error code %d.", status ); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_Disconnect( IotHttpsConnectionHandle_t connHandle ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + _httpsRequest_t * pHttpsRequest = NULL; + _httpsResponse_t * pHttpsResponse = NULL; + IotLink_t * pRespItem = NULL; + IotLink_t * pReqItem = NULL; + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( connHandle ); + + /* If this routine is currently is progress by another thread, for instance the dispatch task that received a + * network error after sending, then return right away because connection resources are being used. */ + if( IotMutex_TryLock( &( connHandle->connectionMutex ) ) == false ) + { + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_BUSY ); + } + + /* Do not attempt to disconnect an already disconnected connection. + * It can happen when a user calls this functions and we return IOT_HTTPS_BUSY. */ + if( connHandle->isConnected ) + { + /* Mark the network as disconnected whether the disconnect passes or not. */ + connHandle->isConnected = false; + _networkDisconnect( connHandle ); + } + + /* If there is a response in the connection's response queue and the associated request has not finished sending, + * then we cannot destroy the connection until it finishes. */ + pRespItem = IotDeQueue_DequeueHead( &( connHandle->respQ ) ); + + if( pRespItem != NULL ) + { + pHttpsResponse = IotLink_Container( _httpsResponse_t, pRespItem, link ); + IotLogDebug( "Response %p found in the queue during disconnect.", pHttpsResponse ); + + if( pHttpsResponse->reqFinishedSending == false ) + { + IotLogError( "Connection is in use. Disconnected, but cannot destroy the connection." ); + status = IOT_HTTPS_BUSY; + + /* The request is busy, to as quickly as possible allow a successful retry call of this function we must + * cancel the busy request which is the first in the queue. */ + pReqItem = IotDeQueue_PeekHead( &( connHandle->reqQ ) ); + + if( pReqItem != NULL ) + { + pHttpsRequest = IotLink_Container( _httpsRequest_t, pReqItem, link ); + _cancelRequest( pHttpsRequest ); + } + + /* We set the status as busy, but we do not goto the cleanup right away because we still want to remove + * all pending requests. */ + } + + /* Delete all possible pending responses. (This is defensive.) */ + IotDeQueue_RemoveAll( &( connHandle->respQ ), NULL, 0 ); + + /* Put the response that was dequeued back so that the application can call this function again to check later + * that is exited and marked itself as finished sending. + * If during the last check and this check reqFinishedSending gets set to true, that is OK because on the next + * call to this routine, the disconnect will succeed. */ + if( pHttpsResponse->reqFinishedSending == false ) + { + IotDeQueue_EnqueueHead( &( connHandle->respQ ), pRespItem ); + } + } + + /* Debug code */ + IotLogDebug( "There were %d requests in the queue while disconnecting. ", IotDeQueue_Count( &( connHandle->reqQ ) ) ); + + /* Remove all pending requests. If this routine is called from the application context and there is a + * network receive callback in process, this routine will wait in _networkDestroy until that routine returns. + * If this is routine is called from the network receive callback context, then the destroy happens after the + * network receive callback context returns. */ + IotDeQueue_RemoveAll( &( connHandle->reqQ ), NULL, 0 ); + + /* Do not attempt to destroy an already destroyed connection. This can happen when the user calls this function and + * IOT_HTTPS_BUSY is returned. */ + if( HTTPS_SUCCEEDED( status ) ) + { + if( connHandle->isDestroyed == false ) + { + connHandle->isDestroyed = true; + _networkDestroy( connHandle ); + } + } + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + /* This function is no longer in process, so disconnecting is no longer in process. This signals to the retry + * on this function that it can proceed with the disconnecting activities. */ + if( connHandle != NULL ) + { + IotMutex_Unlock( &( connHandle->connectionMutex ) ); + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_InitializeRequest( IotHttpsRequestHandle_t * pReqHandle, + IotHttpsRequestInfo_t * pReqInfo ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPStatus_t coreHttpStatus = HTTPSuccess; + HTTPRequestHeaders_t coreHttpRequestHeaders; + HTTPRequestInfo_t coreHttpRequestInfo; + + _httpsRequest_t * pHttpsRequest = NULL; + + /* Check for NULL parameters in the public API. */ + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pReqHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pReqInfo ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pReqInfo->userBuffer.pBuffer ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pReqInfo->pHost ); + + if( pReqInfo->isAsync ) + { + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pReqInfo->u.pAsyncInfo ); + } + else + { + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pReqInfo->u.pSyncInfo ); + } + + /* Check of the user buffer is large enough for the request context + default headers. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( pReqInfo->userBuffer.bufferLen >= requestUserBufferMinimumSize, + IOT_HTTPS_INSUFFICIENT_MEMORY, + "Buffer size is too small to initialize the request context. User buffer size: %d, required minimum size; %d.", + pReqInfo->userBuffer.bufferLen, + requestUserBufferMinimumSize ); + + /* Set the request context to the start of the user buffer. */ + pHttpsRequest = ( _httpsRequest_t * ) ( pReqInfo->userBuffer.pBuffer ); + + /* Set the start of the headers to the end of the request context in the user buffer. */ + pHttpsRequest->pHeaders = ( uint8_t * ) pHttpsRequest + sizeof( _httpsRequest_t ); + pHttpsRequest->pHeadersEnd = ( uint8_t * ) pHttpsRequest + pReqInfo->userBuffer.bufferLen; + pHttpsRequest->pHeadersCur = pHttpsRequest->pHeaders; + + /* Map coreHTTP objects to be used by #HTTPClient_InitializeRequestHeaders. */ + coreHttpRequestHeaders.pBuffer = pHttpsRequest->pHeaders; + coreHttpRequestHeaders.bufferLen = ( size_t ) ( pHttpsRequest->pHeadersEnd - pHttpsRequest->pHeaders ); + + coreHttpRequestInfo.pMethod = _pHttpsMethodStrings[ pReqInfo->method ]; + coreHttpRequestInfo.methodLen = ( size_t ) strlen( _pHttpsMethodStrings[ pReqInfo->method ] ); + coreHttpRequestInfo.pPath = pReqInfo->pPath; + coreHttpRequestInfo.pathLen = ( size_t ) pReqInfo->pathLen; + coreHttpRequestInfo.pHost = pReqInfo->pHost; + coreHttpRequestInfo.hostLen = ( size_t ) pReqInfo->hostLen; + + if( pHttpsRequest->isNonPersistent == false ) + { + coreHttpRequestInfo.reqFlags = HTTP_REQUEST_KEEP_ALIVE_FLAG; + } + + coreHttpStatus = HTTPClient_InitializeRequestHeaders( &coreHttpRequestHeaders, + &coreHttpRequestInfo ); + status = _shimConvertStatus( coreHttpStatus ); + + if( HTTPS_FAILED( status ) ) + { + HTTPS_GOTO_CLEANUP(); + } + + /* Update the original library based on coreHTTP's output. */ + pHttpsRequest->pHeadersCur = pHttpsRequest->pHeaders + coreHttpRequestHeaders.headersLen; + + if( pReqInfo->isAsync ) + { + pHttpsRequest->isAsync = true; + /* If this is an asynchronous request then save the callbacks to use. */ + pHttpsRequest->pCallbacks = &( pReqInfo->u.pAsyncInfo->callbacks ); + pHttpsRequest->pUserPrivData = pReqInfo->u.pAsyncInfo->pPrivData; + /* The body pointer and body length will be filled in when the application sends data in the writeCallback. */ + pHttpsRequest->pBody = NULL; + pHttpsRequest->bodyLength = 0; + } + else + { + pHttpsRequest->isAsync = false; + /* Set the HTTP request entity body. This is allowed to be NULL for no body like for a GET request. */ + pHttpsRequest->pBody = pReqInfo->u.pSyncInfo->pBody; + pHttpsRequest->bodyLength = pReqInfo->u.pSyncInfo->bodyLen; + } + + /* Save the method of this request. */ + pHttpsRequest->method = pReqInfo->method; + /* Set the connection persistence flag for keeping the connection open after receiving a response. */ + pHttpsRequest->isNonPersistent = pReqInfo->isNonPersistent; + /* Initialize the request cancellation. */ + pHttpsRequest->cancelled = false; + /* Initialize the status of sending the body over the network in a possible asynchronous request. */ + pHttpsRequest->bodyTxStatus = IOT_HTTPS_OK; + /* This is a new request and therefore not scheduled yet. */ + pHttpsRequest->scheduled = false; + + /* Set the request handle to return. */ + *pReqHandle = pHttpsRequest; + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + if( HTTPS_FAILED( status ) && ( pReqHandle != NULL ) ) + { + /* Set the request handle to return to NULL, if we failed anywhere. */ + *pReqHandle = NULL; + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_AddHeader( IotHttpsRequestHandle_t reqHandle, + char * pName, + uint32_t nameLen, + char * pValue, + uint32_t valueLen ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPStatus_t coreHttpStatus = HTTPSuccess; + HTTPRequestHeaders_t coreHttpRequestHeaders; + + /* Check for NULL pointer paramters. */ + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pName ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pValue ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( reqHandle ); + + /* Check for name long enough for header length calculation to overflow */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( nameLen <= ( UINT32_MAX >> 2 ), + IOT_HTTPS_INVALID_PARAMETER, + "Attempting to generate headers with name length %u > %lu. This is not allowed.", + nameLen, UINT32_MAX >> 2 ); + + /* Check for value long enough for header length calculation to overflow */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( valueLen <= ( UINT32_MAX >> 2 ), + IOT_HTTPS_INVALID_PARAMETER, + "Attempting to generate headers with value length %u > %lu. This is not allowed.", + valueLen, UINT32_MAX >> 2 ); + + /* Check for auto-generated header "Content-Length". This header is created and send automatically when right before + * request body is sent on the network. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( ( ( nameLen != FAST_MACRO_STRLEN( HTTPS_CONTENT_LENGTH_HEADER ) ) || + ( strncmp( pName, HTTPS_CONTENT_LENGTH_HEADER, FAST_MACRO_STRLEN( HTTPS_CONTENT_LENGTH_HEADER ) ) != 0 ) ), + IOT_HTTPS_INVALID_PARAMETER, + "Attempting to add auto-generated header %s. This is not allowed.", + HTTPS_CONTENT_LENGTH_HEADER ); + + /* Check for auto-generated header "Connection". This header is created and send automatically when right before + * request body is sent on the network. */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( ( ( nameLen != FAST_MACRO_STRLEN( HTTPS_CONNECTION_HEADER ) ) || + ( strncmp( pName, HTTPS_CONNECTION_HEADER, FAST_MACRO_STRLEN( HTTPS_CONNECTION_HEADER ) ) != 0 ) ), + IOT_HTTPS_INVALID_PARAMETER, + "Attempting to add auto-generated header %s. This is not allowed.", + HTTPS_CONNECTION_HEADER ); + + /* Check for auto-generated header "Host". This header is created and placed into the header buffer space + * in IotHttpsClient_InitializeRequest(). */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( ( ( nameLen != FAST_MACRO_STRLEN( HTTPS_HOST_HEADER ) ) || + ( strncmp( pName, HTTPS_HOST_HEADER, FAST_MACRO_STRLEN( HTTPS_HOST_HEADER ) ) != 0 ) ), + IOT_HTTPS_INVALID_PARAMETER, + "Attempting to add auto-generated header %s. This is not allowed.", + HTTPS_HOST_HEADER ); + + /* Check for auto-generated header "User-Agent". This header is created and placed into the header buffer space + * in IotHttpsClient_InitializeRequest(). */ + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( ( ( nameLen != FAST_MACRO_STRLEN( HTTPS_USER_AGENT_HEADER ) ) || + ( strncmp( pName, HTTPS_USER_AGENT_HEADER, FAST_MACRO_STRLEN( HTTPS_USER_AGENT_HEADER ) ) != 0 ) ), + IOT_HTTPS_INVALID_PARAMETER, + "Attempting to add auto-generated header %s. This is not allowed.", + HTTPS_USER_AGENT_HEADER ); + + /* Map coreHTTP objects to be used by #HTTPClient_AddHeader. */ + coreHttpRequestHeaders.pBuffer = reqHandle->pHeaders; + coreHttpRequestHeaders.bufferLen = ( size_t ) ( reqHandle->pHeadersEnd - reqHandle->pHeaders ); + coreHttpRequestHeaders.headersLen = ( size_t ) ( reqHandle->pHeadersCur - reqHandle->pHeaders ); + + coreHttpStatus = HTTPClient_AddHeader( &coreHttpRequestHeaders, pName, nameLen, pValue, valueLen ); + status = _shimConvertStatus( coreHttpStatus ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Error in IotHttpsClient_AddHeader(), error code %d.", status ); + HTTPS_GOTO_CLEANUP(); + } + + /* Update the original library based on coreHTTP's output. */ + reqHandle->pHeadersCur = reqHandle->pHeaders + coreHttpRequestHeaders.headersLen; + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_SendSync( IotHttpsConnectionHandle_t connHandle, + IotHttpsRequestHandle_t reqHandle, + IotHttpsResponseHandle_t * pRespHandle, + IotHttpsResponseInfo_t * pRespInfo, + uint32_t timeoutMs ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + bool respFinishedSemCreated = false; + _httpsResponse_t * pHttpsResponse = NULL; + + /* Parameter checks. */ + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( connHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( reqHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pRespHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pRespInfo ); + /* Stop the application from scheduling requests on a closed connection. */ + HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( connHandle->isConnected ); + + /* If an asynchronous request/response is configured, that is invalid for this API. */ + if( reqHandle->isAsync ) + { + IotLogError( "Called IotHttpsClient_SendSync on an asynchronous configured request." ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); + } + + /* Initialize the response handle to return. */ + status = _initializeResponse( pRespHandle, pRespInfo, reqHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to initialize the response on the synchronous request %p.", reqHandle ); + HTTPS_GOTO_CLEANUP(); + } + + /* Set the internal response to use. */ + pHttpsResponse = *pRespHandle; + + /* The implicit connection passed and we need to the set the connection handle in the request and response. */ + reqHandle->pHttpsConnection = connHandle; + pHttpsResponse->pHttpsConnection = connHandle; + + /* Create the semaphore used to wait on the response to finish being received. */ + respFinishedSemCreated = IotSemaphore_Create( &( pHttpsResponse->respFinishedSem ), 0 /* initialValue */, 1 /* maxValue */ ); + + if( respFinishedSemCreated == false ) + { + IotLogError( "Failed to create an internal semaphore." ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INTERNAL_ERROR ); + } + + /* Associate the response to the request so that we can schedule it to be received when the request gets scheduled to send. */ + reqHandle->pHttpsResponse = pHttpsResponse; + + /* Schedule this request to be sent by adding it to the connection's request queue. */ + status = _addRequestToConnectionReqQ( reqHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to schedule the synchronous request. Error code: %d", status ); + HTTPS_GOTO_CLEANUP(); + } + + /* Wait for the request to finish. */ + if( timeoutMs == 0 ) + { + IotSemaphore_Wait( &( pHttpsResponse->respFinishedSem ) ); + } + else + { + if( IotSemaphore_TimedWait( &( pHttpsResponse->respFinishedSem ), timeoutMs ) == false ) + { + IotLogError( "Timed out waiting for the synchronous request to finish. Timeout ms: %d", timeoutMs ); + _cancelRequest( reqHandle ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_TIMEOUT_ERROR ); + } + } + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + if( respFinishedSemCreated ) + { + IotSemaphore_Destroy( &( pHttpsResponse->respFinishedSem ) ); + } + + /* If the syncStatus is anything other than IOT_HTTPS_OK, then the request was scheduled. */ + if( ( pHttpsResponse != NULL ) && HTTPS_FAILED( pHttpsResponse->syncStatus ) ) + { + status = pHttpsResponse->syncStatus; + } + + if( HTTPS_FAILED( status ) ) + { + if( pRespHandle != NULL ) + { + *pRespHandle = NULL; + } + + IotLogError( "IotHttpsClient_SendSync() failed." ); + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_WriteRequestBody( IotHttpsRequestHandle_t reqHandle, + uint8_t * pBuf, + uint32_t len, + int isComplete ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( reqHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pBuf ); + + /* This function is not valid for a synchronous response. Applications need to configure the request body in + * IotHttpsRequestInfo_t.pSyncInfo_t.reqData before calling IotHttpsClient_SendSync(). */ + HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( reqHandle->isAsync ); + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( isComplete == 1, + IOT_HTTPS_NOT_SUPPORTED, + "isComplete must be 1 in IotHttpsClient_WriteRequestBody() for the current version of the HTTPS Client library." ); + + /* If the bodyLength is greater than 0, then we already called this function and we need to enforce that this + * function must only be called once. We only call this function once so that we can calculate the Content-Length. */ + if( reqHandle->bodyLength > 0 ) + { + IotLogError( "Error this function must be called once with the data needed to send. Variable length HTTP " + "request body is not supported in this library." ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_MESSAGE_FINISHED ); + } + + /* Set the pointer to the body and the length for the content-length calculation. */ + reqHandle->pBody = ( uint8_t * ) pBuf; + reqHandle->bodyLength = len; + + /* We send the HTTPS headers and body in this function so that the application has the freedom to specify a body + * that may be buffer on stack. */ + status = _sendHttpsHeadersAndBody( reqHandle->pHttpsConnection, reqHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to send the headers and body. Error code %d.", status ); + HTTPS_GOTO_CLEANUP(); + } + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + if( reqHandle != NULL ) + { + reqHandle->bodyTxStatus = status; + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_ReadResponseBody( IotHttpsResponseHandle_t respHandle, + uint8_t * pBuf, + uint32_t * pLen ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + uint32_t bodyLengthInHeaderBuf = 0; + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( respHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pBuf ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pLen ); + HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( respHandle->isAsync ); + + /* Set the current body in the respHandle to use in _receiveHttpsBody(). _receiveHttpsBody is generic + * to both async and sync request/response handling. In the sync version the body is configured during + * initializing the request. In the async version the body is given in this function on the fly. */ + respHandle->pBody = pBuf; + respHandle->pBodyCur = respHandle->pBody; + respHandle->pBodyEnd = respHandle->pBodyCur + *pLen; + + /* When there is part of the body in the header pBuffer. We need to move that data to this body pBuffer + * provided in this function. */ + bodyLengthInHeaderBuf = respHandle->pBodyCurInHeaderBuf - respHandle->pBodyInHeaderBuf; + + if( bodyLengthInHeaderBuf > 0 ) + { + uint32_t copyLength = bodyLengthInHeaderBuf > *pLen ? *pLen : bodyLengthInHeaderBuf; + memcpy( respHandle->pBodyCur, respHandle->pBodyInHeaderBuf, copyLength ); + respHandle->pBodyCur += copyLength; + + /* This function may be called multiple times until all of the body that may be present in the header buffer is + * moved out. */ + respHandle->pBodyInHeaderBuf += copyLength; + } + + /* If there is room in the body buffer just provided by the application and we have not completed the current + * HTTP response message, then try to receive more body. */ + if( ( ( respHandle->pBodyEnd - respHandle->pBodyCur ) > 0 ) && ( respHandle->parserState < PARSER_STATE_BODY_COMPLETE ) ) + { + status = _receiveHttpsBody( respHandle->pHttpsConnection, respHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to receive the HTTP response body on the network. Error code: %d.", status ); + HTTPS_GOTO_CLEANUP(); + } + } + + *pLen = respHandle->pBodyCur - respHandle->pBody; + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + if( respHandle != NULL ) + { + respHandle->bodyRxStatus = status; + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_CancelRequestAsync( IotHttpsRequestHandle_t reqHandle ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( reqHandle ); + + _cancelRequest( reqHandle ); + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_CancelResponseAsync( IotHttpsResponseHandle_t respHandle ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( respHandle ); + + _cancelResponse( respHandle ); + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_SendAsync( IotHttpsConnectionHandle_t connHandle, + IotHttpsRequestHandle_t reqHandle, + IotHttpsResponseHandle_t * pRespHandle, + IotHttpsResponseInfo_t * pRespInfo ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( connHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( reqHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pRespHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pRespInfo ); + HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( reqHandle->isAsync ); + /* Stop the application from scheduling requests on a closed connection. */ + HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( connHandle->isConnected ); + + /* Initialize the response handle to return. */ + status = _initializeResponse( pRespHandle, pRespInfo, reqHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to initialize the response on the synchronous request %p.", reqHandle ); + HTTPS_GOTO_CLEANUP(); + } + + /* Set the connection handle in the request handle so that we can use it in the _writeRequestBody() callback. */ + reqHandle->pHttpsConnection = connHandle; + + /* Set the connection handle in the response handle sp that we can use it in the _readReadyCallback() callback. */ + ( *pRespHandle )->pHttpsConnection = connHandle; + + /* Associate the response to the request so that we can schedule it to be received when the request gets scheduled to send. */ + reqHandle->pHttpsResponse = *pRespHandle; + + /* Add the request to the connection's request queue. */ + status = _addRequestToConnectionReqQ( reqHandle ); + + if( HTTPS_FAILED( status ) ) + { + IotLogError( "Failed to add request %p to the connection's request queue. Error code: %d.", reqHandle, status ); + HTTPS_GOTO_CLEANUP(); + } + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_ReadResponseStatus( IotHttpsResponseHandle_t respHandle, + uint16_t * pStatus ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( respHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pStatus ); + + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( respHandle->status != 0, + IOT_HTTPS_NOT_FOUND, + "The HTTP response status was not found in the HTTP response header buffer." ); + + *pStatus = respHandle->status; + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_ReadHeader( IotHttpsResponseHandle_t respHandle, + char * pName, + uint32_t nameLen, + char * pValue, + uint32_t valueLen ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + const char * pHttpParserErrorDescription = NULL; + IotHttpsResponseBufferState_t savedBufferState = PROCESSING_STATE_NONE; + IotHttpsResponseParserState_t savedParserState = PARSER_STATE_NONE; + size_t numParsed = 0; + + /* Disable -Wunused-but-set-variable for local variables used for logging. */ + ( void ) numParsed; + ( void ) pHttpParserErrorDescription; + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( respHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pName ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pValue ); + HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( valueLen > 0, + IOT_HTTPS_INVALID_PARAMETER, + "pValue has insufficient space to store a value string (length is 0)" ); + + /* The buffer processing state is changed to searching the header buffer in this function. The parser state is + * changed in the response to wherever the parser is currently located in the response. If this function is called + * in the middle of processing a response (for example in readReadyCallback() routine of an asynchronous response), + * then parsing the response need to be able to start at the same place it was before calling this function. */ + savedBufferState = respHandle->bufferProcessingState; + savedParserState = respHandle->parserState; + + /* The header search parameters in the response handle are used as context in the http-parser callbacks. During + * the callback, pReadHeaderField is checked against the currently parsed header name. foundHeaderField is set to + * true when the pReadHeaderField is found in a header field callback. The bufferProcessingState tells the callback + * to skip the logic pertaining to when the response is being parsed for the first time. pReadHeaderValue will store + * the header value found. readHeaderValueLength will store the length of the header value found from within the + * response headers. */ + respHandle->pReadHeaderField = pName; + respHandle->readHeaderFieldLength = nameLen; + respHandle->foundHeaderField = false; + respHandle->bufferProcessingState = PROCESSING_STATE_SEARCHING_HEADER_BUFFER; + respHandle->pReadHeaderValue = NULL; + respHandle->readHeaderValueLength = 0; + + /* Start over the HTTP parser so that it will parser from the beginning of the message. */ + http_parser_init( &( respHandle->httpParserInfo.readHeaderParser ), HTTP_RESPONSE ); + + IotLogDebug( "Now parsing HTTP Message buffer to read a header." ); + numParsed = respHandle->httpParserInfo.parseFunc( &( respHandle->httpParserInfo.readHeaderParser ), &_httpParserSettings, ( char * ) ( respHandle->pHeaders ), respHandle->pHeadersCur - respHandle->pHeaders ); + IotLogDebug( "Parsed %d characters in IotHttpsClient_ReadHeader().", numParsed ); + + /* There shouldn't be any errors parsing the response body given that the handle is from a validly + * received response, so this check is defensive. If there were errors parsing the original response headers, then + * the response handle would have been invalidated and the connection closed. */ + if( ( respHandle->httpParserInfo.readHeaderParser.http_errno != 0 ) && + ( HTTP_PARSER_ERRNO( &( respHandle->httpParserInfo.readHeaderParser ) ) > HPE_CB_chunk_complete ) ) + { + pHttpParserErrorDescription = http_errno_description( HTTP_PARSER_ERRNO( &( respHandle->httpParserInfo.readHeaderParser ) ) ); + IotLogError( "http_parser failed on the http response with error: %s", pHttpParserErrorDescription ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_PARSING_ERROR ); + } + + /* Not only do we need an indication that the header field was found, but also that the value was found as well. + * The value is found when it is non-NULL. The case where the header field is found, but the value is not found + * occurs when there are incomplete headers stored in the header buffer. The header buffer could end with a header + * field name. */ + if( respHandle->foundHeaderField && ( respHandle->pReadHeaderValue != NULL ) ) + { + /* The len of the pValue buffer must account for the NULL terminator. */ + if( respHandle->readHeaderValueLength > ( valueLen - 1 ) ) + { + IotLogError( "IotHttpsClient_ReadHeader(): The length of the pValue buffer specified is less than the actual length of the pValue. " ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INSUFFICIENT_MEMORY ); + } + else + { + memcpy( pValue, respHandle->pReadHeaderValue, respHandle->readHeaderValueLength ); + pValue[ respHandle->readHeaderValueLength ] = '\0'; + } + } + else + { + IotLogWarn( "IotHttpsClient_ReadHeader(): The header field %s was not found.", pName ); + HTTPS_SET_AND_GOTO_CLEANUP( IOT_HTTPS_NOT_FOUND ); + } + + HTTPS_FUNCTION_CLEANUP_BEGIN(); + + /* Always restore the state back to what it was before entering this function. */ + if( respHandle != NULL ) + { + respHandle->bufferProcessingState = savedBufferState; + respHandle->parserState = savedParserState; + } + + HTTPS_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_ReadContentLength( IotHttpsResponseHandle_t respHandle, + uint32_t * pContentLength ) +{ + HTTPS_FUNCTION_ENTRY( IOT_HTTPS_OK ); + + const int CONTENT_LENGTH_NUMBERIC_BASE = 10; + char pContentLengthStr[ HTTPS_MAX_CONTENT_LENGTH_LINE_LENGTH ] = { 0 }; + + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( respHandle ); + HTTPS_ON_NULL_ARG_GOTO_CLEANUP( pContentLength ); + + /* If there is no content-length header or if we were not able to store it in the header buffer this will be + * invalid. We do not use the content-length member of the http-parser state structure to get the content + * length as this is a PRIVATE member. Because it is a PRIVATE member it can be any value. */ + status = IotHttpsClient_ReadHeader( respHandle, HTTPS_CONTENT_LENGTH_HEADER, FAST_MACRO_STRLEN( HTTPS_CONTENT_LENGTH_HEADER ), pContentLengthStr, HTTPS_MAX_CONTENT_LENGTH_LINE_LENGTH ); + + if( HTTPS_FAILED( status ) ) + { + *pContentLength = 0; + IotLogError( "Could not read the Content-Length for the response." ); + HTTPS_GOTO_CLEANUP(); + } + + *pContentLength = strtoul( pContentLengthStr, NULL, CONTENT_LENGTH_NUMBERIC_BASE ); + + HTTPS_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +/* Provide access to internal functions and variables if testing. */ +#if IOT_BUILD_TESTS == 1 + #include "iot_test_access_https_client.c" +#endif diff --git a/bsp/aws_libraries/c_sdk/standard/https/src/iot_https_utils.c b/bsp/aws_libraries/c_sdk/standard/https/src/iot_https_utils.c new file mode 100644 index 0000000..5134f11 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/https/src/iot_https_utils.c @@ -0,0 +1,137 @@ +/* + * FreeRTOS HTTPS Client V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_https_utils.c + * @brief Implements functions for HTTPS Client library utilities. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* iot_https_includes */ +#include "iot_https_utils.h" +#include "http_parser.h" +#include "private/iot_https_internal.h" + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_GetUrlPath( const char * pUrl, + size_t urlLen, + const char ** pPath, + size_t * pPathLen ) +{ + /* http-parser status. Initialized to 0 to signify success. */ + int parserStatus = 0; + struct http_parser_url urlParser; + IotHttpsReturnCode_t returnStatus = IOT_HTTPS_OK; + + /* Sets all members in urlParser to 0. */ + http_parser_url_init( &urlParser ); + + if( ( pUrl == NULL ) || ( pPath == NULL ) || ( pPathLen == NULL ) ) + { + IotLogError( "NULL parameter passed to IotHttpsClient_GetUrlPath()." ); + returnStatus = IOT_HTTPS_INVALID_PARAMETER; + } + + if( returnStatus == IOT_HTTPS_OK ) + { + parserStatus = http_parser_parse_url( pUrl, urlLen, 0, &urlParser ); + + if( parserStatus != 0 ) + { + IotLogError( "Error parsing the input URL %.*s. Error code: %d.", urlLen, pUrl, parserStatus ); + returnStatus = IOT_HTTPS_PARSING_ERROR; + } + } + + if( returnStatus == IOT_HTTPS_OK ) + { + *pPathLen = ( size_t ) ( urlParser.field_data[ UF_PATH ].len ); + + if( *pPathLen == 0 ) + { + returnStatus = IOT_HTTPS_NOT_FOUND; + *pPath = NULL; + } + else + { + *pPath = &pUrl[ urlParser.field_data[ UF_PATH ].off ]; + } + } + + return returnStatus; +} + +/*-----------------------------------------------------------*/ + +IotHttpsReturnCode_t IotHttpsClient_GetUrlAddress( const char * pUrl, + size_t urlLen, + const char ** pAddress, + size_t * pAddressLen ) +{ + /* http-parser status. Initialized to 0 to signify success. */ + int parserStatus = 0; + struct http_parser_url urlParser; + IotHttpsReturnCode_t returnStatus = IOT_HTTPS_OK; + + /* Sets all members in urlParser to 0. */ + http_parser_url_init( &urlParser ); + + if( ( pUrl == NULL ) || ( pAddress == NULL ) || ( pAddressLen == NULL ) ) + { + IotLogError( "NULL parameter passed to IotHttpsClient_GetUrlAddress()." ); + returnStatus = IOT_HTTPS_INVALID_PARAMETER; + } + + if( returnStatus == IOT_HTTPS_OK ) + { + parserStatus = http_parser_parse_url( pUrl, urlLen, 0, &urlParser ); + + if( parserStatus != 0 ) + { + IotLogError( "Error parsing the input URL %.*s. Error code: %d.", urlLen, pUrl, parserStatus ); + returnStatus = IOT_HTTPS_PARSING_ERROR; + } + } + + if( returnStatus == IOT_HTTPS_OK ) + { + *pAddressLen = ( size_t ) ( urlParser.field_data[ UF_HOST ].len ); + + if( *pAddressLen == 0 ) + { + returnStatus = IOT_HTTPS_NOT_FOUND; + *pAddress = NULL; + } + else + { + *pAddress = &pUrl[ urlParser.field_data[ UF_HOST ].off ]; + } + } + + return returnStatus; +} diff --git a/bsp/aws_libraries/c_sdk/standard/https/src/private/iot_https_internal.h b/bsp/aws_libraries/c_sdk/standard/https/src/private/iot_https_internal.h new file mode 100644 index 0000000..118bf24 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/https/src/private/iot_https_internal.h @@ -0,0 +1,539 @@ +/* + * FreeRTOS HTTPS Client V1.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +#ifndef IOT_HTTPS_INTERNAL_H_ +#define IOT_HTTPS_INTERNAL_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include +#include + +/* Kernel includes. */ +#include "queue.h" + +/* coreHTTP includes. */ +#include "core_http_client.h" + +/* Third party http-parser include. */ +#include "http_parser.h" + +/* HTTPS Client library includes. */ +#include "iot_https_client.h" + +/* Linear containers (lists and queues) include. */ +#include "iot_linear_containers.h" + +/* Platform layer includes. */ +#include "platform/iot_threads.h" +#include "platform/iot_network.h" + +/* Error handling include. */ +#include "private/iot_error.h" + +/*-----------------------------------------------------------*/ + +/* Convenience macros for handling errors in a standard way. */ + +/** + * @brief Every public API return an enumeration value with an underlying value of 0 in case of success. + */ +#define HTTPS_SUCCEEDED( x ) ( ( x ) == IOT_HTTPS_OK ) + +/** + * @brief Every public API returns an enumeration value with an underlying value different than 0 in case of success. + */ +#define HTTPS_FAILED( x ) ( ( x ) != IOT_HTTPS_OK ) + +/** + * @brief Declare the storage for the error status variable. + */ +#define HTTPS_FUNCTION_ENTRY( result ) IOT_FUNCTION_ENTRY( IotHttpsReturnCode_t, result ) + +/** + * @brief Jump to the cleanup area. + */ +#define HTTPS_GOTO_CLEANUP() IOT_GOTO_CLEANUP() + +/** + * @brief Set error and leave. + */ +#define HTTPS_SET_AND_GOTO_CLEANUP( statusValue ) IOT_SET_AND_GOTO_CLEANUP( statusValue ) + +/** + * @brief Initialize error and declare start of cleanup area. + */ +#define HTTPS_FUNCTION_CLEANUP_BEGIN() IOT_FUNCTION_CLEANUP_BEGIN() + +/** + * @brief Initialize error and declare end of cleanup area. + */ +#define HTTPS_FUNCTION_CLEANUP_END() IOT_FUNCTION_CLEANUP_END() + +/** + * @brief Create an empty cleanup area. + */ +#define HTTPS_FUNCTION_EXIT_NO_CLEANUP() IOT_FUNCTION_EXIT_NO_CLEANUP() + +/** + * @brief Exit if an argument is NULL. + */ +#define HTTPS_ON_NULL_ARG_GOTO_CLEANUP( ptr ) \ + if( ( ptr == NULL ) ) \ + { \ + IotLogError( # ptr " was NULL." ); \ + IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \ + } + +/** + * @brief Exit if an condition is false. + */ +#define HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( expr ) \ + if( ( expr ) == false ) \ + { \ + IotLogError( # expr " must be true." ); \ + IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \ + } + +/** + * @brief Exit if an argument is false with a message. + */ +#define HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( expr, statusValue, ... ) \ + if( ( expr ) == false ) \ + { \ + IotLogError( __VA_ARGS__ ); \ + IOT_SET_AND_GOTO_CLEANUP( statusValue ); \ + } + +/* Configure logs for HTTPS Client functions. */ +#ifdef IOT_LOG_LEVEL_HTTPS + #ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_HTTPS + #endif +#else + #ifndef LIBRARY_LOG_LEVEL + #ifdef IOT_LOG_LEVEL_GLOBAL + #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL + #else + #define LIBRARY_LOG_LEVEL IOT_LOG_NONE + #endif + #endif +#endif /* ifdef IOT_LOG_LEVEL_HTTPS */ + +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME ( "HTTPS Client" ) +#endif + +#include "iot_logging_setup.h" + +/* + * Provide default values for undefined memory allocation functions based on + * the usage of dynamic memory allocation. + */ +#if IOT_STATIC_MEMORY_ONLY == 1 + #include "private/iot_static_memory.h" + #ifndef IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY + #define IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY ( 1 ) /* Use static memory for dispatch queue and tasks. */ + #endif +#endif + +/** + * @cond DOXYGEN_IGNORE + * Doxygen should ignore this section. + * + * Provide default values for undefined configuration constants. + */ +#ifndef AWS_IOT_HTTPS_ENABLE_METRICS + #define AWS_IOT_HTTPS_ENABLE_METRICS ( 1 ) +#endif +#ifndef IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE + #define IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE ( 1024 ) +#endif +#ifndef IOT_HTTPS_RESPONSE_WAIT_MS + #define IOT_HTTPS_RESPONSE_WAIT_MS ( 1000 ) +#endif +#ifndef IOT_HTTPS_MAX_HOST_NAME_LENGTH + #define IOT_HTTPS_MAX_HOST_NAME_LENGTH ( 255 ) /* Per FQDN, the maximum host name length is 255 bytes. */ +#endif +#ifndef IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH + #define IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH ( 255 ) /* The maximum alpn protocols length is chosen arbitrarily. */ +#endif +#ifndef IOT_HTTPS_QUEUE_RECV_TICKS + #define IOT_HTTPS_QUEUE_RECV_TICKS ( portMAX_DELAY ) /* The ticks to wait for a #xQueueReceive to complete. */ +#endif +#ifndef IOT_HTTPS_QUEUE_SEND_TICKS + #define IOT_HTTPS_QUEUE_SEND_TICKS ( 0U ) /* The ticks to wait for a #xQueueSendToBack to complete. */ +#endif +#ifndef IOT_HTTPS_DISPATCH_QUEUE_SIZE + #define IOT_HTTPS_DISPATCH_QUEUE_SIZE ( 4U ) /* The size of the queue containing requests ready to send to the server. */ +#endif +#ifndef IOT_HTTPS_DISPATCH_TASK_COUNT + #define IOT_HTTPS_DISPATCH_TASK_COUNT ( 2U ) /* The number of tasks that send requests from the queue. */ +#endif +#ifndef IOT_HTTPS_DISPATCH_TASK_STACK_SIZE + #define IOT_HTTPS_DISPATCH_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) /* The stack size of each dispatch task. */ +#endif +#ifndef IOT_HTTPS_DISPATCH_TASK_PRIORITY + #define IOT_HTTPS_DISPATCH_TASK_PRIORITY ( IOT_THREAD_DEFAULT_PRIORITY ) /* Priority is deliberately chosen to match the original taskpool's priority. */ +#endif +#ifndef IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY + #define IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY ( 0 ) /* The dispatch queue and tasks will not use static memory by default. */ +#endif + +/* Provide the User-Agent Value definition fom coreHTTP. */ +#ifdef HTTP_USER_AGENT_VALUE + #define IOT_HTTPS_USER_AGENT HTTP_USER_AGENT_VALUE +#endif + +/** @endcond */ + +/* Error checking of macro configurations. */ +#if IOT_HTTPS_DISPATCH_TASK_COUNT < 1 + #error "IOT_HTTPS_DISPATCH_TASK_COUNT must be at least 1." +#endif +#if IOT_HTTPS_DISPATCH_QUEUE_SIZE < 1 + #error "IOT_HTTPS_DISPATCH_QUEUE_SIZE must be at least 1." +#endif +#if IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY == 1 && configSUPPORT_STATIC_ALLOCATION != 1 + #error "IOT_HTTPS_DISPATCH_USE_STATIC_MEMORY is 1, but configSUPPORT_STATIC_ALLOCATION is not set to 1." +#endif + +/** + * @brief The HTTP protocol version of this library is HTTP/1.1. + */ +#define HTTPS_PROTOCOL_VERSION "HTTP/1.1" + +/** + * @brief An empty path for a NULL specified path in the request initialization configuration. + */ +#define HTTPS_EMPTY_PATH "/" + +/** + * @brief HTTPS "CONNECT" method, defined as the longest string length method. + */ +#define HTTPS_CONNECT_METHOD "CONNECT" + +/* + * Constants for the values of the HTTP "Connection" header field. + * + * This is used for writing headers automatically during the sending of the HTTP request. + * "Connection: keep-alive\r\n" is written automatically for a persistent connection. + * "Connection: close\r\n" is written automatically for a non-persistent connection. + */ +#define HTTPS_CONNECTION_KEEP_ALIVE_HEADER_VALUE "keep-alive" +#define HTTPS_CONNECTION_CLOSE_HEADER_VALUE "close" + +/** + * Constants for HTTP header formatting. + * + * ": " separates and header field from the header value. + */ +#define HTTPS_HEADER_FIELD_SEPARATOR ": " +#define HTTPS_HEADER_FIELD_SEPARATOR_LENGTH ( 2 ) +#define COLON_CHARACTER ':' +#define SPACE_CHARACTER ' ' + +/** + * Constants for HTTP header formatting. + * + * "\r\n" Ends the header line. + */ +#define HTTPS_END_OF_HEADER_LINES_INDICATOR "\r\n" +#define HTTPS_END_OF_HEADER_LINES_INDICATOR_LENGTH ( 2 ) +#define CARRIAGE_RETURN_CHARACTER '\r' +#define NEWLINE_CHARACTER '\n' + +/* + * Constants for header fields added automatically during the request initialization. + */ +#define HTTPS_USER_AGENT_HEADER "User-Agent" +#define HTTPS_HOST_HEADER "Host" + +/* + * Constants for the header fields added automatically during the sending of the HTTP request. + */ +#define HTTPS_CONTENT_LENGTH_HEADER "Content-Length" +#define HTTPS_CONNECTION_HEADER "Connection" + +/* + * Constant for a mocked response so that #HTTPClient_Send returns #HTTPSuccess. + */ +#define HTTPS_MINIMAL_MOCKED_RESPONSE "HTTP/1.1 404\r\nContent-Length: 0\r\n\r\n" + +/** + * @brief The maximum Content-Length header line size. + * + * This is the length of header line string: "Content-Length: 4294967296\r\n". 4294967296 is 2^32. This number is chosen + * because it is the maximum file size that can be represented in a 32 bit system. + * + * This is used to initialize a local array for the final headers to send. + */ +#define HTTPS_MAX_CONTENT_LENGTH_LINE_LENGTH ( 26 ) + +/** + * @brief Macro for fast string length calculation of string macros. + * + * We subtract 1 to subtract the NULL terminating character. + * We do not assume that the size of a character is a single byte or 8 bits with this calculation. + */ +#define FAST_MACRO_STRLEN( x ) ( ( sizeof( x ) / sizeof( char ) ) - 1 ) + +/*-----------------------------------------------------------*/ + +/** + * @brief The state of the HTTP response parsing. + * + * This state notes what has been parsed in the HTTP response. As soon as any part of the HTTP response is received from + * the network, it is sent to be parsed. + * + * The states move as follows: + * PARSER_STATE_NONE --> PARSER_STATE_IN_HEADERS --> PARSER_STATE_HEADERS_COMPLETE --> PARSER_STATE_BODY_COMPLETE + * + * The parser callbacks are called in the following order: + * 1. _httpParserOnMessageBeginCallback() + * 2. _httpParserOnStatusCallback() + * 3. _httpParserOnHeaderFieldCallback() + * 4. _httpParserOnHeaderValueCallback() + * 5. _httpParserOnHeadersCompleteCallback() + * 6. _httpParserOnChunkHeaderCallback() (optional only if the response is chunked) + * 7. _httpParserOnBodyCallback() + * 8. _httpParserOnChunkCompleteCallback() (optional only if the response is chunked) + * 9. _httpParserOnMessageCompleteCallback() + * + * Theses states are set in the parser callbacks and used outside the callbacks to determine action. + * + * PARSER_STATE_NONE is assigned to #_httpsResponse_t.parserState when the _httpsResponse_t.parserState is initialized + * in @ref IotHttpsClient_InitializeRequest and before parsing a new respone message from the server. + * + * PARSER_STATE_IN_HEADERS is assigned at the start of the HTTP Response message. This occurs in the + * _httpParserOnMessageBeginCallback(). HTTP headers are always first and there is always the response status line + * and some headers in a response message according to RFC 2616. + * + * PARSER_STATE_HEADERS_COMPLETE is assigned when all of the headers are finished being parsed in the HTTP response + * message. This occurs in the _httpParserOnHeadersCompleteCallback(). The state can end here if the response has no + * body, like for a response to a HEAD request. + * If this state is not reached after receiving headers from the network into the user configured header buffer and + * running it through the parser, then we know that not all of the headers from the response could fit into the buffer. + * + * PARSER_STATE_IN_BODY is assigned each time the parser reaches HTTP response body. This occurs in the + * _httpParserOnBodyCallback(). + * + * PARSER_STATE_BODY_COMPLETE is assigned when the parser has finished with the whole HTTP response message. This + * happens when _httpParserOnMessageCompleteCallback() is invoked. + * If this state is not reached after receiving body from the network into the user configured body buffer and + * running it through the parser, then we know that not all of the body from the response could fit into the buffer. + */ +typedef enum IotHttpsResponseParserState +{ + PARSER_STATE_NONE = 0, /**< @brief The parser has not started so we are neither in the headers or the body. */ + PARSER_STATE_IN_HEADERS, /**< @brief The parser is currently parsing the HTTP respone headers. */ + PARSER_STATE_HEADERS_COMPLETE, /**< @brief The parser has finished parsing the headers. */ + PARSER_STATE_IN_BODY, /**< @brief The parser is currently parsing the HTTP response body. */ + PARSER_STATE_BODY_COMPLETE /**< @brief The parser has completed parsing the HTTP response body. */ +} IotHttpsResponseParserState_t; + +/** + * @brief The state denoting which buffer (the header buffer or the body buffer) is currently being processed + * and for what. + * + * This state is set outside of the parser callbacks and used inside the of parser callbacks to determine actions. + * + * The state moves as follows: + * Receiving and parsing a response: PROCESSING_STATE_NONE --> PROCESSING_STATE_FILLING_HEADER_BUFFER --> PROCESSING_STATE_FILLING_BODY_BUFFER --> PROCESSING_STATE_FINISHED + * Searching a response for headers: ((enter state)) --> PROCESSING_STATE_SEARCHING_HEADER_BUFFER --> ((enter state)) + * + * PROCESSING_STATE_NONE is assigned when #_httpsResponse_t.bufferProcessingState is initialized in + * @ref IotHttpsClient_InitializeRequest. + * + * PROCESSING_STATE_FILLING_HEADER_BUFFER is assigned at the start of receiving HTTP response headers from the network + * into the header buffer, before processing the received headers with the parser. + * This state is then used in the parser callbacks _httpParserOnStatusCallback(), _httpParserOnHeaderFieldCallback(), + * _httpParserOnHeaderValueCallback(), and _httpParserOnHeadersCompleteCallback() to move the + * #_httpsResponse_t.headersCur pointer along in the header buffer. + * Since the server sends the HTTP response as a single continuous message, sometimes during receiving of the HTTP + * headers we may receive part or all of the HTTP response body: + * ((example header buffer))[headers headers headers headers body body body] + * When parsing this header buffer the parser will execute _httpParserOnBodyCallback() in the + * PROCESSING_STATE_FILLING_HEADER_BUFFER state. The state is used here, for an asynchronous response, to save where + * and how much body is inside the of the header buffer. When a body buffer becomes available, the body in the header + * buffer will be copied to the body buffer. + * + * PROCESSING_STATE_FILLING_BODY_BUFFER is assigned at the start of receiving the HTTP response body form the network + * into the body buffer, before processing the received body with the parser. + * + * PROCESSING_STATE_FINISHED is assigned at the end of IotHttpsClient_SendSync() or at the end of + * IotHttpsClient_SendAsync() when both the header and body buffer are finished being filled with network data and + * parsed. + * + * PROCESSING_STATE_SEARCHING_HEADER_BUFFER is assigned in IotHttpsClient_ReadHeader() when searching for a header + * in the header buffer. + * This state is used in the parser callback _httpParserOnHeaderFieldCallback() to check if the current header field + * parsed equals the header we are searching for. It is used in parser callback _httpParserOnHeaderValueCallback() to + * return the header value if the corresponding field we are searching for was found. It is used in parser callback + * _httpParserOnHeadersCompleteCallback() to stop parsing the header buffer if the header we are searching for was not + * found. + * + * The header buffer is separate from the body buffer. + * The header buffer is configured in #IotHttpRequestInfo_t.respUserBuff. The body buffer is configured in + * #IotHttpRequestInfo_t.syncInfo->respData or as buffer provided asynchronously during the + * #IotHttpsClientCallbacks_t.readReadyCallback() to call to @ref IotHttpsClient_ReadResponseBody(). + */ +typedef enum IotHttpsResponseBufferState +{ + PROCESSING_STATE_NONE, /**< @brief There is no buffer processing currently. */ + PROCESSING_STATE_FILLING_HEADER_BUFFER, /**< @brief The header buffer is being filled and parsed. */ + PROCESSING_STATE_FILLING_BODY_BUFFER, /**< @brief The body buffer is being filled and parsed. */ + PROCESSING_STATE_FINISHED, /**< @brief Filling and parsing of both buffers is finished. */ + PROCESSING_STATE_SEARCHING_HEADER_BUFFER /**< @brief The header buffer is being searched. */ +} IotHttpsResponseBufferState_t; + +/*-----------------------------------------------------------*/ + +/** + * @brief Represents an HTTP connection. + */ +typedef struct _httpsConnection +{ + const IotNetworkInterface_t * pNetworkInterface; /**< @brief Network interface with calls for connect, disconnect, send, and receive. */ + void * pNetworkConnection; /**< @brief Pointer to the network connection to use pNetworkInterface calls on. */ + uint32_t timeout; /**< @brief Timeout for a connection and waiting for a response from the network. */ + + /** + * @brief true if a connection was successful most recently on this context + * + * We have no way of knowing if the server closed the connection because that error is unique to the underlying TLS + * layer. This is set to false initially, then set to true for a successful intentional call to connect. + * Post connection, this is set to false only after an implicit disconnect with a non-persistent request, an implicit + * disconnect with a network error, or an explicit disconnect with a call to @ref https_client_function_disconnect. + */ + bool isConnected; + bool isDestroyed; /**< @brief true if the connection is already destroyed and we should not make calls on it anymore. */ + IotMutex_t connectionMutex; /**< @brief Mutex protecting operations on this entire connection context. */ + IotDeQueue_t reqQ; /**< @brief The queue for the requests that are not finished yet. */ + IotDeQueue_t respQ; /**< @brief The queue for the responses that are waiting to be processed. */ +} _httpsConnection_t; + +/** + * @brief Third party library http-parser information. + * + * There are two separate structures for http_parser state information. This is so that the application can read + * a header during it's readReadyCallback. The readReadyCallback could be invoked many times and the parser will + * therefore be invoked many times for each response read from the network. In order to ensure that the state of + * the parser remains intact whilst headers may be read, two structures holding the state are kept. + */ +typedef struct _httpParserInfo +{ + http_parser responseParser; /**< @brief http_parser state information for parsing the response. */ + size_t ( * parseFunc )( http_parser * parser, + const http_parser_settings * settings, + const char * data, + size_t len ); /**< @brief http_parser_execute function is to be plugged in here during initialization of the response. */ + http_parser readHeaderParser; /**< @brief http_parser state information for parsing the header buffer for reading a header. */ +} _httpParserInfo_t; + +/** + * @brief Represents an HTTP response. + */ +typedef struct _httpsResponse +{ + IotLink_t link; /**< @brief The link to insert the job in the connection's respQ. */ + uint8_t * pHeaders; /**< @brief Pointer to the start of the headers buffer. */ + uint8_t * pHeadersEnd; /**< @brief Pointer to the end of the headers buffer. */ + uint8_t * pHeadersCur; /**< @brief Pointer to the next location to write in the headers buffer. */ + uint8_t * pBody; /**< @brief Pointer to the start of the body buffer. */ + uint8_t * pBodyEnd; /**< @brief Pointer to the end of the body buffer. */ + uint8_t * pBodyCur; /**< @brief Pointer to the next location to write in the body buffer. */ + _httpParserInfo_t httpParserInfo; /**< @brief Third party http-parser information. */ + uint16_t status; /**< @brief The HTTP response status code of this response. */ + IotHttpsMethod_t method; /**< @brief The method of the originating request. */ + IotHttpsResponseParserState_t parserState; /**< @brief The current state of the parser. See #IotHttpsResponseParserState_t documentation for more details. */ + IotHttpsResponseBufferState_t bufferProcessingState; /**< @brief Which buffer is currently being processed and for what. See #IotHttpsResponseBufferState_t documentation. */ + char * pReadHeaderField; /**< @brief Header field that we want to read from the headers buffer when IotHttpsClient_ReadHeader() is called. */ + size_t readHeaderFieldLength; /**< @brief Length of pReadHeaderField */ + char * pReadHeaderValue; /**< @brief Header value that we read from the headers buffer when IotHttpsClient_ReadHeader() is called. */ + size_t readHeaderValueLength; /**< @brief Length of pReadHeaderValue. */ + bool foundHeaderField; /**< @brief State to use during parsing to let us know when we found the header field in the https-parser callbacks. + * This is set to true when the header field is found in parser callback _httpParserOnHeaderFieldCallback(). + * On the following parser callback _httpParserOnHeaderValueCallback() we will store the value in pReadHeaderValue and then exit the parsing. */ + struct _httpsConnection * pHttpsConnection; /**< @brief Connection associated with response. This is set during IotHttpsClient_SendAsync(). This is needed during the asynchronous workflow to receive data given the respHandle only in the callback. */ + bool isAsync; /**< @brief This is set to true if this response is to be retrieved asynchronously. Set to false otherwise. */ + uint8_t * pBodyInHeaderBuf; /**< @brief Pointer to the start of body inside the header buffer for copying to a body buffer provided later by the asynchronous response process. */ + uint8_t * pBodyCurInHeaderBuf; /**< @brief Pointer to the next location to write body data during processing of the header buffer. This is necessary in case there is a chunk encoded HTTP response. */ + IotHttpsReturnCode_t bodyRxStatus; /**< @brief The status of network receiving the HTTPS body to be returned during the #IotHttpsClientCallbacks_t.readReadyCallback. */ + bool cancelled; /**< @brief This is set to true to stop the request/response processing in the asynchronous request workflow. */ + IotSemaphore_t respFinishedSem; /**< @brief This is for synchronous response to post that is finished being received. It is better to use a task event signal, but that is not implemented yet in the iot_threads.h API. */ + IotHttpsReturnCode_t syncStatus; /**< @brief The status of the synchronous response. */ + + /** + * @brief This is set to true to when the request is finished being sent on the network + * + * A request is not shared with multiple tasks, so only one task will update this. This is to let the let the + * network receive callback know that the request is fully pushed out to the server. This is also to let the + * disconnect know that the request is not using the network interface resources anymore. + */ + bool reqFinishedSending; + IotHttpsClientCallbacks_t * pCallbacks; /**< @brief Pointer to the asynchronous request callbacks. */ + void * pUserPrivData; /**< @brief User private data to hand back in the asynchronous callbacks for context. */ + bool isNonPersistent; /**< @brief Non-persistent flag to indicate closing the connection immediately after receiving the response. */ +} _httpsResponse_t; + +/** + * @brief Represents and HTTP request. + */ +typedef struct _httpsRequest +{ + IotLink_t link; /**< @brief The link to insert the job in the connection's reqQ. */ + uint8_t * pHeaders; /**< @brief Pointer to the start of the headers buffer. */ + uint8_t * pHeadersEnd; /**< @brief Pointer to the end of the headers buffer. */ + uint8_t * pHeadersCur; /**< @brief Pointer to the next location to write in the headers buffer. */ + uint8_t * pBody; /**< @brief Pointer to the start of the body buffer. */ + uint32_t bodyLength; /**< @brief Length of request body buffer. */ + IotHttpsMethod_t method; /**< @brief The method of the originating request. */ + IotHttpsConnectionInfo_t * pConnInfo; /**< @brief Connection info associated with this request. For an implicit connection. */ + struct _httpsResponse * pHttpsResponse; /**< @brief Response associated with request. This is initialized during IotHttpsClient_InitializeRequest(), then returned to the application in IotHttpsClient_SendAsync() and IotHttpsClient_SendSync(). */ + struct _httpsConnection * pHttpsConnection; /**< @brief Connection associated with request. This is set during IotHttpsClient_SendAsync(). It is needed for the asynchronous workflow to use to send data given the reqHandle only in the callback. */ + bool isNonPersistent; /**< @brief Non-persistent flag to indicate closing the connection immediately after receiving the response. */ + bool isAsync; /**< @brief This is set to true if this request is to be sent asynchronously. Set to false otherwise. */ + void * pUserPrivData; /**< @brief User private data to hand back in the asynchronous callbacks for context. */ + IotHttpsClientCallbacks_t * pCallbacks; /**< @brief Pointer to the asynchronous request callbacks. */ + bool cancelled; /**< @brief Set this to true to stop the response processing in the asynchronous workflow. */ + IotHttpsReturnCode_t bodyTxStatus; /**< @brief The status of network sending the HTTPS body to be returned during the #IotHttpsClientCallbacks_t.writeCallback. */ + bool scheduled; /**< @brief Set to true when this request has already been added to the dispatch queue. */ +} _httpsRequest_t; + +/*-----------------------------------------------------------*/ + +/** + * @brief A map of the method enum to strings + * + * These are in the same order as the HTTP request method enums defined in IotHttpsMethod_t. + */ +extern const char * _pHttpsMethodStrings[]; + +#endif /* IOT_HTTPS_INTERNAL_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt.h b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt.h new file mode 100644 index 0000000..545c54e --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt.h @@ -0,0 +1,869 @@ +/* + * FreeRTOS MQTT V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt.h + * @brief User-facing functions of the MQTT 3.1.1 library. + */ + +#ifndef IOT_MQTT_H_ +#define IOT_MQTT_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* MQTT types include. */ +#include "types/iot_mqtt_types.h" + +/*------------------------- MQTT library functions --------------------------*/ + +/** + * @functions_page{mqtt, MQTT} + * @functions_brief{mqtt} + * - @function_name{mqtt_function_init} + * @function_brief{mqtt_function_init} + * - @function_name{mqtt_function_cleanup} + * @function_brief{mqtt_function_cleanup} + * - @function_name{mqtt_function_receivecallback} + * @function_brief{mqtt_function_receivecallback} + * - @function_name{mqtt_function_connect} + * @function_brief{mqtt_function_connect} + * - @function_name{mqtt_function_disconnect} + * @function_brief{mqtt_function_disconnect} + * - @function_name{mqtt_function_subscribe} + * @function_brief{mqtt_function_subscribe} + * - @function_name{mqtt_function_timedsubscribe} + * @function_brief{mqtt_function_timedsubscribe} + * - @function_name{mqtt_function_unsubscribe} + * @function_brief{mqtt_function_unsubscribe} + * - @function_name{mqtt_function_timedunsubscribe} + * @function_brief{mqtt_function_timedunsubscribe} + * - @function_name{mqtt_function_publish} + * @function_brief{mqtt_function_publish} + * - @function_name{mqtt_function_timedpublish} + * @function_brief{mqtt_function_timedpublish} + * - @function_name{mqtt_function_wait} + * @function_brief{mqtt_function_wait} + * - @function_name{mqtt_function_strerror} + * @function_brief{mqtt_function_strerror} + * - @function_name{mqtt_function_operationtype} + * @function_brief{mqtt_function_operationtype} + * - @function_name{mqtt_function_issubscribed} + * @function_brief{mqtt_function_issubscribed} + */ + +/** + * @page mqtt_function_init IotMqtt_Init + * @snippet this declare_mqtt_init + * @copydoc IotMqtt_Init + * @page mqtt_function_cleanup IotMqtt_Cleanup + * @snippet this declare_mqtt_cleanup + * @copydoc IotMqtt_Cleanup + * @page mqtt_function_receivecallback IotMqtt_ReceiveCallback + * @snippet this declare_mqtt_receivecallback + * @copydoc IotMqtt_ReceiveCallback + * @page mqtt_function_connect IotMqtt_Connect + * @snippet this declare_mqtt_connect + * @copydoc IotMqtt_Connect + * @page mqtt_function_disconnect IotMqtt_Disconnect + * @snippet this declare_mqtt_disconnect + * @copydoc IotMqtt_Disconnect + * @page mqtt_function_subscribe IotMqtt_Subscribe + * @snippet this declare_mqtt_subscribe + * @copydoc IotMqtt_Subscribe + * @page mqtt_function_timedsubscribe IotMqtt_TimedSubscribe + * @snippet this declare_mqtt_timedsubscribe + * @copydoc IotMqtt_TimedSubscribe + * @page mqtt_function_unsubscribe IotMqtt_Unsubscribe + * @snippet this declare_mqtt_unsubscribe + * @copydoc IotMqtt_Unsubscribe + * @page mqtt_function_timedunsubscribe IotMqtt_TimedUnsubscribe + * @snippet this declare_mqtt_timedunsubscribe + * @copydoc IotMqtt_TimedUnsubscribe + * @page mqtt_function_publish IotMqtt_Publish + * @snippet this declare_mqtt_publish + * @copydoc IotMqtt_Publish + * @page mqtt_function_timedpublish IotMqtt_TimedPublish + * @snippet this declare_mqtt_timedpublish + * @copydoc IotMqtt_TimedPublish + * @page mqtt_function_wait IotMqtt_Wait + * @snippet this declare_mqtt_wait + * @copydoc IotMqtt_Wait + * @page mqtt_function_strerror IotMqtt_strerror + * @snippet this declare_mqtt_strerror + * @copydoc IotMqtt_strerror + * @page mqtt_function_operationtype IotMqtt_OperationType + * @snippet this declare_mqtt_operationtype + * @copydoc IotMqtt_OperationType + * @page mqtt_function_issubscribed IotMqtt_IsSubscribed + * @snippet this declare_mqtt_issubscribed + * @copydoc IotMqtt_IsSubscribed + */ + +/** + * @brief One-time initialization function for the MQTT library. + * + * This function performs setup of the MQTT library. It must be called + * once (and only once) before calling any other MQTT function. Calling this + * function more than once without first calling @ref mqtt_function_cleanup + * may result in a crash. + * + * @return One of the following: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_INIT_FAILED + * + * @warning No thread-safety guarantees are provided for this function. + * + * @see @ref mqtt_function_cleanup + */ +/* @[declare_mqtt_init] */ +IotMqttError_t IotMqtt_Init( void ); +/* @[declare_mqtt_init] */ + +/** + * @brief One-time deinitialization function for the MQTT library. + * + * This function frees resources taken in @ref mqtt_function_init. It should be + * called after [closing all MQTT connections](@ref mqtt_function_disconnect) to + * clean up the MQTT library. After this function returns, @ref mqtt_function_init + * must be called again before calling any other MQTT function. + * + * @warning No thread-safety guarantees are provided for this function. Do not + * call this function if any MQTT connections are open! + * + * @see @ref mqtt_function_init + */ +/* @[declare_mqtt_cleanup] */ +void IotMqtt_Cleanup( void ); +/* @[declare_mqtt_cleanup] */ + +/** + * @brief Network receive callback for the MQTT library. + * + * This function should be called by the system whenever data is available for + * the MQTT library. + * + * @param[in] pNetworkConnection The network connection associated with the MQTT + * connection, passed by the network stack. + * @param[in] pReceiveContext A pointer to the MQTT connection handle for which + * the packet was received. + */ +/* @[declare_mqtt_receivecallback] */ +void IotMqtt_ReceiveCallback( void * pNetworkConnection, + void * pReceiveContext ); +/* @[declare_mqtt_receivecallback] */ + +/** + * @brief Establish a new MQTT connection. + * + * This function opens a connection between a new MQTT client and an MQTT server + * (also called a broker). MQTT connections are established on top of transport + * layer protocols (such as TCP/IP), and optionally, application layer security + * protocols (such as TLS). The MQTT packet that establishes a connection is called + * the MQTT CONNECT packet. After @ref mqtt_function_init, this function must be + * called before any other MQTT library function. + * + * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `true`, + * this function establishes a clean MQTT session. Subscriptions and unacknowledged + * PUBLISH messages will be discarded when the connection is closed. + * + * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `false`, + * this function establishes (or re-establishes) a persistent MQTT session. The parameters + * [pConnectInfo->pPreviousSubscriptions](@ref IotMqttConnectInfo_t.pPreviousSubscriptions) + * and [pConnectInfo->previousSubscriptionCount](@ref IotMqttConnectInfo_t.previousSubscriptionCount) + * may be used to restore subscriptions present in a re-established persistent session. + * Any restored subscriptions MUST have been present in the persistent session; + * this function does not send an MQTT SUBSCRIBE packet! + * + * This MQTT library is network agnostic, meaning it has no knowledge of the + * underlying network protocol carrying the MQTT packets. It interacts with the + * network through a network abstraction layer, allowing it to be used with many + * different network stacks. The network abstraction layer is established + * per-connection, allowing every #IotMqttConnection_t to use a different network + * stack. The parameter `pNetworkInterface` sets up the network abstraction layer + * for an MQTT connection; see the documentation on #IotMqttNetworkInfo_t for details + * on its members. + * + * The `pConnectInfo` parameter provides the contents of the MQTT CONNECT packet. + * Most members [are defined by the MQTT spec.](@ref IotMqttConnectInfo_t). The + * [pConnectInfo->pWillInfo](@ref IotMqttConnectInfo_t.pWillInfo) member provides + * information on a Last Will and Testament (LWT) message to be published if the + * MQTT connection is closed without [sending a DISCONNECT packet] + * (@ref mqtt_function_disconnect). Unlike other PUBLISH + * messages, a LWT message payload is limited to 65535 bytes in length. Additionally, + * the retry [interval](@ref IotMqttPublishInfo_t.retryMs) and [limit] + * (@ref IotMqttPublishInfo_t.retryLimit) members of #IotMqttPublishInfo_t + * are ignored for LWT messages. The LWT message is optional; `pWillInfo` may be NULL. + * + * Unlike @ref mqtt_function_publish, @ref mqtt_function_subscribe, and + * @ref mqtt_function_unsubscribe, this function is always blocking. Additionally, + * because the MQTT connection acknowledgement packet (CONNACK packet) does not + * contain any information on which CONNECT packet it acknowledges, only one + * CONNECT operation may be in progress at any time. This means that parallel + * threads making calls to @ref mqtt_function_connect will be serialized to send + * their CONNECT packets one-by-one. + * + * @param[in] pNetworkInfo Information on the transport-layer network connection + * to use with the MQTT connection. + * @param[in] pConnectInfo MQTT connection setup parameters. + * @param[in] timeoutMs If the MQTT server does not accept the connection within + * this timeout, this function returns #IOT_MQTT_TIMEOUT. + * @param[out] pMqttConnection Set to a newly-initialized MQTT connection handle + * if this function succeeds. + * + * @return One of the following: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + * - #IOT_MQTT_TIMEOUT + * - #IOT_MQTT_SERVER_REFUSED + * + * Example + * @code{c} + * // An initialized and connected network connection. + * IotNetworkConnection_t pNetworkConnection; + * + * // Parameters to MQTT connect. + * IotMqttConnection_t mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER; + * IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER; + * IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER; + * IotMqttPublishInfo_t willInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER; + * + * // Example network abstraction types. + * IotNetworkServerInfo_t serverInfo = { ... }; + * IotNetworkCredentials_t credentialInfo = { ... }; + * IotNetworkInterface_t networkInterface = { ... }; + * + * // Example using a generic network implementation. + * networkInfo.createNetworkConnection = true; + * networkInfo.u.setup.pNetworkServerInfo = &serverInfo; + * networkInfo.u.setup.pNetworkCredentialInfo = &credentialInfo; + * networkInfo.pNetworkInterface = &networkInterface; + * + * // Set the members of the connection info (password and username not used). + * connectInfo.cleanSession = true; + * connectInfo.keepAliveSeconds = 30; + * connectInfo.pClientIdentifier = "uniqueclientidentifier"; + * connectInfo.clientIdentifierLength = 22; + * + * // Set the members of the will info (retain and retry not used). + * willInfo.qos = IOT_MQTT_QOS_1; + * willInfo.pTopicName = "will/topic/name"; + * willInfo.topicNameLength = 15; + * willInfo.pPayload = "MQTT client unexpectedly disconnected."; + * willInfo.payloadLength = 38; + * + * // Set the pointer to the will info. + * connectInfo.pWillInfo = &willInfo; + * + * // Call CONNECT with a 5 second block time. Should return + * // IOT_MQTT_SUCCESS when successful. + * IotMqttError_t result = IotMqtt_Connect( &networkInfo, + * &connectInfo, + * 5000, + * &mqttConnection ); + * + * if( result == IOT_MQTT_SUCCESS ) + * { + * // Do something with the MQTT connection... + * + * // Clean up and close the MQTT connection once it's no longer needed. + * IotMqtt_Disconnect( mqttConnection, 0 ); + * } + * @endcode + */ +/* @[declare_mqtt_connect] */ +IotMqttError_t IotMqtt_Connect( const IotMqttNetworkInfo_t * pNetworkInfo, + const IotMqttConnectInfo_t * pConnectInfo, + uint32_t timeoutMs, + IotMqttConnection_t * const pMqttConnection ); +/* @[declare_mqtt_connect] */ + +/** + * @brief Closes an MQTT connection and frees resources. + * + * This function closes an MQTT connection and MUST be called ONLY ONCE once + * the MQTT connection is no longer needed. Its exact behavior depends on the + * `flags` parameter. + * + * Normally, `flags` should be `0`. This gracefully shuts down an MQTT + * connection by sending an MQTT DISCONNECT packet. Any [network close function] + * (@ref IotNetworkInterface_t::close) provided [when the connection was established] + * (@ref mqtt_function_connect) will also be called. Note that because the MQTT server + * will not acknowledge a DISCONNECT packet, the client has no way of knowing if + * the server received the DISCONNECT packet. In the case where the DISCONNECT + * packet is lost in transport, any Last Will and Testament (LWT) message established + * with the connection may be published. However, if the DISCONNECT reaches the + * MQTT server, the LWT message will be discarded and not published. + * + * Should the underlying network connection become unusable, this function should + * be called with `flags` set to #IOT_MQTT_FLAG_CLEANUP_ONLY. In this case, no + * DISCONNECT packet will be sent, though the [network close function](@ref IotNetworkInterface_t::close) + * will still be called. This function will only free the resources used by the MQTT + * connection; it still must be called even if the network is offline to avoid leaking + * resources. + * + * @warning This function is NOT thread-safe. Once this function is called, its parameter + * @p mqttConnection MUST NOT be used anymore. + * + * @param[in] mqttConnection The MQTT connection to close and clean up. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + */ +/* @[declare_mqtt_disconnect] */ +void IotMqtt_Disconnect( IotMqttConnection_t mqttConnection, + uint32_t flags ); +/* @[declare_mqtt_disconnect] */ + +/** + * @brief Subscribes to the given array of topic filters and receive an asynchronous + * notification when the subscribe completes. + * + * This function transmits an MQTT SUBSCRIBE packet to the server. A SUBSCRIBE + * packet notifies the server to send any matching PUBLISH messages to this client. + * A single SUBSCRIBE packet may carry more than one topic filter, hence the + * parameters to this function include an array of [subscriptions] + * (@ref IotMqttSubscription_t). + * + * An MQTT subscription has two pieces: + * 1. The subscription topic filter registered with the MQTT server. The MQTT + * SUBSCRIBE packet sent from this client to server notifies the server to send + * messages matching the given topic filters to this client. + * 2. The [callback function](@ref IotMqttCallbackInfo_t.function) that this + * client will invoke when an incoming message is received. The callback function + * notifies applications of an incoming PUBLISH message. + * + * The helper function @ref mqtt_function_issubscribed can be used to check if a + * [callback function](@ref IotMqttCallbackInfo_t.function) is registered for + * a particular topic filter. + * + * To modify an already-registered subscription callback, call this function with + * a new `pSubscriptionList`. Any topic filters in `pSubscriptionList` that already + * have a registered callback will be replaced with the new values in `pSubscriptionList`. + * + * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid + * for subscription QoS. + * + * @param[in] mqttConnection The MQTT connection to use for the subscription. + * @param[in] pSubscriptionList Pointer to the first element in the array of + * subscriptions. + * @param[in] subscriptionCount The number of elements in pSubscriptionList. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + * @param[in] pCallbackInfo Asynchronous notification of this function's completion. + * @param[out] pSubscribeOperation Set to a handle by which this operation may be + * referenced after this function returns. This reference is invalidated once + * the subscription operation completes. + * + * @return This function will return #IOT_MQTT_STATUS_PENDING upon success. + * @return Upon completion of the subscription (either through an + * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + * - #IOT_MQTT_SERVER_REFUSED + * @return If this function fails before queuing a subscribe operation, it will return + * one of: + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * + * @see @ref mqtt_function_timedsubscribe for a blocking variant of this function. + * @see @ref mqtt_function_unsubscribe for the function that removes subscriptions. + * + * Example + * @code{c} + * #define NUMBER_OF_SUBSCRIPTIONS ... + * + * // Subscription callback function. + * void subscriptionCallback( void * pArgument, IotMqttCallbackParam_t * pPublish ); + * + * // An initialized and connected MQTT connection. + * IotMqttConnection_t mqttConnection; + * + * // Subscription information. + * pSubscriptions[ NUMBER_OF_SUBSCRIPTIONS ] = { IOT_MQTT_SUBSCRIPTION_INITIALIZER }; + * IotMqttOperation_t lastOperation = IOT_MQTT_OPERATION_INITIALIZER; + * + * // Set the subscription information. + * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ ) + * { + * pSubscriptions[ i ].qos = IOT_MQTT_QOS_1; + * pSubscriptions[ i ].pTopicFilter = "some/topic/filter"; + * pSubscriptions[ i ].topicLength = ( uint16_t ) strlen( pSubscriptions[ i ].pTopicFilter ); + * pSubscriptions[ i ].callback.function = subscriptionCallback; + * } + * + * IotMqttError_t result = IotMqtt_Subscribe( mqttConnection, + * pSubscriptions, + * NUMBER_OF_SUBSCRIPTIONS, + * IOT_MQTT_FLAG_WAITABLE, + * NULL, + * &lastOperation ); + * + * // Subscribe returns IOT_MQTT_STATUS_PENDING when successful. Wait up to + * // 5 seconds for the operation to complete. + * if( result == IOT_MQTT_STATUS_PENDING ) + * { + * result = IotMqtt_Wait( subscriptionRef, 5000 ); + * } + * + * // Check that the subscriptions were successful. + * if( result == IOT_MQTT_SUCCESS ) + * { + * // Wait for messages on the subscription topic filters... + * + * // Unsubscribe once the subscriptions are no longer needed. + * result = IotMqtt_Unsubscribe( mqttConnection, + * pSubscriptions, + * NUMBER_OF_SUBSCRIPTIONS, + * IOT_MQTT_FLAG_WAITABLE, + * NULL, + * &lastOperation ); + * + * // UNSUBSCRIBE returns IOT_MQTT_STATUS_PENDING when successful. + * // Wait up to 5 seconds for the operation to complete. + * if( result == IOT_MQTT_STATUS_PENDING ) + * { + * result = IotMqtt_Wait( lastOperation, 5000 ); + * } + * } + * // Check which subscriptions were rejected by the server. + * else if( result == IOT_MQTT_SERVER_REFUSED ) + * { + * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ ) + * { + * if( IotMqtt_IsSubscribed( mqttConnection, + * pSubscriptions[ i ].pTopicFilter, + * pSubscriptions[ i ].topicFilterLength, + * NULL ) == false ) + * { + * // This subscription was rejected. + * } + * } + * } + * @endcode + */ +/* @[declare_mqtt_subscribe] */ +IotMqttError_t IotMqtt_Subscribe( IotMqttConnection_t mqttConnection, + const IotMqttSubscription_t * pSubscriptionList, + size_t subscriptionCount, + uint32_t flags, + const IotMqttCallbackInfo_t * pCallbackInfo, + IotMqttOperation_t * pSubscribeOperation ); +/* @[declare_mqtt_subscribe] */ + +/** + * @brief Subscribes to the given array of topic filters with a timeout. + * + * This function transmits an MQTT SUBSCRIBE packet to the server, then waits for + * a server response to the packet. Internally, this function is a call to @ref + * mqtt_function_subscribe followed by @ref mqtt_function_wait. See @ref + * mqtt_function_subscribe for more information about the MQTT SUBSCRIBE operation. + * + * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid + * for subscription QoS. + * + * @param[in] mqttConnection The MQTT connection to use for the subscription. + * @param[in] pSubscriptionList Pointer to the first element in the array of + * subscriptions. + * @param[in] subscriptionCount The number of elements in pSubscriptionList. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + * Currently, flags are ignored by this function; this parameter is for + * future-compatibility. + * @param[in] timeoutMs If the MQTT server does not acknowledge the subscriptions within + * this timeout, this function returns #IOT_MQTT_TIMEOUT. + * + * @return One of the following: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + * - #IOT_MQTT_TIMEOUT + * - #IOT_MQTT_SERVER_REFUSED + */ +/* @[declare_mqtt_timedsubscribe] */ +IotMqttError_t IotMqtt_TimedSubscribe( IotMqttConnection_t mqttConnection, + const IotMqttSubscription_t * pSubscriptionList, + size_t subscriptionCount, + uint32_t flags, + uint32_t timeoutMs ); +/* @[declare_mqtt_timedsubscribe] */ + +/** + * @brief Unsubscribes from the given array of topic filters and receive an asynchronous + * notification when the unsubscribe completes. + * + * This function transmits an MQTT UNSUBSCRIBE packet to the server. An UNSUBSCRIBE + * packet removes registered topic filters from the server. After unsubscribing, + * the server will no longer send messages on these topic filters to the client. + * + * Corresponding [subscription callback functions](@ref IotMqttCallbackInfo_t.function) + * are also removed from the MQTT connection. These subscription callback functions + * will be removed even if the MQTT UNSUBSCRIBE packet fails to send. + * + * @param[in] mqttConnection The MQTT connection used for the subscription. + * @param[in] pSubscriptionList Pointer to the first element in the array of + * subscriptions. + * @param[in] subscriptionCount The number of elements in pSubscriptionList. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + * @param[in] pCallbackInfo Asynchronous notification of this function's completion. + * @param[out] pUnsubscribeOperation Set to a handle by which this operation may be + * referenced after this function returns. This reference is invalidated once + * the unsubscribe operation completes. + * + * @return This function will return #IOT_MQTT_STATUS_PENDING upon success. + * @return Upon completion of the unsubscribe (either through an + * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + * @return If this function fails before queuing an unsubscribe operation, it will return + * one of: + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * + * @see @ref mqtt_function_timedsubscribe for a blocking variant of this function. + * @see @ref mqtt_function_subscribe for the function that adds subscriptions. + */ +/* @[declare_mqtt_unsubscribe] */ +IotMqttError_t IotMqtt_Unsubscribe( IotMqttConnection_t mqttConnection, + const IotMqttSubscription_t * pSubscriptionList, + size_t subscriptionCount, + uint32_t flags, + const IotMqttCallbackInfo_t * pCallbackInfo, + IotMqttOperation_t * pUnsubscribeOperation ); +/* @[declare_mqtt_unsubscribe] */ + +/** + * @brief Unsubscribes from a given array of topic filters with a timeout. + * + * This function transmits an MQTT UNSUBSCRIBE packet to the server, then waits + * for a server response to the packet. Internally, this function is a call to + * @ref mqtt_function_unsubscribe followed by @ref mqtt_function_wait. See @ref + * mqtt_function_unsubscribe for more information about the MQTT UNSUBSCRIBE + * operation. + * + * @param[in] mqttConnection The MQTT connection used for the subscription. + * @param[in] pSubscriptionList Pointer to the first element in the array of + * subscriptions. + * @param[in] subscriptionCount The number of elements in pSubscriptionList. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + * Currently, flags are ignored by this function; this parameter is for + * future-compatibility. + * @param[in] timeoutMs If the MQTT server does not acknowledge the UNSUBSCRIBE within + * this timeout, this function returns #IOT_MQTT_TIMEOUT. + * + * @return One of the following: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + */ +/* @[declare_mqtt_timedunsubscribe] */ +IotMqttError_t IotMqtt_TimedUnsubscribe( IotMqttConnection_t mqttConnection, + const IotMqttSubscription_t * pSubscriptionList, + size_t subscriptionCount, + uint32_t flags, + uint32_t timeoutMs ); +/* @[declare_mqtt_timedunsubscribe] */ + +/** + * @brief Publishes a message to the given topic name and receive an asynchronous + * notification when the publish completes. + * + * This function transmits an MQTT PUBLISH packet to the server. A PUBLISH packet + * contains a payload and a topic name. Any clients with a subscription on a + * topic filter matching the PUBLISH topic name will receive a copy of the + * PUBLISH packet from the server. + * + * If a PUBLISH packet fails to reach the server and it is not a QoS 0 message, + * it will be retransmitted. See #IotMqttPublishInfo_t for a description + * of the retransmission strategy. + * + * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid + * for message QoS. + * + * @param[in] mqttConnection The MQTT connection to use for the publish. + * @param[in] pPublishInfo MQTT publish parameters. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + * @param[in] pCallbackInfo Asynchronous notification of this function's completion. + * @param[out] pPublishOperation Set to a handle by which this operation may be + * referenced after this function returns. This reference is invalidated once + * the publish operation completes. + * + * @return This function will return #IOT_MQTT_STATUS_PENDING upon success for + * QoS 1 publishes. For a QoS 0 publish it returns #IOT_MQTT_SUCCESS upon + * success. + * @return Upon completion of a QoS 1 publish (either through an + * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs) + * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set). + * @return If this function fails before queuing an publish operation (regardless + * of QoS), it will return one of: + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * + * @note The parameters `pCallbackInfo` and `pPublishOperation` should only be used for QoS + * 1 publishes. For QoS 0, they should both be `NULL`. + * + * @see @ref mqtt_function_timedpublish for a blocking variant of this function. + * + * Example + * @code{c} + * // An initialized and connected MQTT connection. + * IotMqttConnection_t mqttConnection; + * + * // Publish information. + * IotMqttPublishInfo_t publishInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER; + * + * // Set the publish information. QoS 0 example (retain not used): + * publishInfo.qos = IOT_MQTT_QOS_0; + * publishInfo.pTopicName = "some/topic/name"; + * publishInfo.topicNameLength = 15; + * publishInfo.pPayload = "payload"; + * publishInfo.payloadLength = 8; + * + * // QoS 0 publish should return IOT_MQTT_SUCCESS upon success. + * IotMqttError_t qos0Result = IotMqtt_Publish( mqttConnection, + * &publishInfo, + * 0, + * NULL, + * NULL ); + * + * // QoS 1 with retry example (using same topic name and payload as QoS 0 example): + * IotMqttOperation_t qos1Operation = IOT_MQTT_OPERATION_INITIALIZER; + * publishInfo.qos = IOT_MQTT_QOS_1; + * publishInfo.retryMs = 1000; // Retry if no response is received in 1 second. + * publishInfo.retryLimit = 5; // Retry up to 5 times. + * + * // QoS 1 publish should return IOT_MQTT_STATUS_PENDING upon success. + * IotMqttError_t qos1Result = IotMqtt_Publish( mqttConnection, + * &publishInfo, + * IOT_MQTT_FLAG_WAITABLE, + * NULL, + * &qos1Operation ); + * + * // Wait up to 5 seconds for the publish to complete. + * if( qos1Result == IOT_MQTT_STATUS_PENDING ) + * { + * qos1Result = IotMqtt_Wait( qos1Operation, 5000 ); + * } + * @endcode + */ +/* @[declare_mqtt_publish] */ +IotMqttError_t IotMqtt_Publish( IotMqttConnection_t mqttConnection, + const IotMqttPublishInfo_t * pPublishInfo, + uint32_t flags, + const IotMqttCallbackInfo_t * pCallbackInfo, + IotMqttOperation_t * pPublishOperation ); +/* @[declare_mqtt_publish] */ + +/** + * @brief Publish a message to the given topic name with a timeout. + * + * This function transmits an MQTT PUBLISH packet to the server, then waits for + * a server response to the packet. Internally, this function is a call to @ref + * mqtt_function_publish followed by @ref mqtt_function_wait. See @ref + * mqtt_function_publish for more information about the MQTT PUBLISH operation. + * + * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid + * for message QoS. + * + * @param[in] mqttConnection The MQTT connection to use for the publish. + * @param[in] pPublishInfo MQTT publish parameters. + * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. + * Currently, flags are ignored by this function; this parameter is for + * future-compatibility. + * @param[in] timeoutMs If the MQTT server does not acknowledge a QoS 1 PUBLISH + * within this timeout, this function returns #IOT_MQTT_TIMEOUT. This parameter + * is ignored for QoS 0 PUBLISH messages. + * + * @return One of the following: + * - #IOT_MQTT_SUCCESS + * - #IOT_MQTT_BAD_PARAMETER + * - #IOT_MQTT_NO_MEMORY + * - #IOT_MQTT_NETWORK_ERROR + * - #IOT_MQTT_SCHEDULING_ERROR + * - #IOT_MQTT_BAD_RESPONSE + * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs) + * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set). + */ +/* @[declare_mqtt_timedpublish] */ +IotMqttError_t IotMqtt_TimedPublish( IotMqttConnection_t mqttConnection, + const IotMqttPublishInfo_t * pPublishInfo, + uint32_t flags, + uint32_t timeoutMs ); +/* @[declare_mqtt_timedpublish] */ + +/** + * @brief Waits for an operation to complete. + * + * This function blocks to wait for a [subscribe](@ref mqtt_function_subscribe), + * [unsubscribe](@ref mqtt_function_unsubscribe), or [publish] + * (@ref mqtt_function_publish) to complete. These operations are by default + * asynchronous; the function calls queue an operation for processing, and a + * callback is invoked once the operation is complete. + * + * To use this function, the flag #IOT_MQTT_FLAG_WAITABLE must have been + * set in the operation's function call. Additionally, this function must always + * be called with any waitable operation to clean up resources. + * + * Regardless of its return value, this function always clean up resources used + * by the waitable operation. This means `reference` is invalidated as soon as + * this function returns, even if it returns #IOT_MQTT_TIMEOUT or another error. + * + * @param[in] operation Reference to the operation to wait for. The flag + * #IOT_MQTT_FLAG_WAITABLE must have been set for this operation. + * @param[in] timeoutMs How long to wait before returning #IOT_MQTT_TIMEOUT. + * + * @return The return value of this function depends on the MQTT operation associated + * with `reference`. See #IotMqttError_t for possible return values. + * + * Example + * @code{c} + * // Operation reference and timeout. + * IotMqttOperation_t publishOperation = IOT_MQTT_OPERATION_INITIALIZER; + * uint32_t timeoutMs = 5000; // 5 seconds + * + * // MQTT operation to wait for. + * IotMqttError_t result = IotMqtt_Publish( mqttConnection, + * &publishInfo, + * IOT_MQTT_FLAG_WAITABLE, + * NULL, + * &publishOperation ); + * + * // Publish should have returned IOT_MQTT_STATUS_PENDING. The call to wait + * // returns once the result of the publish is available or the timeout expires. + * if( result == IOT_MQTT_STATUS_PENDING ) + * { + * result = IotMqtt_Wait( publishOperation, timeoutMs ); + * + * // After the call to wait, the result of the publish is known + * // (not IOT_MQTT_STATUS_PENDING). + * assert( result != IOT_MQTT_STATUS_PENDING ); + * } + * @endcode + */ +/* @[declare_mqtt_wait] */ +IotMqttError_t IotMqtt_Wait( IotMqttOperation_t operation, + uint32_t timeoutMs ); +/* @[declare_mqtt_wait] */ + +/*-------------------------- MQTT helper functions --------------------------*/ + +/** + * @brief Returns a string that describes an #IotMqttError_t. + * + * Like the POSIX's `strerror`, this function returns a string describing a + * return code. In this case, the return code is an MQTT library error code, + * `status`. + * + * The string returned by this function MUST be treated as read-only: any + * attempt to modify its contents may result in a crash. Therefore, this function + * is limited to usage in logging. + * + * @param[in] status The status to describe. + * + * @return A read-only string that describes `status`. + * + * @warning The string returned by this function must never be modified. + */ +/* @[declare_mqtt_strerror] */ +const char * IotMqtt_strerror( IotMqttError_t status ); +/* @[declare_mqtt_strerror] */ + +/** + * @brief Returns a string that describes an #IotMqttOperationType_t. + * + * This function returns a string describing an MQTT operation type, `operation`. + * + * The string returned by this function MUST be treated as read-only: any + * attempt to modify its contents may result in a crash. Therefore, this function + * is limited to usage in logging. + * + * @param[in] operation The operation to describe. + * + * @return A read-only string that describes `operation`. + * + * @warning The string returned by this function must never be modified. + */ +/* @[declare_mqtt_operationtype] */ +const char * IotMqtt_OperationType( IotMqttOperationType_t operation ); +/* @[declare_mqtt_operationtype] */ + +/** + * @brief Check if an MQTT connection has a subscription for a topic filter. + * + * This function checks whether an MQTT connection `mqttConnection` has a + * subscription callback registered for a topic filter `pTopicFilter`. If a + * subscription callback is found, its details are copied into the output parameter + * `pCurrentSubscription`. This subscription callback will be invoked for incoming + * PUBLISH messages on `pTopicFilter`. + * + * The check for a matching subscription is only performed client-side; + * therefore, this function should not be relied upon for perfect accuracy. For + * example, this function may return an incorrect result if the MQTT server + * crashes and drops subscriptions without informing the client. + * + * Note that an MQTT connection's subscriptions might change between the time this + * function checks the subscription list and its caller tests the return value. + * This function certainly should not be used concurrently with any pending SUBSCRIBE + * or UNSUBSCRIBE operations. + * + * One suitable use of this function is to check which subscriptions were rejected + * if @ref mqtt_function_subscribe returns #IOT_MQTT_SERVER_REFUSED; that return + * code only means that at least one subscription was rejected. + * + * @param[in] mqttConnection The MQTT connection to check. + * @param[in] pTopicFilter The topic filter to check. + * @param[in] topicFilterLength Length of `pTopicFilter`. + * @param[out] pCurrentSubscription If a subscription is found, its details are + * copied here. This output parameter is only valid if this function returns `true`. + * Pass `NULL` to ignore. + * + * @return `true` if a subscription was found; `false` otherwise. + * + * @note The subscription QoS is not stored by the MQTT library; therefore, + * `pCurrentSubscription->qos` will always be set to #IOT_MQTT_QOS_0. + */ +/* @[declare_mqtt_issubscribed] */ +bool IotMqtt_IsSubscribed( IotMqttConnection_t mqttConnection, + const char * pTopicFilter, + uint16_t topicFilterLength, + IotMqttSubscription_t * pCurrentSubscription ); +/* @[declare_mqtt_issubscribed] */ + +#endif /* ifndef IOT_MQTT_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent.h b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent.h new file mode 100644 index 0000000..8b5b6da --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent.h @@ -0,0 +1,358 @@ +/* + * FreeRTOS MQTT V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt_agent.h + * @brief MQTT Agent Interface. + */ + +#ifndef _AWS_MQTT_AGENT_H_ +#define _AWS_MQTT_AGENT_H_ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" + +/* MQTT lib includes. */ +#include "iot_mqtt_lib.h" + +/* Library initialization definition include */ +#include "iot_lib_init.h" + +/** + * @brief Opaque handle to represent an MQTT client. + * + * The MQTT library is capable of creating multiple MQTT clients, maximum number of which + * is controlled by mqttconfigMAX_BROKERS macro. Each client is identified by an opaque + * handle which is returned by the MQTT_AGENT_Create API call and later used in all + * the subsequent API calls. + */ +typedef void * MQTTAgentHandle_t; + +/** + * @brief Return codes. + * + * Each API returns a value of this type. + */ +typedef enum +{ + eMQTTAgentSuccess, /**< The operation was successful. */ + eMQTTAgentFailure, /**< The operation failed. */ + eMQTTAgentTimeout, /**< The operation timed out. */ + eMQTTAgentAPICalledFromCallback /**< The MQTT agent APIs must not be called from MQTT callbacks as callbacks run + * in the context of MQTT agent task and therefore can result in deadlock. This + * error code is returned if any MQTT agent API is invoked from any callback. */ +} MQTTAgentReturnCode_t; + +/** + * @brief Various events reported by the library in the callback. + * + * The user can register an optional callback with the MQTT library to + * get notified of various events including Publish messages received + * from the broker. This enum identifies the event received in the + * callback. + */ +typedef enum +{ + eMQTTAgentPublish, /**< A Publish message was received from the broker. */ + eMQTTAgentDisconnect /**< The connection to the broker got disconnected. */ +} MQTTAgentEvent_t; + +/** + * @brief Passed by the library in the callback to inform the user of various events. + * + * If the user has registered a callback to get notified of various events, a pointer + * to this structure is passed in the callback function. + * @see MQTTAgentEvent_t. + */ +typedef struct MQTTAgentCallbackParams +{ + MQTTAgentEvent_t xMQTTEvent; /**< Type of the event received. */ + /* This union is here for future support. */ + union + { + MQTTPublishData_t xPublishData; /**< Publish data. Meaningful only in case of eMQTTAgentPublish event. */ + } u; +} MQTTAgentCallbackParams_t; + +/** + * @brief Signature of the callback registered by the user to get notified of various events. + * + * The user can register an optional callback to get notified of various events. + * + * @param[in] pvUserData The user data as provided in the connect parameters while connecting. + * @param[in] pxCallbackParams The event and related data. + * + * @return The return value is ignored in all other cases except publish (i.e. eMQTTAgentPublish + * event): + * 1. If pdTRUE is returned - The ownership of the buffer passed in the callback (xBuffer + * in MQTTPublishData_t) lies with the user. + * 2. If pdFALSE is returned - The ownership of the buffer passed in the callback (xBuffer + * in MQTTPublishData_t) remains with the library and it is recycled as soon as + * the callback returns.
+ * The user should take the ownership of the buffer containing the received message from the + * broker by returning pdTRUE from the callback if the user wants to use the buffer after + * the callback is over. The user should return the buffer whenever done by calling the + * MQTT_AGENT_ReturnBuffer API. + * + * @see MQTTAgentCallbackParams_t. + */ +typedef BaseType_t ( * MQTTAgentCallback_t )( void * pvUserData, + const MQTTAgentCallbackParams_t * const pxCallbackParams ); + +/** + * @brief Flags for the MQTT agent connect params. + */ +#define mqttagentURL_IS_IP_ADDRESS 0x00000001 /**< Set this bit in xFlags if the provided URL is an IP address. */ +#define mqttagentREQUIRE_TLS 0x00000002 /**< Set this bit in xFlags to use TLS. */ +#define mqttagentUSE_AWS_IOT_ALPN_443 0x00000004 /**< Set this bit in xFlags to use AWS IoT support for MQTT over TLS port 443. */ + +/** + * @brief Parameters passed to the MQTT_AGENT_Connect API. + */ +typedef struct MQTTAgentConnectParams +{ + const char * pcURL; /**< The URL of the MQTT broker to connect to. */ + BaseType_t xFlags; /**< Flags to control the behavior of MQTT connect. */ + BaseType_t xURLIsIPAddress; /**< Deprecated. Set the mqttagentURL_IS_IP_ADDRESS bit in xFlags instead. */ + uint16_t usPort; /**< Port number at which MQTT broker is listening. This field is ignored if the mqttagentUSE_AWS_IOT_ALPN_443 flag is set. */ + const uint8_t * pucClientId; /**< Client Identifier of the MQTT client. It should be unique per broker. */ + uint16_t usClientIdLength; /**< The length of the client Id. */ + BaseType_t xSecuredConnection; /**< Deprecated. Set the mqttagentREQUIRE_TLS bit in xFlags instead. */ + void * pvUserData; /**< User data supplied back as it is in the callback. Can be NULL. */ + MQTTAgentCallback_t pxCallback; /**< Callback used to report various events. In addition to other events, this callback is invoked for the publish + * messages received on the topics for which the user has not registered any subscription callback. Can be NULL. */ + char * pcCertificate; /**< Certificate used for secure connection. Can be NULL. If it is NULL, the one specified in the aws_credential_keys.h is used. */ + uint32_t ulCertificateSize; /**< Size of certificate used for secure connection. */ +} MQTTAgentConnectParams_t; + +/** + * @brief Parameters passed to the MQTT_AGENT_Subscribe API. + */ +typedef struct MQTTAgentSubscribeParams +{ + const uint8_t * pucTopic; /**< The topic to subscribe to. This can be a topic filter containing wild cards as permitted by the MQTT protocol. */ + uint16_t usTopicLength; /**< The length of the topic. */ + MQTTQoS_t xQoS; /**< Requested Quality of Service. */ + #if ( mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT == 1 ) + void * pvPublishCallbackContext; /**< Passed as it is in the publish callback. Can be NULL. */ + MQTTPublishCallback_t pxPublishCallback; /**< Callback function to be called whenever a publish message is received on this topic or on a topic which matches this + * topic filter. If a publish message is received on a topic which matches more than one topic filters, the order in which + * the callbacks are invoked is undefined. This can be NULL if the user does not want to register a topic specific callback, + * in which case the generic callback ( if registered during connect ) is invoked. */ + #endif /* mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT */ +} MQTTAgentSubscribeParams_t; + +/** + * @brief Parameters passed to the MQTT_AGENT_Unsubscribe API. + */ +typedef struct MQTTAgentUnsubscribeParams +{ + const uint8_t * pucTopic; /**< The topic to unsubscribe from. */ + uint16_t usTopicLength; /**< The length of the topic. */ +} MQTTAgentUnsubscribeParams_t; + +/** + * @brief Parameters passed to the MQTT_AGENT_Publish API. + */ +typedef struct MQTTAgentPublishParams +{ + const uint8_t * pucTopic; /**< The topic string on which the message should be published. */ + uint16_t usTopicLength; /**< The length of the topic. */ + MQTTQoS_t xQoS; /**< Quality of Service (qos). */ + const void * pvData; /**< The data to publish. This data is copied into the MQTT buffers and therefore the user can free the buffer after the MQTT_AGENT_Publish call returns. */ + uint32_t ulDataLength; /**< Length of the data. */ +} MQTTAgentPublishParams_t; + +/** + * @brief MQTT library Init function. + * + * This function does general initialization and setup. It must be called once + * and only once before calling any other function. + * + * @return pdPASS if everything succeeds, pdFAIL otherwise. + */ +lib_initDECLARE_LIB_INIT( MQTT_AGENT_Init ); + +/** + * @brief Creates a new MQTT client. + * + * The MQTT library is capable of creating multiple MQTT clients, maximum number of which + * is controlled by mqttconfigMAX_BROKERS macro. If mqttconfigMAX_BROKERS clients are already + * in use, this function will fail immediately. Otherwise a new client is setup and the handle + * to the created client is returned in the pxMQTTHandle parameter which should be used in all + * the subsequent API calls. Note that the returned handled is only valid if the return value + * of the API is eMQTTAgentSuccess. + * + * @param[out] pxMQTTHandle Output parameter to return the opaque client handle. + * + * @return eMQTTAgentSuccess if a new client is successfully created, otherwise an error code + * explaining the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Create( MQTTAgentHandle_t * const pxMQTTHandle ); + +/** + * @brief Deletes the already created MQTT client. + * + * This function just frees up the internal resources and does not disconnect. The user must + * call MQTT_AGENT_Disconnect API to make sure that the client is disconnected before + * deleting it. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * + * @return eMQTTAgentSuccess if the client is successfully deleted, otherwise an + * error code explaining the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Delete( MQTTAgentHandle_t xMQTTHandle ); + +/** + * @brief Establishes a connection with the MQTT broker. + * + * @note This function alters the calling task's notification state and value. If xTimeoutTicks + * is short the calling task's notification state and value may be updated after MQTT_AGENT_Connect() + * has returned. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * @param[in] pxConnectParams Connect parameters. + * @param[in] xTimeoutTicks Maximum time in ticks after which the operation should fail. Use pdMS_TO_TICKS + * macro to convert milliseconds to ticks. + * + * @return eMQTTAgentSuccess if the connect operation succeeds, otherwise an error code explaining the + * reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Connect( MQTTAgentHandle_t xMQTTHandle, + const MQTTAgentConnectParams_t * const pxConnectParams, + TickType_t xTimeoutTicks ); + +/** + * @brief Disconnects the connection with the MQTT broker. + * + * @note This function alters the calling task's notification state and value. If xTimeoutTicks + * is short the calling task's notification state and value may be updated after MQTT_AGENT_Disconnect() + * has returned. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * @param[in] xTimeoutTicks Maximum time in ticks after which the operation should fail. Use pdMS_TO_TICKS + * macro to convert milliseconds to ticks. + * + * @return eMQTTAgentSuccess if the disconnect operation succeeds, otherwise an error code explaining + * the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Disconnect( MQTTAgentHandle_t xMQTTHandle, + TickType_t xTimeoutTicks ); + +/** + * @brief Subscribes to a given topic. + * + * @note This function alters the calling task's notification state and value. If xTimeoutTicks + * is short the calling task's notification state and value may be updated after MQTT_AGENT_Subscribe() + * has returned. + * + * Whenever a publish message is received on a topic, the registered callbacks are invoked + * in the following order: + * * If we have an exact matching entry in the subscription manager, the corresponding + * callback is invoked. + * * Then the wild card topic filters are checked for match and the corresponding callbacks + * are invoked for the ones which match the topic. + * + * @note If a publish message is received on a topic which matches more than one topic + * filters, the order in which the registered callbacks are invoked is undefined. + * + * @warning If the user takes the ownership of the MQTT buffer by returning eMQTTTrue from the + * callback, no further callbacks are invoked. The user should make sure not to take the ownership + * of the MQTT buffer if they want all the callbacks to get invoked. For example: + * * Subscriptions: a/b/c, a/b/#, a/b/+ + * * Publish message received on topic: a/b/c --> First the callback corresponding to a/b/c + * subscription is invoked. Then the callbacks for topic filters a/b/# and a/b/+ are invoked + * in no particular order. If the user decides to take the ownership of the MQTT buffer in + * any of the callback by returning eMQTTTrue, no further callbacks are invoked. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * @param[in] pxSubscribeParams Subscribe parameters. + * @param[in] xTimeoutTicks Maximum time in ticks after which the operation should fail. Use pdMS_TO_TICKS + * macro to convert milliseconds to ticks. + * + * @return eMQTTAgentSuccess if the subscribe operation succeeds, otherwise an error code explaining + * the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Subscribe( MQTTAgentHandle_t xMQTTHandle, + const MQTTAgentSubscribeParams_t * const pxSubscribeParams, + TickType_t xTimeoutTicks ); + +/** + * @brief Unsubscribes from a given topic. + * + * @note This function alters the calling task's notification state and value. If xTimeoutTicks + * is short the calling task's notification state and value may be updated after MQTT_AGENT_Unsubscribe() + * has returned. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * @param[in] pxUnsubscribeParams Unsubscribe parameters. + * @param[in] xTimeoutTicks Maximum time in ticks after which the operation should fail. Use pdMS_TO_TICKS + * macro to convert milliseconds to ticks. + * + * @return eMQTTAgentSuccess if the unsubscribe operation succeeds, otherwise an error code explaining + * the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Unsubscribe( MQTTAgentHandle_t xMQTTHandle, + const MQTTAgentUnsubscribeParams_t * const pxUnsubscribeParams, + TickType_t xTimeoutTicks ); + +/** + * @brief Publishes a message to a given topic. + * + * @note This function alters the calling task's notification state and value. If xTimeoutTicks + * is short the calling task's notification state and value may be updated after MQTT_AGENT_Publish() + * has returned. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * @param[in] pxPublishParams Publish parameters. + * @param[in] xTimeoutTicks Maximum time in ticks after which the operation should fail. Use pdMS_TO_TICKS + * macro to convert milliseconds to ticks. + * + * @return eMQTTAgentSuccess if the publish operation succeeds, otherwise an error code explaining + * the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_Publish( MQTTAgentHandle_t xMQTTHandle, + const MQTTAgentPublishParams_t * const pxPublishParams, + TickType_t xTimeoutTicks ); + +/** + * @brief Returns the buffer provided in the publish callback. + * + * When a publish message is received from the broker, the buffer containing the message + * is returned in the user supplied callback (xBuffer in MQTTPublishData_t) and the user + * can take the ownership by returning pdTRUE from the callback. The user should later + * return the buffer whenever done by calling the MQTT_AGENT_ReturnBuffer API. + * + * @param[in] xMQTTHandle The opaque handle as returned from MQTT_AGENT_Create. + * @param[in] xBufferHandle The buffer to return. + * + * @return eMQTTAgentSuccess if the return buffer operation succeeds, otherwise an error + * code explaining the reason of the failure is returned. + */ +MQTTAgentReturnCode_t MQTT_AGENT_ReturnBuffer( MQTTAgentHandle_t xMQTTHandle, + MQTTBufferHandle_t xBufferHandle ); + +#endif /* _AWS_MQTT_AGENT_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent_config_defaults.h b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent_config_defaults.h new file mode 100644 index 0000000..d0ab25e --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_agent_config_defaults.h @@ -0,0 +1,180 @@ +/* + * FreeRTOS MQTT V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt_agent_config_defaults.h + * @brief MQTT agent default config options. + * + * Ensures that the config options for MQTT agent are set to sensible + * default values if the user does not provide one. + */ + +#ifndef _AWS_MQTT_AGENT_CONFIG_DEFAULTS_H_ +#define _AWS_MQTT_AGENT_CONFIG_DEFAULTS_H_ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/** + * @brief Controls whether or not to report usage metrics to the + * AWS IoT broker. + * + * If mqttconfigENABLE_METRICS is set to 1, a string containing + * metric information will be included in the "username" field of + * the MQTT connect messages. + */ +#ifndef mqttconfigENABLE_METRICS + #define mqttconfigENABLE_METRICS ( 1 ) +#endif + +/** + * @brief The maximum time interval in seconds allowed to elapse between 2 consecutive + * control packets. + */ +#ifndef mqttconfigKEEP_ALIVE_INTERVAL_SECONDS + #define mqttconfigKEEP_ALIVE_INTERVAL_SECONDS ( 1200 ) +#endif + +/** + * @brief Defines the frequency at which the client should send Keep Alive messages. + * + * Even though the maximum time allowed between 2 consecutive control packets + * is defined by the mqttconfigKEEP_ALIVE_INTERVAL_SECONDS macro, the user + * can and should send Keep Alive messages at a slightly faster rate to ensure + * that the connection is not closed by the server because of network delays. + * This macro defines the interval of inactivity after which a keep alive messages + * is sent. + */ +#ifndef mqttconfigKEEP_ALIVE_ACTUAL_INTERVAL_TICKS + #define mqttconfigKEEP_ALIVE_ACTUAL_INTERVAL_TICKS ( 5000 ) +#endif + +/** + * @brief The maximum interval in ticks to wait for PINGRESP. + * + * If PINGRESP is not received within this much time after sending PINGREQ, + * the client assumes that the PINGREQ timed out. + */ +#ifndef mqttconfigKEEP_ALIVE_TIMEOUT_TICKS + #define mqttconfigKEEP_ALIVE_TIMEOUT_TICKS ( 1000 ) +#endif + +/** + * @brief The maximum time in ticks for which the MQTT task is permitted to block. + * + * The MQTT task blocks until the user initiates any action or until it receives + * any data from the broker. This macro controls the maximum time the MQTT task can + * block. It should be set to a small number for the platforms which do not have any + * mechanism to wake up the MQTT task whenever data is received on a connected socket. + * This ensures that the MQTT task keeps waking up frequently and processes the publish + * messages received from the broker, if any. + * + * If the platform's secure_sockets layer supports SOCKETS_SO_WAKEUP_CALLBACK i.e. + * the MQTT task can wake up whenever data is received on a connected socket, this + * value should be set to maximum value: + * #define #define mqttconfigMQTT_TASK_MAX_BLOCK_TICKS ( ~( ( uint32_t ) 0 ) ) + * + * If the platform's secure_sockets layer does not support SOCKETS_SO_WAKEUP_CALLBACK + * i.e. the MQTT task cannot wake up whenever data is received on a connected socket, + * this value should be set to a small number: + * #define mqttconfigMQTT_TASK_MAX_BLOCK_TICKS ( 100 ) + */ +#ifndef mqttconfigMQTT_TASK_MAX_BLOCK_TICKS + #error "mqttconfigMQTT_TASK_MAX_BLOCK_TICKS must be defined in iot_mqtt_agent_config.h." +#endif + +/** + * @defgroup MQTTTask MQTT task configuration parameters. + */ +/** @{ */ +#ifndef mqttconfigMQTT_TASK_STACK_DEPTH + #define mqttconfigMQTT_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 4 ) +#endif + +#ifndef mqttconfigMQTT_TASK_PRIORITY + #define mqttconfigMQTT_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#endif +/** @} */ + +/** + * @brief Maximum number of MQTT clients that can exist simultaneously. + */ +#ifndef mqttconfigMAX_BROKERS + #define mqttconfigMAX_BROKERS ( 1 ) +#endif + +/** + * @brief Maximum number of parallel operations per client. + */ +#ifndef mqttconfigMAX_PARALLEL_OPS + #define mqttconfigMAX_PARALLEL_OPS ( 5 ) +#endif + +/** + * @brief Time in milliseconds after which the TCP send operation should timeout. + */ +#ifndef mqttconfigTCP_SEND_TIMEOUT_MS + #define mqttconfigTCP_SEND_TIMEOUT_MS ( 2000 ) +#endif + +/** + * @brief Length of the buffer used to receive data. + */ +#ifndef mqttconfigRX_BUFFER_SIZE + #define mqttconfigRX_BUFFER_SIZE ( 1024 ) +#endif + +/** + * @defgroup BufferPoolInterface The functions used by the MQTT client to get and return buffers. + * + * The MQTT client needs buffers for both transmitting and receiving messages. + * Whenever it needs a buffer, it invokes mqttconfigGET_FREE_BUFFER_FXN function to get + * a buffer and after it is done it invokes mqttconfigRETURN_BUFFER_FXN to return the + * buffer. By default, BUFFERPOOL_GetFreeBuffer and BUFFERPOOL_ReturnBuffer functions are + * used to get and return buffers from the central buffer pool. The user can change the + * buffer management functions for MQTT client by defining mqttconfigGET_FREE_BUFFER_FXN + * and mqttconfigRETURN_BUFFER_FXN macros. The user should implement the two functions + * having signatures same as BUFFERPOOL_GetFreeBuffer and BUFFERPOOL_ReturnBuffer and then + * define the macros in BufferPoolConfig.h: + * @code + * uint8_t* UserDefined_GetFreeBuffer( uint32_t *pulBufferLength ); + * void UserDefined_ReturnBuffer( uint8_t * const pucBuffer ); + * + * #define mqttconfigGET_FREE_BUFFER_FXN UserDefined_GetFreeBuffer + * #define mqttconfigRETURN_BUFFER_FXN UserDefined_ReturnBuffer + * @endcode + */ +/** @{ */ +#ifndef mqttconfigGET_FREE_BUFFER_FXN + #define mqttconfigGET_FREE_BUFFER_FXN BUFFERPOOL_GetFreeBuffer +#endif + +#ifndef mqttconfigRETURN_BUFFER_FXN + #define mqttconfigRETURN_BUFFER_FXN BUFFERPOOL_ReturnBuffer +#endif +/** @} */ + +#endif /* _AWS_MQTT_AGENT_CONFIG_DEFAULTS_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_config_defaults.h b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_config_defaults.h new file mode 100644 index 0000000..17ccc57 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_config_defaults.h @@ -0,0 +1,115 @@ +/* + * FreeRTOS MQTT V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt_config_defaults.h + * @brief MQTT default config options. + * + * Ensures that the config options for MQTT are set to sensible default + * values if the user does not provide one. + */ + +#ifndef _AWS_MQTT_CONFIG_DEFAULTS_H_ +#define _AWS_MQTT_CONFIG_DEFAULTS_H_ + +/** + * @brief Enable subscription management. + * + * Subscription management allows the user to register per subscription + * callback. + */ +#ifndef mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT + #define mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT ( 1 ) +#endif + +/** + * @brief Maximum length of the topic which can be stored in subscription + * manager. + * + * If the user has enabled subscription management (by defining the macro + * mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT to 1), then this macro must be defined + * to accommodate the maximum length topic which the user is going to subscribe. + * The subscribe operation will fail if the user tries to subscribe to a topic + * of length more than the maximum specified here. + */ +#ifndef mqttconfigSUBSCRIPTION_MANAGER_MAX_TOPIC_LENGTH + #define mqttconfigSUBSCRIPTION_MANAGER_MAX_TOPIC_LENGTH ( 128 ) +#endif + +/** + * @brief Maximum number of subscriptions which can be stored in subscription + * manager. + * + * If the user has enabled subscription management (by defining the macro + * mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT to 1), then this macro must be defined + * to the maximum number of topics which the user is going to subscribe + * simultaneously. The subscribe operation will fail is the user tries to + * subscribe to more topics than the maximum specified here. + */ +#ifndef mqttconfigSUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS + #define mqttconfigSUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS ( 8 ) +#endif + +/** + * @brief Define mqttconfigASSERT to enable asserts. + * + * mqttconfigASSERT should be defined to match the semantics of standard + * C assert() macro i.e. an assertion should trigger if the parameter + * passed is zero. If the standard C assert is available, the user might + * do the following: + * @code + * #define mqttconfigASSERT( x ) assert( x ) + * @endcode + * + * Otherwise, a user can choose to implement a function which should be + * called when an assertion triggers and then define the mqttconfigASSERT + * to that function: + * @code + * extern void vAssertCalled( const char *pcFile, uint32_t ulLine ); + * #define mqttconfigASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ) + * @endcode + */ +#ifndef mqttconfigASSERT + #define mqttconfigASSERT( x ) +#endif + +/** + * @brief Define mqttconfigENABLE_DEBUG_LOGS macro to 1 for enabling debug logs. + * + * If you choose to enable debug logs, the following function must be implemented + * which is called to print logs: + * @code + * void vLoggingPrintf( const char *pcFormatString, ... ); + * @endcode + */ +#if ( mqttconfigENABLE_DEBUG_LOGS == 1 ) + extern void vLoggingPrintf( const char * pcFormatString, + ... ); + #define mqttconfigDEBUG_LOG( x ) vLoggingPrintf x +#else + #define mqttconfigDEBUG_LOG( x ) +#endif + +#endif /* _AWS_MQTT_CONFIG_DEFAULTS_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_lib.h b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_lib.h new file mode 100644 index 0000000..85017b9 --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/mqtt/include/iot_mqtt_lib.h @@ -0,0 +1,113 @@ +/* + * FreeRTOS MQTT V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt_lib.h + * @brief MQTT Core Library interface. + */ + +#ifndef _AWS_MQTT_LIB_H_ +#define _AWS_MQTT_LIB_H_ + +/* This ifndef enables the core MQTT library to be used without + * providing MQTTConfig.h. All the config values in this case are + * taken from MQTTConfigDefaults.h. */ +#ifndef mqttDO_NOT_USE_CUSTOM_CONFIG + #include "iot_mqtt_config.h" +#endif +#include "iot_mqtt_config_defaults.h" + +#include "iot_doubly_linked_list.h" + +/** + * @brief Opaque handle to represent an MQTT buffer. + */ +typedef void * MQTTBufferHandle_t; + +/** + * @brief Boolean type. + */ +typedef enum +{ + eMQTTFalse = 0, /**< Boolean False. */ + eMQTTTrue = 1 /**< Boolean True. */ +} MQTTBool_t; + +/** + * @brief Quality of Service (qos). + */ +typedef enum +{ + eMQTTQoS0 = 0, /**< Quality of Service 0 - Fire and Forget. No ACK. */ + eMQTTQoS1 = 1, /**< Quality of Service 1 - Wait till ACK or Timeout. */ + eMQTTQoS2 = 2 /**< Quality of Service 2 - Not supported. */ +} MQTTQoS_t; + +/** + * @brief The data sent by the MQTT library in the user supplied callback + * when a publish message from the broker is received. + */ +typedef struct MQTTPublishData +{ + MQTTQoS_t xQos; /**< Quality of Service (qos). */ + const uint8_t * pucTopic; /**< The topic on which the message is received. */ + uint16_t usTopicLength; /**< Length of the topic. */ + const void * pvData; /**< The received message. */ + uint32_t ulDataLength; /**< Length of the message. */ + MQTTBufferHandle_t xBuffer; /**< The buffer containing the whole MQTT message. Both pcTopic and pvData are pointers to the locations in this buffer. */ +} MQTTPublishData_t; + +/** + * @brief Signature of the user supplied topic specific publish callback which gets called + * whenever a publish message is received on the topic this callback is registered for. + * + * The user can choose to register this optional topic specific callback while subscribing to + * a topic. Whenever a publish message is received on the topic, this callback is invoked. If + * the user chooses not to enable subscription management or chooses not to register a topic + * specific callback, the generic callback supplied during Init is invoked. + * + * @param[in] pvPublishCallbackContext The callback context as supplied by the user in the + * subscribe parameters. + * @param[in] pxPublishData The publish data. + * + * @return The return value is interpreted as follows: + * 1. If eMQTTTrue is returned - the ownership of the buffer passed in the callback (xBuffer + * in MQTTPublishData_t) lies with the user. + * 2. If eMQTTFalse is returned - the ownership of the buffer passed in the callback (xBuffer + * in MQTTPublishData_t) remains with the library and it is recycled as soon as the callback + * returns.
+ * The user should take the ownership of the buffer containing the received message from the + * broker by returning eMQTTTrue from the callback if the user wants to use the buffer after + * the callback is over. The user should return the buffer whenever done by calling the + * MQTT_ReturnBuffer API. + */ +#if ( mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT == 1 ) + + typedef MQTTBool_t ( * MQTTPublishCallback_t )( void * pvPublishCallbackContext, + const MQTTPublishData_t * const pxPublishData ); + +#endif /* mqttconfigENABLE_SUBSCRIPTION_MANAGEMENT */ + +#endif /* _AWS_MQTT_LIB_H_ */ diff --git a/bsp/aws_libraries/c_sdk/standard/mqtt/include/types/iot_mqtt_types.h b/bsp/aws_libraries/c_sdk/standard/mqtt/include/types/iot_mqtt_types.h new file mode 100644 index 0000000..bd7ca6a --- /dev/null +++ b/bsp/aws_libraries/c_sdk/standard/mqtt/include/types/iot_mqtt_types.h @@ -0,0 +1,1091 @@ +/* + * FreeRTOS MQTT V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_mqtt_types.h + * @brief Types of the MQTT library. + */ + +#ifndef IOT_MQTT_TYPES_H_ +#define IOT_MQTT_TYPES_H_ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include + +/* Type includes. */ +#include "types/iot_platform_types.h" +#include "types/iot_taskpool_types.h" + +/* Platform network include. */ +#include "platform/iot_network.h" + +/*---------------------------- MQTT handle types ----------------------------*/ + +/** + * @handles_group{mqtt} + * @handles_brief{MQTT library} + */ + +/** + * @ingroup mqtt_datatypes_handles + * @brief Opaque handle of an MQTT connection. + * + * This type identifies an MQTT connection, which is valid after a successful call + * to @ref mqtt_function_connect. A variable of this type is passed as the first + * argument to [MQTT library functions](@ref mqtt_functions) to identify which + * connection that function acts on. + * + * A call to @ref mqtt_function_disconnect makes a connection handle invalid. Once + * @ref mqtt_function_disconnect returns, the connection handle should no longer + * be used. + * + * @initializer{IotMqttConnection_t,IOT_MQTT_CONNECTION_INITIALIZER} + */ +typedef struct _mqttConnection * IotMqttConnection_t; + +/** + * @ingroup mqtt_datatypes_handles + * @brief Opaque handle that references an in-progress MQTT operation. + * + * Set as an output parameter of @ref mqtt_function_publish, @ref mqtt_function_subscribe, + * and @ref mqtt_function_unsubscribe. These functions queue an MQTT operation; the result + * of the operation is unknown until a response from the MQTT server is received. Therefore, + * this handle serves as a reference to MQTT operations awaiting MQTT server response. + * + * This reference will be valid from the successful return of @ref mqtt_function_publish, + * @ref mqtt_function_subscribe, or @ref mqtt_function_unsubscribe. The reference becomes + * invalid once the [completion callback](@ref IotMqttCallbackInfo_t) is invoked, or + * @ref mqtt_function_wait returns. + * + * @initializer{IotMqttOperation_t,IOT_MQTT_OPERATION_INITIALIZER} + * + * @see @ref mqtt_function_wait and #IOT_MQTT_FLAG_WAITABLE for waiting on a reference. + * #IotMqttCallbackInfo_t and #IotMqttCallbackParam_t for an asynchronous notification + * of completion. + */ +typedef struct _mqttOperation * IotMqttOperation_t; + +/*-------------------------- MQTT enumerated types --------------------------*/ + +/** + * @enums_group{mqtt} + * @enums_brief{MQTT library} + */ + +/** + * @ingroup mqtt_datatypes_enums + * @brief Return codes of [MQTT functions](@ref mqtt_functions). + * + * The function @ref mqtt_function_strerror can be used to get a return code's + * description. + */ +typedef enum IotMqttError +{ + /** + * @brief MQTT operation completed successfully. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_publish with QoS 0 parameter + * - @ref mqtt_function_wait + * - @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_timedpublish + * + * Will also be the value of an operation completion callback's + * #IotMqttCallbackParam_t.result when successful. + */ + IOT_MQTT_SUCCESS = 0, + + /** + * @brief MQTT operation queued, awaiting result. + * + * Functions that may return this value: + * - @ref mqtt_function_subscribe + * - @ref mqtt_function_unsubscribe + * - @ref mqtt_function_publish with QoS 1 parameter + */ + IOT_MQTT_STATUS_PENDING, + + /** + * @brief Initialization failed. + * + * Functions that may return this value: + * - @ref mqtt_function_init + */ + IOT_MQTT_INIT_FAILED, + + /** + * @brief At least one parameter is invalid. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_subscribe and @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_unsubscribe and @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_publish and @ref mqtt_function_timedpublish + * - @ref mqtt_function_wait + */ + IOT_MQTT_BAD_PARAMETER, + + /** + * @brief MQTT operation failed because of memory allocation failure. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_subscribe and @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_unsubscribe and @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_publish and @ref mqtt_function_timedpublish + */ + IOT_MQTT_NO_MEMORY, + + /** + * @brief MQTT operation failed because the network was unusable. + * + * This return value may indicate that the network is disconnected. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_wait + * - @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_timedpublish + * + * May also be the value of an operation completion callback's + * #IotMqttCallbackParam_t.result. + */ + IOT_MQTT_NETWORK_ERROR, + + /** + * @brief MQTT operation could not be scheduled, i.e. enqueued for sending. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_subscribe and @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_unsubscribe and @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_publish and @ref mqtt_function_timedpublish + */ + IOT_MQTT_SCHEDULING_ERROR, + + /** + * @brief MQTT response packet received from the network is malformed. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_wait + * - @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_timedpublish + * + * May also be the value of an operation completion callback's + * #IotMqttCallbackParam_t.result. + * + * @note If this value is received, the network connection has been closed. + */ + IOT_MQTT_BAD_RESPONSE, + + /** + * @brief A blocking MQTT operation timed out. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_wait + * - @ref mqtt_function_timedsubscribe + * - @ref mqtt_function_timedunsubscribe + * - @ref mqtt_function_timedpublish + */ + IOT_MQTT_TIMEOUT, + + /** + * @brief A CONNECT or at least one subscription was refused by the server. + * + * Functions that may return this value: + * - @ref mqtt_function_connect + * - @ref mqtt_function_wait, but only when its #IotMqttOperation_t parameter + * is associated with a SUBSCRIBE operation. + * - @ref mqtt_function_timedsubscribe + * + * May also be the value of an operation completion callback's + * #IotMqttCallbackParam_t.result for a SUBSCRIBE. + * + * @note If this value is returned and multiple subscriptions were passed to + * @ref mqtt_function_subscribe (or @ref mqtt_function_timedsubscribe), it's + * still possible that some of the subscriptions succeeded. This value only + * signifies that AT LEAST ONE subscription was rejected. The function @ref + * mqtt_function_issubscribed can be used to determine which subscriptions + * were accepted or rejected. + */ + IOT_MQTT_SERVER_REFUSED, + + /** + * @brief A QoS 1 PUBLISH received no response and [the retry limit] + * (#IotMqttPublishInfo_t.retryLimit) was reached. + * + * Functions that may return this value: + * - @ref mqtt_function_wait, but only when its #IotMqttOperation_t parameter + * is associated with a QoS 1 PUBLISH operation + * - @ref mqtt_function_timedpublish + * + * May also be the value of an operation completion callback's + * #IotMqttCallbackParam_t.result for a QoS 1 PUBLISH. + */ + IOT_MQTT_RETRY_NO_RESPONSE +} IotMqttError_t; + +/** + * @ingroup mqtt_datatypes_enums + * @brief Types of MQTT operations. + * + * The function @ref mqtt_function_operationtype can be used to get an operation + * type's description. + */ +typedef enum IotMqttOperationType +{ + IOT_MQTT_CONNECT, /**< Client-to-server CONNECT. */ + IOT_MQTT_PUBLISH_TO_SERVER, /**< Client-to-server PUBLISH. */ + IOT_MQTT_PUBACK, /**< Client-to-server PUBACK. */ + IOT_MQTT_SUBSCRIBE, /**< Client-to-server SUBSCRIBE. */ + IOT_MQTT_UNSUBSCRIBE, /**< Client-to-server UNSUBSCRIBE. */ + IOT_MQTT_PINGREQ, /**< Client-to-server PINGREQ. */ + IOT_MQTT_DISCONNECT /**< Client-to-server DISCONNECT. */ +} IotMqttOperationType_t; + +/** + * @ingroup mqtt_datatypes_enums + * @brief Quality of service levels for MQTT PUBLISH messages. + * + * All MQTT PUBLISH messages, including Last Will and Testament and messages + * received on subscription filters, have an associated Quality of Service, + * which defines any delivery guarantees for that message. + * - QoS 0 messages will be delivered at most once. This is a "best effort" + * transmission with no retransmissions. + * - QoS 1 messages will be delivered at least once. See #IotMqttPublishInfo_t + * for the retransmission strategy this library uses to redeliver messages + * assumed to be lost. + * + * @attention QoS 2 is not supported by this library and should not be used. + */ +typedef enum IotMqttQos +{ + IOT_MQTT_QOS_0 = 0, /**< Delivery at most once. */ + IOT_MQTT_QOS_1 = 1, /**< Delivery at least once. See #IotMqttPublishInfo_t for client-side retry strategy. */ + IOT_MQTT_QOS_2 = 2 /**< Delivery exactly once. Unsupported, but enumerated for completeness. */ +} IotMqttQos_t; + +/** + * @ingroup mqtt_datatypes_enums + * @brief The reason that an MQTT connection (and its associated network connection) + * was disconnected. + * + * When an MQTT connection is closed, its associated [disconnect callback] + * (@ref IotMqttNetworkInfo_t::disconnectCallback) will be invoked. This type + * is passed inside of an #IotMqttCallbackParam_t to provide a reason for the + * disconnect. + */ +typedef enum IotMqttDisconnectReason +{ + IOT_MQTT_DISCONNECT_CALLED, /**< @ref mqtt_function_disconnect was invoked. */ + IOT_MQTT_BAD_PACKET_RECEIVED, /**< An invalid packet was received from the network. */ + IOT_MQTT_KEEP_ALIVE_TIMEOUT /**< Keep-alive response was not received within @ref IOT_MQTT_RESPONSE_WAIT_MS. */ +} IotMqttDisconnectReason_t; + +/*------------------------- MQTT parameter structs --------------------------*/ + +/** + * @paramstructs_group{mqtt} + * @paramstructs_brief{mqtt,MQTT} + */ + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Information on a PUBLISH message. + * + * @paramfor @ref mqtt_function_connect, @ref mqtt_function_publish + * + * Passed to @ref mqtt_function_publish as the message to publish and @ref + * mqtt_function_connect as the Last Will and Testament (LWT) message. + * + * @initializer{IotMqttPublishInfo_t,IOT_MQTT_PUBLISH_INFO_INITIALIZER} + * + * #IotMqttPublishInfo_t.retryMs and #IotMqttPublishInfo_t.retryLimit are only + * relevant to QoS 1 PUBLISH messages. They are ignored for QoS 0 PUBLISH + * messages and LWT messages. These members control retransmissions of QoS 1 + * messages under the following rules: + * - Retransmission is disabled when #IotMqttPublishInfo_t.retryLimit is 0. + * After sending the PUBLISH, the library will wait indefinitely for a PUBACK. + * - If #IotMqttPublishInfo_t.retryLimit is greater than 0, then QoS 1 publishes + * that do not receive a PUBACK within #IotMqttPublishInfo_t.retryMs will be + * retransmitted, up to #IotMqttPublishInfo_t.retryLimit times. + * + * Retransmission follows a truncated exponential backoff strategy. The constant + * @ref IOT_MQTT_RETRY_MS_CEILING controls the maximum time between retransmissions. + * + * After #IotMqttPublishInfo_t.retryLimit retransmissions are sent, the MQTT + * library will wait @ref IOT_MQTT_RESPONSE_WAIT_MS before a final check + * for a PUBACK. If no PUBACK was received within this time, the QoS 1 PUBLISH + * fails with the code #IOT_MQTT_RETRY_NO_RESPONSE. + * + * @note The lengths of the strings in this struct should not include the NULL + * terminator. Strings in this struct do not need to be NULL-terminated. + * + * @note The AWS IoT MQTT server does not support the DUP bit. When + * [using this library with the AWS IoT MQTT server](@ref IotMqttConnectInfo_t.awsIotMqttMode), + * retransmissions will instead be sent with a new packet identifier in the PUBLISH + * packet. This is a nonstandard workaround. Note that this workaround has some + * flaws, including the following: + * - The previous packet identifier is forgotten, so if a PUBACK arrives for that + * packet identifier, it will be ignored. On an exceptionally busy network, this + * may cause excessive retransmissions when too many PUBACKS arrive after the + * PUBLISH packet identifier is changed. However, the exponential backoff + * retransmission strategy should mitigate this problem. + * - Log messages will be printed using the new packet identifier; the old packet + * identifier is not saved. + * + * Example + * + * Consider a situation where + * - @ref IOT_MQTT_RETRY_MS_CEILING is 60000 + * - #IotMqttPublishInfo_t.retryMs is 2000 + * - #IotMqttPublishInfo_t.retryLimit is 20 + * + * A PUBLISH message will be retransmitted at the following times after the initial + * transmission if no PUBACK is received: + * - 2000 ms (2000 ms after previous transmission) + * - 6000 ms (4000 ms after previous transmission) + * - 14000 ms (8000 ms after previous transmission) + * - 30000 ms (16000 ms after previous transmission) + * - 62000 ms (32000 ms after previous transmission) + * - 122000 ms, 182000 ms, 242000 ms... (every 60000 ms until 20 transmissions have been sent) + * + * After the 20th retransmission, the MQTT library will wait + * @ref IOT_MQTT_RESPONSE_WAIT_MS before checking a final time for a PUBACK. + */ +typedef struct IotMqttPublishInfo +{ + IotMqttQos_t qos; /**< @brief QoS of message. Must be 0 or 1. */ + bool retain; /**< @brief MQTT message retain flag. */ + + const char * pTopicName; /**< @brief Topic name of PUBLISH. */ + uint16_t topicNameLength; /**< @brief Length of #IotMqttPublishInfo_t.pTopicName. */ + + const void * pPayload; /**< @brief Payload of PUBLISH. */ + size_t payloadLength; /**< @brief Length of #IotMqttPublishInfo_t.pPayload. For LWT messages, this is limited to 65535. */ + + uint32_t retryMs; /**< @brief If no response is received within this time, the message is retransmitted. */ + uint32_t retryLimit; /**< @brief How many times to attempt retransmission. */ +} IotMqttPublishInfo_t; + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Parameter to an MQTT callback function. + * + * @paramfor MQTT callback functions + * + * The MQTT library passes this struct to registered callback whenever an + * operation completes, a message is received on a topic filter, or an MQTT + * connection is disconnected. + * + * The members of this struct are different based on the callback trigger. If the + * callback function was triggered for completed operation, the `operation` + * member is valid. Otherwise, if the callback was triggered because of a + * server-to-client PUBLISH, the `message` member is valid. Finally, if the callback + * was triggered because of a disconnect, the `disconnectReason` member is valid. + * + * For an incoming PUBLISH, the `message.pTopicFilter` parameter provides the + * subscription topic filter that matched the topic name in the PUBLISH. Because + * topic filters may use MQTT wildcards, the topic filter may be different from the + * topic name. This pointer must be treated as read-only; the topic filter must not + * be modified. Additionally, the topic filter may go out of scope as soon as the + * callback function returns, so it must be copied if it is needed at a later time. + * + * @attention Any pointers in this callback parameter may be freed as soon as + * the [callback function](@ref IotMqttCallbackInfo_t.function) returns. + * Therefore, data must be copied if it is needed after the callback function + * returns. + * @attention The MQTT library may set strings that are not NULL-terminated. + * + * @see #IotMqttCallbackInfo_t for the signature of a callback function. + */ +typedef struct IotMqttCallbackParam +{ + /** + * @brief The MQTT connection associated with this completed operation, + * incoming PUBLISH, or disconnect. + * + * [MQTT API functions](@ref mqtt_functions) are safe to call from a callback + * for completed operations or incoming PUBLISH messages. However, blocking + * function calls (including @ref mqtt_function_wait) are not recommended + * (though still safe). Do not call any API functions from a disconnect + * callback. + */ + IotMqttConnection_t mqttConnection; + + union + { + /* Valid for completed operations. */ + struct + { + IotMqttOperationType_t type; /**< @brief Type of operation that completed. */ + IotMqttOperation_t reference; /**< @brief Reference to the operation that completed. */ + IotMqttError_t result; /**< @brief Result of operation, e.g. succeeded or failed. */ + } operation; + + /* Valid for incoming PUBLISH messages. */ + struct + { + const char * pTopicFilter; /**< @brief Topic filter that matched the message. */ + uint16_t topicFilterLength; /**< @brief Length of `pTopicFilter`. */ + IotMqttPublishInfo_t info; /**< @brief PUBLISH message received from the server. */ + } message; + + /* Valid when a connection is disconnected. */ + IotMqttDisconnectReason_t disconnectReason; /**< @brief Why the MQTT connection was disconnected. */ + } u; /**< @brief Valid member depends on callback type. */ +} IotMqttCallbackParam_t; + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Information on a user-provided MQTT callback function. + * + * @paramfor @ref mqtt_function_subscribe, @ref mqtt_function_unsubscribe, + * and @ref mqtt_function_publish. Cannot be used with #IOT_MQTT_FLAG_WAITABLE. + * + * Provides a function to be invoked when an operation completes or when a + * server-to-client PUBLISH is received. + * + * @initializer{IotMqttCallbackInfo_t,IOT_MQTT_CALLBACK_INFO_INITIALIZER} + * + * Below is an example for receiving an asynchronous notification on operation + * completion. See @ref mqtt_function_subscribe for an example of using this struct + * with for incoming PUBLISH messages. + * + * @code{c} + * // Operation completion callback. + * void operationComplete( void * pArgument, IotMqttCallbackParam_t * pOperation ); + * + * // Callback information. + * IotMqttCallbackInfo_t callbackInfo = IOT_MQTT_CALLBACK_INFO_INITIALIZER; + * callbackInfo.function = operationComplete; + * + * // Operation to wait for. + * IotMqttError_t result = IotMqtt_Publish( &mqttConnection, + * &publishInfo, + * 0, + * &callbackInfo, + * &reference ); + * + * // Publish should have returned IOT_MQTT_STATUS_PENDING. Once a response + * // is received, operationComplete is executed with the actual status passed + * // in pOperation. + * @endcode + */ +typedef struct IotMqttCallbackInfo +{ + void * pCallbackContext; /**< @brief The first parameter to pass to the callback function to provide context. */ + + /** + * @brief User-provided callback function signature. + * + * @param[in] void * #IotMqttCallbackInfo_t.pCallbackContext + * @param[in] IotMqttCallbackParam_t * Details on the outcome of the MQTT operation + * or an incoming MQTT PUBLISH. + * + * @see #IotMqttCallbackParam_t for more information on the second parameter. + */ + void ( * function )( void *, + IotMqttCallbackParam_t * ); +} IotMqttCallbackInfo_t; + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Information on an MQTT subscription. + * + * @paramfor @ref mqtt_function_subscribe, @ref mqtt_function_unsubscribe + * + * An array of these is passed to @ref mqtt_function_subscribe and @ref + * mqtt_function_unsubscribe. However, #IotMqttSubscription_t.callback and + * and #IotMqttSubscription_t.qos are ignored by @ref mqtt_function_unsubscribe. + * + * @initializer{IotMqttSubscription_t,IOT_MQTT_SUBSCRIPTION_INITIALIZER} + * + * @note The lengths of the strings in this struct should not include the NULL + * terminator. Strings in this struct do not need to be NULL-terminated. + * @see #IotMqttCallbackInfo_t for details on setting a callback function. + */ +typedef struct IotMqttSubscription +{ + /** + * @brief QoS of messages delivered on subscription. + * + * Must be `0` or `1`. Ignored by @ref mqtt_function_unsubscribe. + */ + IotMqttQos_t qos; + + const char * pTopicFilter; /**< @brief Topic filter of subscription. */ + uint16_t topicFilterLength; /**< @brief Length of #IotMqttSubscription_t.pTopicFilter. */ + + /** + * @brief Callback to invoke when a message is received. + * + * See #IotMqttCallbackInfo_t. Ignored by @ref mqtt_function_unsubscribe. + */ + IotMqttCallbackInfo_t callback; +} IotMqttSubscription_t; + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Information on a new MQTT connection. + * + * @paramfor @ref mqtt_function_connect + * + * Passed as an argument to @ref mqtt_function_connect. Most members of this struct + * correspond to the content of an [MQTT CONNECT packet.] + * (http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd02/mqtt-v3.1.1-csprd02.html#_Toc385349764) + * + * @initializer{IotMqttConnectInfo_t,IOT_MQTT_CONNECT_INFO_INITIALIZER} + * + * @note The lengths of the strings in this struct should not include the NULL + * terminator. Strings in this struct do not need to be NULL-terminated. + */ +typedef struct IotMqttConnectInfo +{ + /** + * @brief Specifies if this MQTT connection is to an AWS IoT MQTT server. + * + * The AWS IoT MQTT broker [differs somewhat from the MQTT specification.] + * (https://docs.aws.amazon.com/iot/latest/developerguide/mqtt.html) + * When this member is `true`, the MQTT library will accommodate these + * differences. This setting should be `false` when communicating with a + * fully-compliant MQTT broker. + * + * @attention This setting MUST be `true` when using the AWS IoT MQTT + * server; it MUST be `false` otherwise. + * @note Currently, @ref IOT_MQTT_CONNECT_INFO_INITIALIZER sets this + * this member to `true`. + */ + bool awsIotMqttMode; + + /** + * @brief Whether this connection is a clean session. + * + * MQTT servers can maintain and topic filter subscriptions and unacknowledged + * PUBLISH messages. These form part of an MQTT session, which is identified by + * the [client identifier](@ref IotMqttConnectInfo_t.pClientIdentifier). + * + * Setting this value to `true` establishes a clean session, which causes + * the MQTT server to discard any previous session data for a client identifier. + * When the client disconnects, the server discards all session data. If this + * value is `true`, #IotMqttConnectInfo_t.pPreviousSubscriptions and + * #IotMqttConnectInfo_t.previousSubscriptionCount are ignored. + * + * Setting this value to `false` does one of the following: + * - If no previous session exists, the MQTT server will create a new + * persistent session. The server may maintain subscriptions and + * unacknowledged PUBLISH messages after a client disconnects, to be restored + * once the same client identifier reconnects. + * - If a previous session exists, the MQTT server restores all of the session's + * subscriptions for the client identifier and may immediately transmit any + * unacknowledged PUBLISH packets to the client. + * + * When a client with a persistent session disconnects, the MQTT server + * continues to maintain all subscriptions and unacknowledged PUBLISH messages. + * The client must also remember the session subscriptions to restore them + * upon reconnecting. #IotMqttConnectInfo_t.pPreviousSubscriptions and + * #IotMqttConnectInfo_t.previousSubscriptionCount are used to restore a + * previous session's subscriptions client-side. + */ + bool cleanSession; + + /** + * @brief An array of MQTT subscriptions present in a previous session, if any. + * + * Pointer to the start of an array of subscriptions present a previous session, + * if any. These subscriptions will be immediately restored upon reconnecting. + * + * This member is ignored if it is `NULL` or #IotMqttConnectInfo_t.cleanSession + * is `true`. If this member is not `NULL`, #IotMqttConnectInfo_t.previousSubscriptionCount + * must be nonzero. + */ + const IotMqttSubscription_t * pPreviousSubscriptions; + + /** + * @brief The number of MQTT subscriptions present in a previous session, if any. + * + * Number of subscriptions contained in the array + * #IotMqttConnectInfo_t.pPreviousSubscriptions. + * + * This value is ignored if #IotMqttConnectInfo_t.pPreviousSubscriptions + * is `NULL` or #IotMqttConnectInfo_t.cleanSession is `true`. If + * #IotMqttConnectInfo_t.pPreviousSubscriptions is not `NULL`, this value + * must be nonzero. + */ + size_t previousSubscriptionCount; + + /** + * @brief A message to publish if the new MQTT connection is unexpectedly closed. + * + * A Last Will and Testament (LWT) message may be published if this connection is + * closed without sending an MQTT DISCONNECT packet. This pointer should be set to + * an #IotMqttPublishInfo_t representing any LWT message to publish. If an LWT + * is not needed, this member must be set to `NULL`. + * + * Unlike other PUBLISH messages, an LWT message is limited to 65535 bytes in + * length. Additionally, [pWillInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs) + * and [pWillInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) will + * be ignored. + */ + const IotMqttPublishInfo_t * pWillInfo; + + uint16_t keepAliveSeconds; /**< @brief Period of keep-alive messages. Set to 0 to disable keep-alive. */ + + const char * pClientIdentifier; /**< @brief MQTT client identifier. */ + uint16_t clientIdentifierLength; /**< @brief Length of #IotMqttConnectInfo_t.pClientIdentifier. */ + + /* These credentials are not used by AWS IoT and may be ignored if + * awsIotMqttMode is true. */ + const char * pUserName; /**< @brief Username for MQTT connection. */ + uint16_t userNameLength; /**< @brief Length of #IotMqttConnectInfo_t.pUserName. */ + const char * pPassword; /**< @brief Password for MQTT connection. */ + uint16_t passwordLength; /**< @brief Length of #IotMqttConnectInfo_t.pPassword. */ +} IotMqttConnectInfo_t; + +#if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 + +/** + * @cond DOXYGEN_IGNORE + * Doxygen should ignore this section. + * + * Forward declaration of the internal MQTT packet structure. + */ + struct _mqttPacket; +/** @endcond */ + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Function pointers for MQTT packet serializer overrides. + * + * These function pointers allow the MQTT serialization and deserialization functions + * to be overridden for an MQTT connection. The compile-time setting + * @ref IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES must be `1` to enable this functionality. + * See the #IotMqttSerializer_t::serialize and #IotMqttSerializer_t::deserialize + * members for a list of functions that can be overridden. In addition, the functions + * for freeing packets and determining the packet type can also be overridden. If + * @ref IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES is `1`, the serializer initialization and + * cleanup functions may be extended. See documentation of + * @ref IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES for more information. + * + * If any function pointers that are `NULL`, then the default implementation of that + * function will be used. + */ + typedef struct IotMqttSerializer + { + /** + * @brief Get the MQTT packet type from a stream of bytes off the network. + * + * @param[in] pNetworkConnection Reference to the network connection. + * @param[in] pNetworkInterface Function pointers used to interact with the + * network. + * + * Default implementation: #_IotMqtt_GetPacketType + */ + uint8_t ( * getPacketType )( void * /* pNetworkConnection */, + const IotNetworkInterface_t * /* pNetworkInterface */ ); + + /** + * @brief Get the remaining length from a stream of bytes off the network. + * + * @param[in] pNetworkConnection Reference to the network connection. + * @param[in] pNetworkInterface Function pointers used to interact with the + * network. + * + * Default implementation: #_IotMqtt_GetRemainingLength + */ + size_t ( * getRemainingLength )( void * pNetworkConnection, + const IotNetworkInterface_t * pNetworkInterface ); + + /** + * @brief Free a packet generated by the serializer. + * + * This function pointer must be set if any other serializer override is set. + * @param[in] uint8_t* The packet to free. + * + * Default implementation: #_IotMqtt_FreePacket + */ + void ( * freePacket )( uint8_t * /* pPacket */ ); + + struct + { + /** + * @brief CONNECT packet serializer function. + * @param[in] IotMqttConnectInfo_t* User-provided CONNECT information. + * @param[out] uint8_t** Where the CONNECT packet is written. + * @param[out] size_t* Size of the CONNECT packet. + * + * Default implementation: #_IotMqtt_SerializeConnect + */ + IotMqttError_t ( * connect )( const IotMqttConnectInfo_t * /* pConnectInfo */, + uint8_t ** /* pConnectPacket */, + size_t * /* pPacketSize */ ); + + /** + * @brief PUBLISH packet serializer function. + * @param[in] IotMqttPublishInfo_t* User-provided PUBLISH information. + * @param[out] uint8_t** Where the PUBLISH packet is written. + * @param[out] size_t* Size of the PUBLISH packet. + * @param[out] uint16_t* The packet identifier generated for this PUBLISH. + * @param[out] uint8_t** Where the high byte of the packet identifier + * is written. + * + * Default implementation: #_IotMqtt_SerializePublish + */ + IotMqttError_t ( * publish )( const IotMqttPublishInfo_t * /* pPublishInfo */, + uint8_t ** /* pPublishPacket */, + size_t * /* pPacketSize */, + uint16_t * /* pPacketIdentifier */, + uint8_t ** /* pPacketIdentifierHigh */ ); + + /** + * @brief Set the `DUP` bit in a QoS `1` PUBLISH packet. + * @param[in] uint8_t* Pointer to the PUBLISH packet to modify. + * @param[in] uint8_t* The high byte of any packet identifier to modify. + * @param[out] uint16_t* New packet identifier (AWS IoT MQTT mode only). + * + * Default implementation: #_IotMqtt_PublishSetDup + */ + void ( * publishSetDup )( uint8_t * /* pPublishPacket */, + uint8_t * /* pPacketIdentifierHigh */, + uint16_t * /* pNewPacketIdentifier */ ); + + /** + * @brief PUBACK packet serializer function. + * @param[in] uint16_t The packet identifier to place in PUBACK. + * @param[out] uint8_t** Where the PUBACK packet is written. + * @param[out] size_t* Size of the PUBACK packet. + * + * Default implementation: #_IotMqtt_SerializePuback + */ + IotMqttError_t ( * puback )( uint16_t /* packetIdentifier */, + uint8_t ** /* pPubackPacket */, + size_t * /* pPacketSize */ ); + + /** + * @brief SUBSCRIBE packet serializer function. + * @param[in] IotMqttSubscription_t* User-provided array of subscriptions. + * @param[in] size_t Number of elements in the subscription array. + * @param[out] uint8_t** Where the SUBSCRIBE packet is written. + * @param[out] size_t* Size of the SUBSCRIBE packet. + * @param[out] uint16_t* The packet identifier generated for this SUBSCRIBE. + * + * Default implementation: #_IotMqtt_SerializeSubscribe + */ + IotMqttError_t ( * subscribe )( const IotMqttSubscription_t * /* pSubscriptionList */, + size_t /* subscriptionCount */, + uint8_t ** /* pSubscribePacket */, + size_t * /* pPacketSize */, + uint16_t * /* pPacketIdentifier */ ); + + /** + * @brief UNSUBSCRIBE packet serializer function. + * @param[in] IotMqttSubscription_t* User-provided array of subscriptions to remove. + * @param[in] size_t Number of elements in the subscription array. + * @param[out] uint8_t** Where the UNSUBSCRIBE packet is written. + * @param[out] size_t* Size of the UNSUBSCRIBE packet. + * @param[out] uint16_t* The packet identifier generated for this UNSUBSCRIBE. + * + * Default implementation: #_IotMqtt_SerializeUnsubscribe + */ + IotMqttError_t ( * unsubscribe )( const IotMqttSubscription_t * /* pSubscriptionList */, + size_t /* subscriptionCount */, + uint8_t ** /* pUnsubscribePacket */, + size_t * /* pPacketSize */, + uint16_t * /* pPacketIdentifier */ ); + + /** + * @brief PINGREQ packet serializer function. + * @param[out] uint8_t** Where the PINGREQ packet is written. + * @param[out] size_t* Size of the PINGREQ packet. + * + * Default implementation: #_IotMqtt_SerializePingreq + */ + IotMqttError_t ( * pingreq )( uint8_t ** /* pPingreqPacket */, + size_t * /* pPacketSize */ ); + + /** + * @brief DISCONNECT packet serializer function. + * @param[out] uint8_t** Where the DISCONNECT packet is written. + * @param[out] size_t* Size of the DISCONNECT packet. + * + * Default implementation: #_IotMqtt_SerializeDisconnect + */ + IotMqttError_t ( * disconnect )( uint8_t ** /* pDisconnectPacket */, + size_t * /* pPacketSize */ ); + } serialize; /**< @brief Overrides the packet serialization functions for a single connection. */ + + struct + { + /** + * @brief CONNACK packet deserializer function. + * @param[in,out] _mqttPacket* Pointer to an MQTT packet struct representing a CONNACK. + * + * Default implementation: #_IotMqtt_DeserializeConnack + */ + IotMqttError_t ( * connack )( struct _mqttPacket * /* pConnack */ ); + + /** + * @brief PUBLISH packet deserializer function. + * @param[in,out] _mqttPacket* Pointer to an MQTT packet struct representing a PUBLISH. + * + * Default implementation: #_IotMqtt_DeserializePublish + */ + IotMqttError_t ( * publish )( struct _mqttPacket * /* pPublish */ ); + + /** + * @brief PUBACK packet deserializer function. + * @param[in,out] _mqttPacket* Pointer to an MQTT packet struct representing a PUBACK. + * + * Default implementation: #_IotMqtt_DeserializePuback + */ + IotMqttError_t ( * puback )( struct _mqttPacket * pPuback ); + + /** + * @brief SUBACK packet deserializer function. + * @param[in,out] _mqttPacket* Pointer to an MQTT packet struct representing a SUBACK. + * + * Default implementation: #_IotMqtt_DeserializeSuback + */ + IotMqttError_t ( * suback )( struct _mqttPacket * /* pSuback */ ); + + /** + * @brief UNSUBACK packet deserializer function. + * @param[in,out] _mqttPacket* Pointer to an MQTT packet struct representing an UNSUBACK. + * + * Default implementation: #_IotMqtt_DeserializeUnsuback + */ + IotMqttError_t ( * unsuback )( struct _mqttPacket * /* pUnsuback */ ); + + /** + * @brief PINGRESP packet deserializer function. + * @param[in,out] _mqttPacket* Pointer to an MQTT packet struct representing a PINGRESP. + * + * Default implementation: #_IotMqtt_DeserializePingresp + */ + IotMqttError_t ( * pingresp )( struct _mqttPacket * /* pPingresp */ ); + } deserialize; /**< @brief Overrides the packet deserialization functions for a single connection. */ + } IotMqttSerializer_t; +#else /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */ + +/* When MQTT packet serializer overrides are disabled, this struct is an + * incomplete type. */ + typedef struct IotMqttSerializer IotMqttSerializer_t; + +#endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */ + +/** + * @ingroup mqtt_datatypes_paramstructs + * @brief Infomation on the transport-layer network connection for the new MQTT + * connection. + * + * @paramfor @ref mqtt_function_connect + * + * The MQTT library needs to be able to send and receive data over a network. + * This struct provides an interface for interacting with the network. + * + * @initializer{IotMqttNetworkInfo_t,IOT_MQTT_NETWORK_INFO_INITIALIZER} + */ +typedef struct IotMqttNetworkInfo +{ + /** + * @brief Whether a new network connection should be created. + * + * When this value is `true`, a new transport-layer network connection will + * be created along with the MQTT connection. #IotMqttNetworkInfo_t::pNetworkServerInfo + * and #IotMqttNetworkInfo_t::pNetworkCredentialInfo are valid when this value + * is `true`. + * + * When this value is `false`, the MQTT connection will use a transport-layer + * network connection that has already been established. The MQTT library will + * still set the appropriate receive callback even if the network connection + * has been established. + * #IotMqttNetworkInfo_t::pNetworkConnection, which represents an established + * network connection, is valid when this value is `false`. + */ + bool createNetworkConnection; + + union + { + struct + { + /** + * @brief Information on the MQTT server, passed as `pConnectionInfo` to + * #IotNetworkInterface_t::create. + * + * This member is opaque to the MQTT library. It is passed to the network + * interface when creating a new network connection. It is only valid when + * #IotMqttNetworkInfo_t::createNetworkConnection is `true`. + */ + void * pNetworkServerInfo; + + /** + * @brief Credentials for the MQTT server, passed as `pCredentialInfo` to + * #IotNetworkInterface_t::create. + * + * This member is opaque to the MQTT library. It is passed to the network + * interface when creating a new network connection. It is only valid when + * #IotMqttNetworkInfo_t::createNetworkConnection is `true`. + */ + void * pNetworkCredentialInfo; + } setup; + + /** + * @brief An established transport-layer network connection. + * + * This member is opaque to the MQTT library. It is passed to the network + * interface to reference an established network connection. It is only + * valid when #IotMqttNetworkInfo_t::createNetworkConnection is `false`. + */ + void * pNetworkConnection; + } u /**< @brief Valid member depends of IotMqttNetworkInfo_t.createNetworkConnection. */; + + /** + * @brief The network functions used by the new MQTT connection. + * + * @attention The function pointers of the network interface must remain valid + * for the lifetime of the MQTT connection. + */ + const IotNetworkInterface_t * pNetworkInterface; + + /** + * @brief A callback function to invoke when this MQTT connection is disconnected. + */ + IotMqttCallbackInfo_t disconnectCallback; + + #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 + + /** + * @brief MQTT packet serializer overrides used by the new MQTT connection. + * + * @attention The function pointers of the MQTT serializer overrides must + * remain valid for the lifetime of the MQTT connection. + */ + const IotMqttSerializer_t * pMqttSerializer; + #endif +} IotMqttNetworkInfo_t; + +/*------------------------- MQTT defined constants --------------------------*/ + +/** + * @constants_page{mqtt} + * @constants_brief{MQTT library} + * + * @section mqtt_constants_initializers MQTT Initializers + * @brief Provides default values for the data types of the MQTT library. + * + * @snippet this define_mqtt_initializers + * + * All user-facing data types of the MQTT library should be initialized using + * one of the following. + * + * @warning Failing to initialize an MQTT data type with the appropriate initializer + * may result in undefined behavior! + * @note The initializers may change at any time in future versions, but their + * names will remain the same. + * + * Example + * @code{c} + * IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER; + * IotMqttSerializer_t serializer = IOT_MQTT_SERIALIZER_INITIALIZER; + * IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER; + * IotMqttPublishInfo_t publishInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER; + * IotMqttSubscription_t subscription = IOT_MQTT_SUBSCRIPTION_INITIALIZER; + * IotMqttCallbackInfo_t callbackInfo = IOT_MQTT_CALLBACK_INFO_INITIALIZER; + * IotMqttConnection_t connection = IOT_MQTT_CONNECTION_INITIALIZER; + * IotMqttOperation_t operation = IOT_MQTT_OPERATION_INITIALIZER; + * @endcode + * + * @section mqtt_constants_flags MQTT Function Flags + * @brief Flags that modify the behavior of MQTT library functions. + * - #IOT_MQTT_FLAG_WAITABLE
+ * @copybrief IOT_MQTT_FLAG_WAITABLE + * - #IOT_MQTT_FLAG_CLEANUP_ONLY
+ * @copybrief IOT_MQTT_FLAG_CLEANUP_ONLY + * + * Flags should be bitwise-ORed with each other to change the behavior of + * @ref mqtt_function_subscribe, @ref mqtt_function_unsubscribe, + * @ref mqtt_function_publish, or @ref mqtt_function_disconnect. + * + * @note The values of the flags may change at any time in future versions, but + * their names will remain the same. Additionally, flags that may be used together + * will be bitwise-exclusive of each other. + */ + +/* @[define_mqtt_initializers] */ +/** @brief Initializer for #IotMqttNetworkInfo_t. */ +#define IOT_MQTT_NETWORK_INFO_INITIALIZER { .createNetworkConnection = true } +/** @brief Initializer for #IotMqttSerializer_t. */ +#define IOT_MQTT_SERIALIZER_INITIALIZER { 0 } +/** @brief Initializer for #IotMqttConnectInfo_t. */ +#define IOT_MQTT_CONNECT_INFO_INITIALIZER { .cleanSession = true } +/** @brief Initializer for #IotMqttPublishInfo_t. */ +#define IOT_MQTT_PUBLISH_INFO_INITIALIZER { .qos = IOT_MQTT_QOS_0 } +/** @brief Initializer for #IotMqttSubscription_t. */ +#define IOT_MQTT_SUBSCRIPTION_INITIALIZER { .qos = IOT_MQTT_QOS_0 } +/** @brief Initializer for #IotMqttCallbackInfo_t. */ +#define IOT_MQTT_CALLBACK_INFO_INITIALIZER { 0 } +/** @brief Initializer for #IotMqttConnection_t. */ +#define IOT_MQTT_CONNECTION_INITIALIZER NULL +/** @brief Initializer for #IotMqttOperation_t. */ +#define IOT_MQTT_OPERATION_INITIALIZER NULL +/* @[define_mqtt_initializers] */ + +/** + * @brief Allows the use of @ref mqtt_function_wait for blocking until completion. + * + * This flag is always valid for @ref mqtt_function_subscribe and + * @ref mqtt_function_unsubscribe. If passed to @ref mqtt_function_publish, + * the parameter [pPublishInfo->qos](@ref IotMqttPublishInfo_t.qos) must not be `0`. + * + * An #IotMqttOperation_t MUST be provided if this flag is set. Additionally, an + * #IotMqttCallbackInfo_t MUST NOT be provided. + * + * @note If this flag is set, @ref mqtt_function_wait MUST be called to clean up + * resources. + */ +#define IOT_MQTT_FLAG_WAITABLE ( 0x00000001 ) + +/** + * @brief Causes @ref mqtt_function_disconnect to only free memory and not send + * an MQTT DISCONNECT packet. + * + * This flag is only valid for @ref mqtt_function_disconnect. It should be passed + * to @ref mqtt_function_disconnect if the network goes offline or is otherwise + * unusable. + */ +#define IOT_MQTT_FLAG_CLEANUP_ONLY ( 0x00000001 ) + +#endif /* ifndef IOT_MQTT_TYPES_H_ */ diff --git a/bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.c b/bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.c new file mode 100644 index 0000000..0eeb827 --- /dev/null +++ b/bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.c @@ -0,0 +1,290 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Standard includes. */ +#include + +#include "http_demo_utils.h" + +/* Retry utilities. */ +#include "backoff_algorithm.h" + +/* Include PKCS11 helpers header. */ +#include "pkcs11_helpers.h" + +/* Parser utilities. */ +#include "http_parser.h" + +/*-----------------------------------------------------------*/ + +/** + * @brief The maximum number of retries for connecting to server. + */ +#define CONNECTION_RETRY_MAX_ATTEMPTS ( 5U ) + +/** + * @brief The maximum back-off delay (in milliseconds) for retrying connection to server. + */ +#define CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) + +/** + * @brief The base back-off delay (in milliseconds) to use for connection retry attempts. + */ +#define CONNECTION_RETRY_BACKOFF_BASE_MS ( 500U ) + +/*-----------------------------------------------------------*/ + +/** + * @brief Calculate and perform an exponential backoff with jitter delay for + * the next retry attempt of a failed network operation with the server. + * + * The function generates a random number, calculates the next backoff period + * with the generated random number, and performs the backoff delay operation if the + * number of retries have not exhausted. + * + * @note The PKCS11 module is used to generate the random number as it allows access + * to a True Random Number Generator (TRNG) if the vendor platform supports it. + * It is recommended to seed the random number generator with a device-specific entropy + * source so that probability of collisions from devices in connection retries is mitigated. + * + * @note The backoff period is calculated using the backoffAlgorithm library. + * + * @param[in, out] pxRetryAttempts The context to use for backoff period calculation + * with the backoffAlgorithm library. + * + * @return pdPASS if calculating the backoff period was successful; otherwise pdFAIL + * if there was failure in random number generation OR all retry attempts had exhausted. + */ +static BaseType_t prvBackoffForRetry( BackoffAlgorithmContext_t * pxRetryParams ); + +/*-----------------------------------------------------------*/ + +static BaseType_t prvBackoffForRetry( BackoffAlgorithmContext_t * pxRetryParams ) +{ + BaseType_t xReturnStatus = pdFAIL; + uint16_t usNextRetryBackOff = 0U; + BackoffAlgorithmStatus_t xBackoffAlgStatus = BackoffAlgorithmSuccess; + + /** + * To calculate the backoff period for the next retry attempt, we will + * generate a random number to provide to the backoffAlgorithm library. + * + * Note: The PKCS11 module is used to generate the random number as it allows access + * to a True Random Number Generator (TRNG) if the vendor platform supports it. + * It is recommended to use a random number generator seeded with a device-specific + * entropy source so that probability of collisions from devices in connection retries + * is mitigated. + */ + uint32_t ulRandomNum = 0; + + if( xPkcs11GenerateRandomNumber( ( uint8_t * ) &ulRandomNum, + sizeof( ulRandomNum ) ) == pdPASS ) + { + /* Get back-off value (in milliseconds) for the next retry attempt. */ + xBackoffAlgStatus = BackoffAlgorithm_GetNextBackoff( pxRetryParams, ulRandomNum, &usNextRetryBackOff ); + + if( xBackoffAlgStatus == BackoffAlgorithmRetriesExhausted ) + { + LogError( ( "All retry attempts have exhausted. Operation will not be retried" ) ); + } + else if( xBackoffAlgStatus == BackoffAlgorithmSuccess ) + { + /* Perform the backoff delay. */ + vTaskDelay( pdMS_TO_TICKS( usNextRetryBackOff ) ); + + xReturnStatus = pdPASS; + + LogInfo( ( "Retry attempt %lu out of maximum retry attempts %lu.", + ( pxRetryParams->attemptsDone + 1 ), + pxRetryParams->maxRetryAttempts ) ); + } + } + else + { + LogError( ( "Unable to retry operation with broker: Random number generation failed" ) ); + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t connectToServerWithBackoffRetries( TransportConnect_t connectFunction, + NetworkContext_t * pxNetworkContext ) +{ + BaseType_t xReturn = pdFAIL; + /* Struct containing the next backoff time. */ + BackoffAlgorithmContext_t xReconnectParams; + BaseType_t xBackoffStatus = 0U; + + configASSERT( connectFunction != NULL ); + configASSERT( pxNetworkContext != NULL ); + + /* Initialize reconnect attempts and interval. */ + BackoffAlgorithm_InitializeParams( &xReconnectParams, + CONNECTION_RETRY_BACKOFF_BASE_MS, + CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS, + CONNECTION_RETRY_MAX_ATTEMPTS ); + + /* Attempt to connect to the HTTP server. If connection fails, retry after a + * timeout. The timeout value will exponentially increase until either the + * maximum timeout value is reached or the set number of attempts are + * exhausted.*/ + do + { + xReturn = connectFunction( pxNetworkContext ); + + if( xReturn != pdPASS ) + { + LogWarn( ( "Connection to the HTTP server failed. " + "Retrying connection with backoff and jitter." ) ); + + /* As the connection attempt failed, we will retry the connection after an + * exponential backoff with jitter delay. */ + + /* Calculate the backoff period for the next retry attempt and perform the wait operation. */ + xBackoffStatus = prvBackoffForRetry( &xReconnectParams ); + } + } while( ( xReturn == pdFAIL ) && ( xBackoffStatus == pdPASS ) ); + + return xReturn; +} + +/*-----------------------------------------------------------*/ + +HTTPStatus_t getUrlPath( const char * pcUrl, + size_t xUrlLen, + const char ** pcPath, + size_t * pxPathLen ) +{ + /* http-parser status. Initialized to 1 to signify failure. */ + int parserStatus = 1; + struct http_parser_url urlParser; + HTTPStatus_t xHTTPStatus = HTTPSuccess; + + /* Sets all members in urlParser to 0. */ + http_parser_url_init( &urlParser ); + + if( ( pcUrl == NULL ) || ( pcPath == NULL ) || ( pxPathLen == NULL ) ) + { + LogError( ( "NULL parameter passed to getUrlPath()." ) ); + xHTTPStatus = HTTPInvalidParameter; + } + + if( xHTTPStatus == HTTPSuccess ) + { + parserStatus = http_parser_parse_url( pcUrl, xUrlLen, 0, &urlParser ); + + if( parserStatus != 0 ) + { + LogError( ( "Error parsing the input URL %.*s. Error code: %d.", + ( int32_t ) xUrlLen, + pcUrl, + parserStatus ) ); + xHTTPStatus = HTTPParserInternalError; + } + } + + if( xHTTPStatus == HTTPSuccess ) + { + *pxPathLen = ( size_t ) ( urlParser.field_data[ UF_PATH ].len ); + + if( *pxPathLen == 0 ) + { + xHTTPStatus = HTTPNoResponse; + *pcPath = NULL; + } + else + { + *pcPath = &pcUrl[ urlParser.field_data[ UF_PATH ].off ]; + } + } + + if( xHTTPStatus != HTTPSuccess ) + { + LogError( ( "Error parsing the path from URL %s. Error code: %d", + pcUrl, + xHTTPStatus ) ); + } + + return xHTTPStatus; +} + +/*-----------------------------------------------------------*/ + +HTTPStatus_t getUrlAddress( const char * pcUrl, + size_t xUrlLen, + const char ** pcAddress, + size_t * pxAddressLen ) +{ + /* http-parser status. Initialized to 1 to signify failure. */ + int parserStatus = 1; + struct http_parser_url urlParser; + HTTPStatus_t xHTTPStatus = HTTPSuccess; + + /* Sets all members in urlParser to 0. */ + http_parser_url_init( &urlParser ); + + if( ( pcUrl == NULL ) || ( pcAddress == NULL ) || ( pxAddressLen == NULL ) ) + { + LogError( ( "NULL parameter passed to getUrlAddress()." ) ); + xHTTPStatus = HTTPInvalidParameter; + } + + if( xHTTPStatus == HTTPSuccess ) + { + parserStatus = http_parser_parse_url( pcUrl, xUrlLen, 0, &urlParser ); + + if( parserStatus != 0 ) + { + LogError( ( "Error parsing the input URL %.*s. Error code: %d.", + ( int32_t ) xUrlLen, + pcUrl, + parserStatus ) ); + xHTTPStatus = HTTPParserInternalError; + } + } + + if( xHTTPStatus == HTTPSuccess ) + { + *pxAddressLen = ( size_t ) ( urlParser.field_data[ UF_HOST ].len ); + + if( *pxAddressLen == 0 ) + { + xHTTPStatus = HTTPNoResponse; + *pcAddress = NULL; + } + else + { + *pcAddress = &pcUrl[ urlParser.field_data[ UF_HOST ].off ]; + } + } + + if( xHTTPStatus != HTTPSuccess ) + { + LogError( ( "Error parsing the address from URL %s. Error code %d", + pcUrl, + xHTTPStatus ) ); + } + + return xHTTPStatus; +} diff --git a/bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.h b/bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.h new file mode 100644 index 0000000..7a93bdc --- /dev/null +++ b/bsp/aws_libraries/demos/common/http_demo_helpers/http_demo_utils.h @@ -0,0 +1,125 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef HTTP_DEMO_UTILS_H +#define HTTP_DEMO_UTILS_H + +/* Standard includes. */ +#include +#include +#include + +/* Transport interface implementation include header for TLS. */ +#include "transport_secure_sockets.h" + +/* Kernel includes. */ +#include "FreeRTOS.h" + +/* HTTP API header. */ +#include "core_http_client.h" + +/** + * @brief Function pointer for establishing connection to a server. + * + * @param[out] pxNetworkContext Implementation-defined network context. + * + * @return pdFAIL on failure; pdPASS on successful connection. + */ +typedef BaseType_t ( * TransportConnect_t )( NetworkContext_t * pxNetworkContext ); + +/** + * @brief Connect to a server with reconnection retries. + * + * If connection fails, retry is attempted after a timeout. The timeout value + * will exponentially increase until either the maximum timeout value is reached + * or the set number of attempts are exhausted. + * + * @param[in] connectFunction Function pointer for establishing connection to a + * server. + * @param[out] pxNetworkContext Implementation-defined network context. + * + * @return pdFAIL on failure; pdPASS on successful connection. + */ +BaseType_t connectToServerWithBackoffRetries( TransportConnect_t connectFunction, + NetworkContext_t * pxNetworkContext ); + +/** + * @brief Retrieve the path from the input URL. + * + * This function retrieves the location and length of the path from within the + * input the URL. The query is not included in the length returned. + * + * The URL MUST start with "http://" or "https://" to find the path. + * + * For example, if pcUrl is: + * "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff" + * + * Then pcPath and pxPathLen will be the following: + * *pcPath = "/path/to/item.txt?optionalquery=stuff" + * *pxPathLen = 17 + * + * @param[in] pcUrl URL string to parse. + * @param[in] xUrlLen The length of the URL string input. + * @param[out] pcPath pointer within input url that the path starts at. + * @param[out] pxPathLen Length of the path. + * + * @return The status of the parsing attempt: + * HTTPSuccess if the path was successfully parsed, + * HTTPParserInternalError if there was an error parsing the URL, + * or HTTPNoResponse if the path was not found. + */ +HTTPStatus_t getUrlPath( const char * pcUrl, + size_t xUrlLen, + const char ** pcPath, + size_t * pxPathLen ); + +/** + * @brief Retrieve the Address from the input URL. + * + * This function retrieves the location and length of the address from within + * the input URL. The path and query are not included in the length returned. + * + * The URL MUST start with "http://" or "https://" to find the address. + * + * For example, if pcUrl is: + * "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff" + * + * Then pcAddress and pxAddressLen will be the following: + * *pcAddress = "www.somewebsite.com/path/to/item.txt?optionalquery=stuff" + * *pxAddressLen = 19 + * + * @param[in] pcUrl URL string to parse. + * @param[in] xUrlLen The length of the URL string input. + * @param[out] pcAddress pointer within input url that the address starts at. + * @param[out] pxAddressLen Length of the address. + * + * @return The status of the parsing attempt: + * HTTPSuccess if the path was successfully parsed, + * HTTPParserInternalError if there was an error parsing the URL, + * or HTTPNoResponse if the path was not found. + */ +HTTPStatus_t getUrlAddress( const char * pcUrl, + size_t xUrlLen, + const char ** pcAddress, + size_t * pxAddressLen ); + +#endif /* ifndef HTTP_DEMO_UTILS_H */ diff --git a/bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.c b/bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.c new file mode 100644 index 0000000..088b949 --- /dev/null +++ b/bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.c @@ -0,0 +1,1165 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file mqtt_demo_helpers.c + * + * @brief This file provides helper functions used by the Shadow demo application to + * do MQTT operations over a mutually authenticated TLS connection. + * + * A mutually authenticated TLS connection is used to connect to the AWS IoT + * MQTT message broker in this example. Define democonfigMQTT_BROKER_ENDPOINT + * and democonfigROOT_CA_PEM, in shadow_demo_config.h, and the client + * private key and certificate, in aws_clientcredential_keys.h, to establish a + * mutually authenticated connection. + */ + +/* Standard includes. */ +#include +#include +#include + +/* MQTT API header. */ +#include "core_mqtt.h" + +/* Shadow includes */ +#include "mqtt_demo_helpers.h" + +/* Include AWS IoT metrics macros header. */ +#include "aws_iot_metrics.h" + +/* Retry utilities include. */ +#include "backoff_algorithm.h" + +/* Include PKCS11 helpers header. */ +#include "pkcs11_helpers.h" + +/* Include header for client credentials. */ +#include "aws_clientcredential.h" + +/* Include header for root CA certificates. */ +#include "iot_default_root_certificates.h" + +/* Include the secure sockets implementation of the transport interface. */ +#include "transport_secure_sockets.h" + +/*-----------------------------------------------------------*/ + +/** + * @brief The maximum number of retries for connecting to server. + */ +#define CONNECTION_RETRY_MAX_ATTEMPTS ( 5U ) + +/** + * @brief The maximum back-off delay (in milliseconds) for retrying connection to server. + */ +#define CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) + +/** + * @brief The base back-off delay (in milliseconds) to use for connection retry attempts. + */ +#define CONNECTION_RETRY_BACKOFF_BASE_MS ( 500U ) + +/** + * @brief The maximum number of retries for subscribing to topic filter when broker rejects an attempt. + */ +#define SUBSCRIBE_RETRY_MAX_ATTEMPTS ( 4U ) + +/** + * @brief The maximum back-off delay (in milliseconds) for retrying subscription to topic. + */ +#define SUBSCRIBE_RETRY_MAX_BACKOFF_DELAY_MS ( 2500U ) + +/** + * @brief The base back-off delay (in milliseconds) to use for subscription retry attempts. + */ +#define SUBSCRIBE_RETRY_BACKOFF_BASE_MS ( 500U ) + +/** + * @brief Timeout for receiving CONNACK packet in milliseconds. + */ +#define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 1000U ) + +/** + * @brief The number of topic filters to subscribe. + */ +#define mqttexampleTOPIC_COUNT ( 1 ) + +/** + * @brief Time to wait between each cycle of the demo implemented by prvMQTTDemoTask(). + */ +#define mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS ( pdMS_TO_TICKS( 5000U ) ) + +/** + * @brief Timeout for MQTT_ProcessLoop in milliseconds. + */ +#define mqttexamplePROCESS_LOOP_TIMEOUT_MS ( 500U ) + +/** + * @brief The maximum number of times to call MQTT_ProcessLoop() when polling + * for a specific packet from the broker. + */ +#define MQTT_PROCESS_LOOP_PACKET_WAIT_COUNT_MAX ( 30U ) + +/** + * @brief Keep alive time reported to the broker while establishing an MQTT connection. + * + * It is the responsibility of the Client to ensure that the interval between + * Control Packets being sent does not exceed the this Keep Alive value. In the + * absence of sending any other Control Packets, the Client MUST send a + * PINGREQ Packet. + */ +#define mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS ( 60U ) + +/** + * @brief Delay between MQTT publishes. Note that the process loop also has a + * timeout, so the total time between publishes is the sum of the two delays. + */ +#define mqttexampleDELAY_BETWEEN_PUBLISHES ( pdMS_TO_TICKS( 500U ) ) + +/** + * @brief Transport timeout in milliseconds for transport send and receive. + */ +#define mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ( 200U ) + +/** + * @brief Maximum number of outgoing publishes maintained in the application + * until an ack is received from the broker. + */ +#define MAX_OUTGOING_PUBLISHES ( 1U ) + +/** + * @brief Milliseconds per second. + */ +#define MILLISECONDS_PER_SECOND ( 1000U ) + +/** + * @brief Milliseconds per FreeRTOS tick. + */ +#define MILLISECONDS_PER_TICK ( MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) + +/*-----------------------------------------------------------*/ + +/** + * @brief Each compilation unit that consumes the NetworkContext must define it. + * It should contain a single pointer to the type of your desired transport. + * When using multiple transports in the same compilation unit, define this pointer as void *. + * + * @note Transport stacks are defined in amazon-freertos/libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h. + */ +struct NetworkContext +{ + SecureSocketsTransportParams_t * pParams; +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Structure to keep the MQTT publish packets until an ack is received + * for QoS1 publishes. + */ +typedef struct PublishPackets +{ + /** + * @brief Packet identifier of the publish packet. + */ + uint16_t packetId; + + /** + * @brief Publish info of the publish packet. + */ + MQTTPublishInfo_t pubInfo; +} PublishPackets_t; + +/** + * @brief Global entry time into the application to use as a reference timestamp + * in the #prvGetTimeMs function. #prvGetTimeMs will always return the difference + * between the current time and the global entry time. This will reduce the chances + * of overflow for the 32 bit unsigned integer used for holding the timestamp. + */ +static uint32_t ulGlobalEntryTimeMs; + +/*-----------------------------------------------------------*/ + +/** + * @brief Packet Identifier generated when Subscribe request was sent to the broker; + * it is used to match received Subscribe ACK to the transmitted subscribe. + */ +static uint16_t globalSubscribePacketIdentifier = 0U; + +/** + * @brief Packet Identifier generated when Unsubscribe request was sent to the broker; + * it is used to match received Unsubscribe ACK to the transmitted unsubscribe + * request. + */ +static uint16_t globalUnsubscribePacketIdentifier = 0U; + +/** + * @brief MQTT packet type received from the MQTT broker. + * + * @note Only on receiving incoming SUBACK or UNSUBACK, this + * variable is updated. For MQTT packets PUBACK and PINGRESP, the variable is + * not updated since there is no need to specifically wait for it in this demo. + * A single variable suffices as this demo uses single task and requests one operation + * (of SUBSCRIBE or UNSUBSCRIBE) at a time before expecting response from + * the broker. Hence it is not possible to receive multiple packets of type + * SUBACK and UNSUBACK in a single call of #prvWaitForPacket. + * For a multi task application, consider a different method to wait for the packet, if needed. + */ +static uint16_t globalPacketTypeReceived = 0U; + +/** + * @brief A pair containing a topic filter and its SUBACK status. + */ +typedef struct topicFilterContext +{ + const char * pcTopicFilter; + MQTTSubAckStatus_t xSubAckStatus; +} topicFilterContext_t; + +/** + * @brief A struct containing the context of a SUBACK; the SUBACK status + * of a filter is updated when the event callback processes a SUBACK. + */ +static topicFilterContext_t xTopicFilterContext; + +/** + * @brief Array to keep the outgoing publish messages. + * These stored outgoing publish messages are kept until a successful ack + * is received. + */ +static PublishPackets_t outgoingPublishPackets[ MAX_OUTGOING_PUBLISHES ] = { 0 }; + +/** + * @brief The flag to indicate the mqtt session changed. + */ +static bool mqttSessionEstablished = false; + +/** + * @brief The parameters for the network context using a TLS channel. + */ +static SecureSocketsTransportParams_t xSecureSocketsTransportParams; + +/*-----------------------------------------------------------*/ + +/** + * @brief Calculate and perform an exponential backoff with jitter delay for + * the next retry attempt of a failed network operation with the server. + * + * The function generates a random number, calculates the next backoff period + * with the generated random number, and performs the backoff delay operation if the + * number of retries have not exhausted. + * + * @note The PKCS11 module is used to generate the random number as it allows access + * to a True Random Number Generator (TRNG) if the vendor platform supports it. + * It is recommended to seed the random number generator with a device-specific entropy + * source so that probability of collisions from devices in connection retries is mitigated. + * + * @note The backoff period is calculated using the backoffAlgorithm library. + * + * @param[in, out] pxRetryAttempts The context to use for backoff period calculation + * with the backoffAlgorithm library. + * + * @return pdPASS if calculating the backoff period was successful; otherwise pdFAIL + * if there was failure in random number generation OR all retry attempts had exhausted. + */ +static BaseType_t prvBackoffForRetry( BackoffAlgorithmContext_t * pxRetryParams ); + +/** + * @brief Connect to MQTT broker with reconnection retries. + * + * If connection fails, retry is attempted after a timeout. + * Timeout value will exponentially increase until maximum + * timeout value is reached or the number of attempts are exhausted. + * + * @param[out] pxNetworkContext The output parameter to return the created network context. + * + * @return The status of the final connection attempt. + */ +static TransportSocketStatus_t prvConnectToServerWithBackoffRetries( NetworkContext_t * pxNetworkContext ); + +/** + * @brief Helper function to wait for a specific incoming packet from the + * broker. + * + * @param[in] pxMQTTContext MQTT context pointer. + * @param[in] usPacketType Packet type to wait for. + * + * @return pdFAIL if the expected packet from the broker never arrives; + * pdPASS if it arrives. + */ +static BaseType_t prvWaitForPacket( MQTTContext_t * pxMQTTContext, + uint16_t usPacketType ); + +/** + * @brief Function to get the free index at which an outgoing publish + * can be stored. + * + * @param[out] pucIndex The output parameter to return the index at which an + * outgoing publish message can be stored. + * + * @return pdFAIL if no more publishes can be stored; + * pdPASS if an index to store the next outgoing publish is obtained. + */ +static BaseType_t prvGetNextFreeIndexForOutgoingPublishes( uint8_t * pucIndex ); + +/** + * @brief Function to clean up an outgoing publish at given index from the + * #outgoingPublishPackets array. + * + * @param[in] ucIndex The index at which a publish message has to be cleaned up. + */ +static void vCleanupOutgoingPublishAt( uint8_t ucIndex ); + +/** + * @brief Function to clean up all the outgoing publishes maintained in the + * array. + */ +static void vCleanupOutgoingPublishes( void ); + +/** + * @brief Function to clean up the publish packet with the given packet id. + * + * @param[in] usPacketId Packet identifier of the packet to be cleaned up from + * the array. + */ +static void vCleanupOutgoingPublishWithPacketID( uint16_t usPacketId ); + +/** + * @brief Function to resend the publishes if a session is re-established with + * the broker. This function handles the resending of the QoS1 publish packets, + * which are maintained locally. + * + * @param[in] pxMqttContext MQTT context pointer. + */ +static BaseType_t handlePublishResend( MQTTContext_t * pxMqttContext ); + +/** + * @brief The timer query function provided to the MQTT context. + * + * @return Time in milliseconds. + */ +static uint32_t prvGetTimeMs( void ); + +/*-----------------------------------------------------------*/ + +static BaseType_t prvBackoffForRetry( BackoffAlgorithmContext_t * pxRetryParams ) +{ + BaseType_t xReturnStatus = pdFAIL; + uint16_t usNextRetryBackOff = 0U; + BackoffAlgorithmStatus_t xBackoffAlgStatus = BackoffAlgorithmSuccess; + + /** + * To calculate the backoff period for the next retry attempt, we will + * generate a random number to provide to the backoffAlgorithm library. + * + * Note: The PKCS11 module is used to generate the random number as it allows access + * to a True Random Number Generator (TRNG) if the vendor platform supports it. + * It is recommended to use a random number generator seeded with a device-specific + * entropy source so that probability of collisions from devices in connection retries + * is mitigated. + */ + uint32_t ulRandomNum = 0; + + if( xPkcs11GenerateRandomNumber( ( uint8_t * ) &ulRandomNum, + sizeof( ulRandomNum ) ) == pdPASS ) + { + /* Get back-off value (in milliseconds) for the next retry attempt. */ + xBackoffAlgStatus = BackoffAlgorithm_GetNextBackoff( pxRetryParams, ulRandomNum, &usNextRetryBackOff ); + + if( xBackoffAlgStatus == BackoffAlgorithmRetriesExhausted ) + { + LogError( ( "All retry attempts have exhausted. Operation will not be retried" ) ); + } + else if( xBackoffAlgStatus == BackoffAlgorithmSuccess ) + { + /* Perform the backoff delay. */ + vTaskDelay( pdMS_TO_TICKS( usNextRetryBackOff ) ); + + xReturnStatus = pdPASS; + + LogInfo( ( "Retry attempt %lu out of maximum retry attempts %lu.", + ( pxRetryParams->attemptsDone + 1 ), + pxRetryParams->maxRetryAttempts ) ); + } + } + else + { + LogError( ( "Unable to retry operation with broker: Random number generation failed" ) ); + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +static TransportSocketStatus_t prvConnectToServerWithBackoffRetries( NetworkContext_t * pxNetworkContext ) +{ + TransportSocketStatus_t xNetworkStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + BackoffAlgorithmContext_t xReconnectParams = { 0 }; + BaseType_t xBackoffStatus = pdPASS; + ServerInfo_t xServerInfo = { 0 }; + SocketsConfig_t xSocketConfig = { 0 }; + + /* Initialize information to connect to the MQTT broker. */ + xServerInfo.pHostName = democonfigMQTT_BROKER_ENDPOINT; + xServerInfo.hostNameLength = sizeof( democonfigMQTT_BROKER_ENDPOINT ) - 1U; + xServerInfo.port = democonfigMQTT_BROKER_PORT; + + /* Set the Secure Socket configurations. */ + xSocketConfig.enableTls = true; + + /* Pass the ALPN protocol name depending on the port being used. + * Please see more details about the ALPN protocol for the AWS IoT MQTT + * endpoint in the link below. + * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ + */ + if( xServerInfo.port == 443 ) + { + xSocketConfig.pAlpnProtos = socketsAWS_IOT_ALPN_MQTT; + } + + xSocketConfig.maxFragmentLength = 0; + xSocketConfig.disableSni = false; + xSocketConfig.sendTimeoutMs = mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS; + xSocketConfig.recvTimeoutMs = mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS; + + /* Initialize reconnect attempts and interval. */ + BackoffAlgorithm_InitializeParams( &xReconnectParams, + CONNECTION_RETRY_BACKOFF_BASE_MS, + CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS, + CONNECTION_RETRY_MAX_ATTEMPTS ); + + /* Attempt to connect to MQTT broker. If connection fails, retry after + * a timeout. Timeout value will exponentially increase until maximum + * attempts are reached. + */ + do + { + /* Establish a TCP connection with the MQTT broker. This example connects to + * the MQTT broker as specified in democonfigMQTT_BROKER_ENDPOINT and + * democonfigMQTT_BROKER_PORT at the top of this file. */ + LogInfo( ( "Create a TCP connection to %s:%d.", + democonfigMQTT_BROKER_ENDPOINT, + democonfigMQTT_BROKER_PORT ) ); + xNetworkStatus = SecureSocketsTransport_Connect( pxNetworkContext, + &xServerInfo, + &xSocketConfig ); + + if( xNetworkStatus != TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + LogWarn( ( "Connection to the broker failed. Attempting connection retry after backoff delay." ) ); + + /* As the connection attempt failed, we will retry the connection after an + * exponential backoff with jitter delay. */ + + /* Calculate the backoff period for the next retry attempt and perform the wait operation. */ + xBackoffStatus = prvBackoffForRetry( &xReconnectParams ); + } + } while( ( xNetworkStatus != TRANSPORT_SOCKET_STATUS_SUCCESS ) && ( xBackoffStatus == pdPASS ) ); + + return xNetworkStatus; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvWaitForPacket( MQTTContext_t * pxMQTTContext, + uint16_t usPacketType ) +{ + uint8_t ucCount = 0U; + MQTTStatus_t xMQTTStatus = MQTTSuccess; + BaseType_t xStatus = pdFAIL; + + /* Reset the packet type received. */ + globalPacketTypeReceived = 0U; + + /* Call MQTT_ProcessLoop multiple times over small timeouts instead of a single + * large timeout so that we can unblock immediately on receiving the packet. */ + while( ( globalPacketTypeReceived != usPacketType ) && + ( ucCount++ < MQTT_PROCESS_LOOP_PACKET_WAIT_COUNT_MAX ) && + ( xMQTTStatus == MQTTSuccess ) ) + { + /* Event callback will set #usPacketTypeReceived when receiving appropriate packet. This + * will wait for at most mqttexamplePROCESS_LOOP_TIMEOUT_MS. */ + xMQTTStatus = MQTT_ProcessLoop( pxMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); + } + + if( ( xMQTTStatus != MQTTSuccess ) || ( globalPacketTypeReceived != usPacketType ) ) + { + xStatus = pdFAIL; + LogError( ( "MQTT_ProcessLoop failed to receive packet: Packet type=%02X, LoopDuration=%u, Status=%s", + usPacketType, + ( mqttexamplePROCESS_LOOP_TIMEOUT_MS * ucCount ), + MQTT_Status_strerror( xMQTTStatus ) ) ); + } + else + { + xStatus = pdPASS; + } + + return xStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t SubscribeToTopic( MQTTContext_t * pxMqttContext, + const char * pcTopicFilter, + uint16_t usTopicFilterLength ) +{ + MQTTStatus_t xMqttStatus = MQTTSuccess; + BackoffAlgorithmContext_t xRetryParams; + BaseType_t xBackoffStatus = pdFAIL; + BaseType_t xSubscribeStatus = pdFAIL; + MQTTSubscribeInfo_t xMQTTSubscription; + + assert( pxMqttContext != NULL ); + assert( pcTopicFilter != NULL ); + assert( usTopicFilterLength > 0 ); + + /* Some fields not used so start with everything at 0. */ + ( void ) memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) ); + + /* Initialize the status of the subscription acknowledgement. */ + xTopicFilterContext.pcTopicFilter = pcTopicFilter; + xTopicFilterContext.xSubAckStatus = MQTTSubAckFailure; + + /* Get a unique packet id. */ + globalSubscribePacketIdentifier = MQTT_GetPacketId( pxMqttContext ); + + /* Subscribe to the #pcTopicFilter topic filter that is passed by a demo application. */ + xMQTTSubscription.qos = MQTTQoS1; + xMQTTSubscription.pTopicFilter = pcTopicFilter; + xMQTTSubscription.topicFilterLength = usTopicFilterLength; + + /* Initialize retry attempts and interval. */ + BackoffAlgorithm_InitializeParams( &xRetryParams, + SUBSCRIBE_RETRY_BACKOFF_BASE_MS, + SUBSCRIBE_RETRY_MAX_BACKOFF_DELAY_MS, + SUBSCRIBE_RETRY_MAX_ATTEMPTS ); + + do + { + xSubscribeStatus = pdFAIL; + + /* The client should now be connected to the broker. Subscribe to the topic + * as specified in #pcTopicFilter by sending a subscribe packet. */ + LogInfo( ( "Attempt to subscribe to the MQTT topic %s.", pcTopicFilter ) ); + xMqttStatus = MQTT_Subscribe( pxMqttContext, + &xMQTTSubscription, + sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ), + globalSubscribePacketIdentifier ); + + if( xMqttStatus != MQTTSuccess ) + { + LogError( ( "Failed to SUBSCRIBE to MQTT topic %s. Error=%s", + pcTopicFilter, usTopicFilterLength ) ); + } + else + { + LogInfo( ( "SUBSCRIBE sent for topic %s to broker.", pcTopicFilter ) ); + + /* Process incoming packet from the broker. After sending the subscribe, the + * client may receive a publish before it receives a subscribe ack. Therefore, + * call generic incoming packet processing function. The application + * must be ready to receive any packet. This demo uses the generic packet + * processing function everywhere to highlight this fact. */ + xSubscribeStatus = prvWaitForPacket( pxMqttContext, MQTT_PACKET_TYPE_SUBACK ); + } + + if( xSubscribeStatus == pdFAIL ) + { + LogError( ( "SUBACK never arrived for subscription attempt to topic %s.", + xTopicFilterContext.pcTopicFilter ) ); + break; + } + else + { + /* Check if recent subscription request has been rejected. #xTopicFilterContext is updated + * in the event callback to reflect the status of the SUBACK sent by the broker. It represents + * either the QoS level granted by the server upon subscription, or acknowledgement of + * server rejection of the subscription request. */ + if( xTopicFilterContext.xSubAckStatus == MQTTSubAckFailure ) + { + xSubscribeStatus = pdFAIL; + + /* As the subscribe attempt failed, we will retry the subscription request after an + * exponential backoff with jitter delay. */ + + /* Retry subscribe after exponential back-off. */ + LogWarn( ( "Server rejected subscription request. Attempting to re-subscribe to topic %s.", + xTopicFilterContext.pcTopicFilter ) ); + + xBackoffStatus = prvBackoffForRetry( &xRetryParams ); + } + } + } while( ( xSubscribeStatus == pdFAIL ) && ( xBackoffStatus == pdPASS ) ); + + return xSubscribeStatus; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvGetNextFreeIndexForOutgoingPublishes( uint8_t * pucIndex ) +{ + BaseType_t xReturnStatus = pdFAIL; + uint8_t ucIndex = 0; + + assert( outgoingPublishPackets != NULL ); + assert( pucIndex != NULL ); + + for( ucIndex = 0; ucIndex < MAX_OUTGOING_PUBLISHES; ucIndex++ ) + { + /* A free ucIndex is marked by invalid packet id. + * Check if the the ucIndex has a free slot. */ + if( outgoingPublishPackets[ ucIndex ].packetId == MQTT_PACKET_ID_INVALID ) + { + xReturnStatus = pdPASS; + break; + } + } + + /* Copy the available ucIndex into the output param. */ + *pucIndex = ucIndex; + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +static void vCleanupOutgoingPublishAt( uint8_t ucIndex ) +{ + assert( outgoingPublishPackets != NULL ); + assert( ucIndex < MAX_OUTGOING_PUBLISHES ); + + /* Clear the outgoing publish packet. */ + ( void ) memset( &( outgoingPublishPackets[ ucIndex ] ), + 0x00, + sizeof( outgoingPublishPackets[ ucIndex ] ) ); +} + +/*-----------------------------------------------------------*/ + +static void vCleanupOutgoingPublishes( void ) +{ + assert( outgoingPublishPackets != NULL ); + + /* Clean up all the outgoing publish packets. */ + ( void ) memset( outgoingPublishPackets, 0x00, sizeof( outgoingPublishPackets ) ); +} + +/*-----------------------------------------------------------*/ + +static void vCleanupOutgoingPublishWithPacketID( uint16_t usPacketId ) +{ + uint8_t ucIndex = 0; + + assert( outgoingPublishPackets != NULL ); + assert( usPacketId != MQTT_PACKET_ID_INVALID ); + + /* Clean up all the saved outgoing publishes. */ + for( ; ucIndex < MAX_OUTGOING_PUBLISHES; ucIndex++ ) + { + if( outgoingPublishPackets[ ucIndex ].packetId == usPacketId ) + { + vCleanupOutgoingPublishAt( ucIndex ); + LogInfo( ( "Cleaned up outgoing publish packet with packet id %u.\n\n", + usPacketId ) ); + break; + } + } +} + +/*-----------------------------------------------------------*/ + +void vHandleOtherIncomingPacket( MQTTPacketInfo_t * pxPacketInfo, + uint16_t usPacketIdentifier ) +{ + MQTTStatus_t xResult = MQTTSuccess; + uint8_t * pucPayload = NULL; + size_t xSize = 0; + + /* Handle other packets. */ + switch( pxPacketInfo->type ) + { + case MQTT_PACKET_TYPE_SUBACK: + LogInfo( ( "MQTT_PACKET_TYPE_SUBACK.\n\n" ) ); + /* Update the packet type received to SUBACK. */ + globalPacketTypeReceived = MQTT_PACKET_TYPE_SUBACK; + + /* A SUBACK from the broker, containing the server response to our subscription request, has been received. + * It contains the status code indicating server approval/rejection for the subscription to the single topic + * requested. The SUBACK will be parsed to obtain the status code, and this status code will be stored in global + * variable #xTopicFilterContext. */ + xResult = MQTT_GetSubAckStatusCodes( pxPacketInfo, &pucPayload, &xSize ); + + /* MQTT_GetSubAckStatusCodes always returns success if called with packet info + * from the event callback and non-NULL parameters. */ + configASSERT( xResult == MQTTSuccess ); + /* Only a single topic filter is expected for each SUBSCRIBE packet. */ + configASSERT( xSize == 1UL ); + xTopicFilterContext.xSubAckStatus = *pucPayload; + + if( xTopicFilterContext.xSubAckStatus != MQTTSubAckFailure ) + { + LogInfo( ( "Subscribed to the topic %s with maximum QoS %u.", + xTopicFilterContext.pcTopicFilter, + xTopicFilterContext.xSubAckStatus ) ); + } + + /* Make sure ACK packet identifier matches with Request packet identifier. */ + assert( globalSubscribePacketIdentifier == usPacketIdentifier ); + break; + + case MQTT_PACKET_TYPE_UNSUBACK: + LogInfo( ( "MQTT_PACKET_TYPE_UNSUBACK.\n\n" ) ); + /* Update the packet type received to UNSUBACK. */ + globalPacketTypeReceived = MQTT_PACKET_TYPE_UNSUBACK; + /* Make sure ACK packet identifier matches with Request packet identifier. */ + assert( globalUnsubscribePacketIdentifier == usPacketIdentifier ); + break; + + case MQTT_PACKET_TYPE_PINGRESP: + + /* Nothing to be done from application as library handles + * PINGRESP. */ + LogWarn( ( "PINGRESP should not be handled by the application " + "callback when using MQTT_ProcessLoop.\n\n" ) ); + break; + + case MQTT_PACKET_TYPE_PUBACK: + LogInfo( ( "PUBACK received for packet id %u.\n\n", + usPacketIdentifier ) ); + /* Cleanup publish packet when a PUBACK is received. */ + vCleanupOutgoingPublishWithPacketID( usPacketIdentifier ); + break; + + /* Any other packet type is invalid. */ + default: + LogError( ( "Unknown packet type received:(%02x).\n\n", + pxPacketInfo->type ) ); + } +} + +/*-----------------------------------------------------------*/ + +static BaseType_t handlePublishResend( MQTTContext_t * pxMqttContext ) +{ + BaseType_t xReturnStatus = pdPASS; + MQTTStatus_t eMqttStatus = MQTTSuccess; + uint8_t ucIndex = 0U; + + assert( outgoingPublishPackets != NULL ); + + /* Resend all the QoS1 publishes still in the array. These are the + * publishes that hasn't received a PUBACK. When a PUBACK is + * received, the publish is removed from the array. */ + for( ucIndex = 0U; ucIndex < MAX_OUTGOING_PUBLISHES; ucIndex++ ) + { + if( outgoingPublishPackets[ ucIndex ].packetId != MQTT_PACKET_ID_INVALID ) + { + outgoingPublishPackets[ ucIndex ].pubInfo.dup = true; + + LogInfo( ( "Sending duplicate PUBLISH with packet id %u.", + outgoingPublishPackets[ ucIndex ].packetId ) ); + eMqttStatus = MQTT_Publish( pxMqttContext, + &outgoingPublishPackets[ ucIndex ].pubInfo, + outgoingPublishPackets[ ucIndex ].packetId ); + + if( eMqttStatus != MQTTSuccess ) + { + LogError( ( "Sending duplicate PUBLISH for packet id %u " + " failed with status %s.", + outgoingPublishPackets[ ucIndex ].packetId, + MQTT_Status_strerror( eMqttStatus ) ) ); + xReturnStatus = pdFAIL; + break; + } + else + { + LogInfo( ( "Sent duplicate PUBLISH successfully for packet id %u.\n\n", + outgoingPublishPackets[ ucIndex ].packetId ) ); + } + } + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t EstablishMqttSession( MQTTContext_t * pxMqttContext, + NetworkContext_t * pxNetworkContext, + MQTTFixedBuffer_t * pxNetworkBuffer, + MQTTEventCallback_t eventCallback ) +{ + BaseType_t xReturnStatus = pdPASS; + MQTTStatus_t eMqttStatus = MQTTSuccess; + MQTTConnectInfo_t xConnectInfo = { 0 }; + TransportInterface_t xTransport = { 0 }; + bool sessionPresent = false; + + assert( pxMqttContext != NULL ); + assert( pxNetworkContext != NULL ); + + /* Initialize the mqtt context and network context. */ + ( void ) memset( pxMqttContext, 0U, sizeof( MQTTContext_t ) ); + ( void ) memset( pxNetworkContext, 0U, sizeof( NetworkContext_t ) ); + + + pxNetworkContext->pParams = &xSecureSocketsTransportParams; + + if( prvConnectToServerWithBackoffRetries( pxNetworkContext ) != TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + /* Log error to indicate connection failure after all + * reconnect attempts are over. */ + LogError( ( "Failed to connect to MQTT broker %.*s.", + strlen( democonfigMQTT_BROKER_ENDPOINT ), + democonfigMQTT_BROKER_ENDPOINT ) ); + xReturnStatus = pdFAIL; + } + else + { + /* Fill in Transport Interface send and receive function pointers. */ + xTransport.pNetworkContext = pxNetworkContext; + xTransport.send = SecureSocketsTransport_Send; + xTransport.recv = SecureSocketsTransport_Recv; + + /* Initialize MQTT library. */ + eMqttStatus = MQTT_Init( pxMqttContext, + &xTransport, + prvGetTimeMs, + eventCallback, + pxNetworkBuffer ); + + if( eMqttStatus != MQTTSuccess ) + { + xReturnStatus = pdFAIL; + LogError( ( "MQTT init failed with status %s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + } + else + { + /* Establish MQTT session by sending a CONNECT packet. */ + + /* Many fields not used in this demo so start with everything at 0. */ + ( void ) memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) ); + + /* Start with a clean session i.e. direct the MQTT broker to discard any + * previous session data. Also, establishing a connection with clean session + * will ensure that the broker does not store any data when this client + * gets disconnected. */ + xConnectInfo.cleanSession = true; + + /* The client identifier is used to uniquely identify this MQTT client to + * the MQTT broker. In a production device the identifier can be something + * unique, such as a device serial number. */ + xConnectInfo.pClientIdentifier = democonfigCLIENT_IDENTIFIER; + xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( democonfigCLIENT_IDENTIFIER ); + + /* Use the metrics string as username to report the OS and MQTT client version + * metrics to AWS IoT. */ + xConnectInfo.pUserName = AWS_IOT_METRICS_STRING; + xConnectInfo.userNameLength = AWS_IOT_METRICS_STRING_LENGTH; + /* Password for authentication is not used. */ + xConnectInfo.pPassword = NULL; + xConnectInfo.passwordLength = 0U; + + /* The maximum time interval in seconds which is allowed to elapse + * between two Control Packets. + * It is the responsibility of the Client to ensure that the interval between + * Control Packets being sent does not exceed the this Keep Alive value. In the + * absence of sending any other Control Packets, the Client MUST send a + * PINGREQ Packet. */ + xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS; + + /* Send MQTT CONNECT packet to broker. */ + eMqttStatus = MQTT_Connect( pxMqttContext, + &xConnectInfo, + NULL, + mqttexampleCONNACK_RECV_TIMEOUT_MS, + &sessionPresent ); + + if( eMqttStatus != MQTTSuccess ) + { + xReturnStatus = pdFAIL; + LogError( ( "Connection with MQTT broker failed with status %s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + } + else + { + LogInfo( ( "MQTT connection successfully established with broker.\n\n" ) ); + } + } + + if( xReturnStatus == pdPASS ) + { + /* Keep a flag for indicating if MQTT session is established. This + * flag will mark that an MQTT DISCONNECT has to be sent at the end + * of the demo even if there are intermediate failures. */ + mqttSessionEstablished = true; + } + + if( xReturnStatus == pdPASS ) + { + /* Check if session is present and if there are any outgoing publishes + * that need to resend. This is only valid if the broker is + * re-establishing a session which was already present. */ + if( sessionPresent == true ) + { + LogInfo( ( "An MQTT session with broker is re-established. " + "Resending unacked publishes." ) ); + + /* Handle all the resend of publish messages. */ + xReturnStatus = handlePublishResend( pxMqttContext ); + } + else + { + LogInfo( ( "A clean MQTT connection is established." + " Cleaning up all the stored outgoing publishes.\n\n" ) ); + + /* Clean up the outgoing publishes waiting for ack as this new + * connection doesn't re-establish an existing session. */ + vCleanupOutgoingPublishes(); + } + } + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t DisconnectMqttSession( MQTTContext_t * pxMqttContext, + NetworkContext_t * pxNetworkContext ) +{ + MQTTStatus_t eMqttStatus = MQTTSuccess; + BaseType_t xReturnStatus = pdPASS; + TransportSocketStatus_t xNetworkStatus; + + assert( pxMqttContext != NULL ); + assert( pxNetworkContext != NULL ); + + if( mqttSessionEstablished == true ) + { + /* Send DISCONNECT. */ + eMqttStatus = MQTT_Disconnect( pxMqttContext ); + + if( eMqttStatus != MQTTSuccess ) + { + LogError( ( "Sending MQTT DISCONNECT failed with status=%s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + xReturnStatus = pdFAIL; + } + } + + /* Close the network connection. */ + xNetworkStatus = SecureSocketsTransport_Disconnect( pxNetworkContext ); + + if( xNetworkStatus != TRANSPORT_SOCKET_STATUS_SUCCESS ) + { + LogError( ( "Disconnecting from SecureSocket failed with status=%u.", + xNetworkStatus ) ); + xReturnStatus = pdFAIL; + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t UnsubscribeFromTopic( MQTTContext_t * pxMqttContext, + const char * pcTopicFilter, + uint16_t usTopicFilterLength ) +{ + BaseType_t xReturnStatus = pdPASS; + MQTTStatus_t eMqttStatus; + MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; + + assert( pxMqttContext != NULL ); + assert( pcTopicFilter != NULL ); + assert( usTopicFilterLength > 0 ); + + /* Start with everything at 0. */ + ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); + + /* This example subscribes to only one topic and uses QOS1. */ + pSubscriptionList[ 0 ].qos = MQTTQoS1; + pSubscriptionList[ 0 ].pTopicFilter = pcTopicFilter; + pSubscriptionList[ 0 ].topicFilterLength = usTopicFilterLength; + + /* Generate packet identifier for the UNSUBSCRIBE packet. */ + globalUnsubscribePacketIdentifier = MQTT_GetPacketId( pxMqttContext ); + + /* Send UNSUBSCRIBE packet. */ + eMqttStatus = MQTT_Unsubscribe( pxMqttContext, + pSubscriptionList, + sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), + globalUnsubscribePacketIdentifier ); + + if( eMqttStatus != MQTTSuccess ) + { + LogError( ( "Failed to send UNSUBSCRIBE packet to broker with error = %s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + xReturnStatus = pdFAIL; + } + else + { + LogInfo( ( "UNSUBSCRIBE sent topic %.*s to broker.\n\n", + usTopicFilterLength, + pcTopicFilter ) ); + + /* Process incoming packet from the broker. Acknowledgment for unsubscription + * ( UNSUBACK ) will be received here. */ + xReturnStatus = prvWaitForPacket( pxMqttContext, MQTT_PACKET_TYPE_UNSUBACK ); + + if( xReturnStatus == pdFAIL ) + { + LogError( ( "UNSUBACK never arrived when unsubscribing to topic %s.", + pcTopicFilter ) ); + } + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t PublishToTopic( MQTTContext_t * pxMqttContext, + const char * pcTopicFilter, + int32_t topicFilterLength, + const char * pcPayload, + size_t payloadLength ) +{ + BaseType_t xReturnStatus = pdPASS; + MQTTStatus_t eMqttStatus = MQTTSuccess; + uint8_t ucPublishIndex = MAX_OUTGOING_PUBLISHES; + + assert( pxMqttContext != NULL ); + assert( pcTopicFilter != NULL ); + assert( topicFilterLength > 0 ); + + /* Get the next free index for the outgoing publish. All QoS1 outgoing + * publishes are stored until a PUBACK is received. These messages are + * stored for supporting a resend if a network connection is broken before + * receiving a PUBACK. */ + xReturnStatus = prvGetNextFreeIndexForOutgoingPublishes( &ucPublishIndex ); + + if( xReturnStatus == pdFAIL ) + { + LogError( ( "Unable to find a free spot for outgoing PUBLISH message.\n\n" ) ); + } + else + { + LogInfo( ( "the published payload:%.*s \r\n ", payloadLength, pcPayload ) ); + /* This example publishes to only one topic and uses QOS1. */ + outgoingPublishPackets[ ucPublishIndex ].pubInfo.qos = MQTTQoS1; + outgoingPublishPackets[ ucPublishIndex ].pubInfo.pTopicName = pcTopicFilter; + outgoingPublishPackets[ ucPublishIndex ].pubInfo.topicNameLength = topicFilterLength; + outgoingPublishPackets[ ucPublishIndex ].pubInfo.pPayload = pcPayload; + outgoingPublishPackets[ ucPublishIndex ].pubInfo.payloadLength = payloadLength; + + /* Get a new packet id. */ + outgoingPublishPackets[ ucPublishIndex ].packetId = MQTT_GetPacketId( pxMqttContext ); + + /* Send PUBLISH packet. */ + eMqttStatus = MQTT_Publish( pxMqttContext, + &outgoingPublishPackets[ ucPublishIndex ].pubInfo, + outgoingPublishPackets[ ucPublishIndex ].packetId ); + + if( eMqttStatus != MQTTSuccess ) + { + LogError( ( "Failed to send PUBLISH packet to broker with error = %s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + vCleanupOutgoingPublishAt( ucPublishIndex ); + xReturnStatus = pdFAIL; + } + else + { + LogInfo( ( "PUBLISH sent for topic %.*s to broker with packet ID %u.\n\n", + topicFilterLength, + pcTopicFilter, + outgoingPublishPackets[ ucPublishIndex ].packetId ) ); + + /* Calling MQTT_ProcessLoop to process incoming publish echo, since + * application subscribed to the same topic the broker will send + * publish message back to the application. This function also + * sends ping request to broker if MQTT_KEEP_ALIVE_INTERVAL_SECONDS + * has expired since the last MQTT packet sent and receive + * ping responses. */ + eMqttStatus = MQTT_ProcessLoop( pxMqttContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); + + if( eMqttStatus != MQTTSuccess ) + { + LogWarn( ( "MQTT_ProcessLoop returned with status = %s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + } + } + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +BaseType_t ProcessLoop( MQTTContext_t * pxMqttContext, + uint32_t ulTimeoutMs ) +{ + BaseType_t xReturnStatus = pdFAIL; + MQTTStatus_t eMqttStatus = MQTTSuccess; + + eMqttStatus = MQTT_ProcessLoop( pxMqttContext, ulTimeoutMs ); + + if( eMqttStatus != MQTTSuccess ) + { + LogWarn( ( "MQTT_ProcessLoop returned with status = %s.", + MQTT_Status_strerror( eMqttStatus ) ) ); + } + else + { + LogDebug( ( "MQTT_ProcessLoop successful." ) ); + xReturnStatus = pdPASS; + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +static uint32_t prvGetTimeMs( void ) +{ + TickType_t xTickCount = 0; + uint32_t ulTimeMs = 0UL; + + /* Get the current tick count. */ + xTickCount = xTaskGetTickCount(); + + /* Convert the ticks to milliseconds. */ + ulTimeMs = ( uint32_t ) xTickCount * MILLISECONDS_PER_TICK; + + /* Reduce ulGlobalEntryTimeMs from obtained time so as to always return the + * elapsed time in the application. */ + ulTimeMs = ( uint32_t ) ( ulTimeMs - ulGlobalEntryTimeMs ); + + return ulTimeMs; +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.h b/bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.h new file mode 100644 index 0000000..3b74506 --- /dev/null +++ b/bsp/aws_libraries/demos/common/mqtt_demo_helpers/mqtt_demo_helpers.h @@ -0,0 +1,172 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef MQTT_DEMO_HELPERS_H_ +#define MQTT_DEMO_HELPERS_H_ + +/* MQTT API header. */ +#include "core_mqtt.h" + +/* Transport interface implementation include header for TLS. */ +#include "transport_secure_sockets.h" + +/* Include header for connection configurations. */ +#include "aws_clientcredential.h" + +/*------------- Demo configurations -------------------------*/ + +/** Note: The device client certificate and private key credentials are + * obtained by the transport interface implementation (with Secure Sockets) + * from the demos/include/aws_clientcredential_keys.h file. + * + * The following macros SHOULD be defined for this demo which uses both server + * and client authentications for TLS session: + * - keyCLIENT_CERTIFICATE_PEM for client certificate. + * - keyCLIENT_PRIVATE_KEY_PEM for client private key. + */ + +#ifndef democonfigMQTT_BROKER_ENDPOINT + #define democonfigMQTT_BROKER_ENDPOINT clientcredentialMQTT_BROKER_ENDPOINT +#endif + +#ifndef democonfigCLIENT_IDENTIFIER + +/** + * @brief The MQTT client identifier used in this example. Each client identifier + * must be unique so edit as required to ensure no two clients connecting to the + * same broker use the same client identifier. + */ + #define democonfigCLIENT_IDENTIFIER clientcredentialIOT_THING_NAME +#endif + +#ifndef democonfigMQTT_BROKER_PORT + +/** + * @brief The port to use for the demo. + */ + #define democonfigMQTT_BROKER_PORT clientcredentialMQTT_BROKER_PORT +#endif + +/*-----------------------------------------------------------*/ + +/** + * @brief Establish a MQTT connection. + * + * @param[in] pxContext The memory for the MQTTContext_t that will be used for the + * MQTT connection. + * @param[in] pxNetContext The memory for the NetworkContext_t required for the + * MQTT connection. + * @param[in] pxNetworkBuffer The buffer space for initializing the @p pxContext MQTT + * context used in the MQTT connection. + * @param[in] appCallback The callback function used to receive incoming + * publishes and incoming acks from MQTT library. + * + * @return The status of the final connection attempt. + */ +BaseType_t EstablishMqttSession( MQTTContext_t * pxContext, + NetworkContext_t * pxNetContext, + MQTTFixedBuffer_t * pxNetworkBuffer, + MQTTEventCallback_t eventCallback ); + +/** + * @brief Invoked by the event callback to handle SUBACK and UNSUBACK packets + * from the broker. + * + * @param[in] pxPacketInfo Packet Info pointer for the incoming packet. + * @param[in] usPacketIdentifier Packet identifier of the incoming packet. + */ +void vHandleOtherIncomingPacket( MQTTPacketInfo_t * pxPacketInfo, + uint16_t usPacketIdentifier ); + +/** + * @brief Close the MQTT connection. + * + * @param[in] pxContext The MQTT context for the MQTT connection to close. + * + * @return pdPASS if DISCONNECT was successfully sent; + * pdFAIL otherwise. + */ +BaseType_t DisconnectMqttSession( MQTTContext_t * pxContext, + NetworkContext_t * pxNetContext ); + +/** + * @brief Subscribe to a MQTT topic filter. + * + * @param[in] pxContext The MQTT context for the MQTT connection. + * @param[in] pcTopicFilter Pointer to the shadow topic buffer. + * @param[in] usTopicFilterLength Indicates the length of the shadow + * topic buffer. + * + * @return pdPASS if SUBSCRIBE was successfully sent; + * pdFAIL otherwise. + */ +BaseType_t SubscribeToTopic( MQTTContext_t * pxContext, + const char * pcTopicFilter, + uint16_t usTopicFilterLength ); + +/** + * @brief Sends an MQTT UNSUBSCRIBE to unsubscribe from the shadow + * topic. + * + * @param[in] pxContext The MQTT context for the MQTT connection. + * @param[in] pcTopicFilter Pointer to the shadow topic buffer. + * @param[in] usTopicFilterLength Indicates the length of the shadow + * topic buffer. + * + * @return pdPASS if UNSUBSCRIBE was successfully sent; + * pdFAIL otherwise. + */ +BaseType_t UnsubscribeFromTopic( MQTTContext_t * pxContext, + const char * pcTopicFilter, + uint16_t usTopicFilterLength ); + +/** + * @brief Publish a message to a MQTT topic. + * + * @param[in] pxContext The MQTT context for the MQTT connection. + * @param[in] pcTopicFilter Points to the topic. + * @param[in] topicFilterLength The length of the topic. + * @param[in] pcPayload Points to the payload. + * @param[in] payloadLength The length of the payload. + * + * @return pdPASS if PUBLISH was successfully sent; + * pdFAIL otherwise. + */ +BaseType_t PublishToTopic( MQTTContext_t * pxContext, + const char * pcTopicFilter, + int32_t topicFilterLength, + const char * pcPayload, + size_t payloadLength ); + +/** + * @brief Invoke the core MQTT library's process loop function. + * + * @param[in] pxMqttContext The MQTT context for the MQTT connection. + * @param[in] ulTimeoutMs Minimum time for the loop to run, if no error occurs. + * + * @return pdPASS if process loop was successful; + * pdFAIL otherwise. + */ +BaseType_t ProcessLoop( MQTTContext_t * pxMqttContext, + uint32_t ulTimeoutMs ); + +#endif /* ifndef MQTT_DEMO_HELPERS_H_ */ diff --git a/bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.c b/bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.c new file mode 100644 index 0000000..f674a14 --- /dev/null +++ b/bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.c @@ -0,0 +1,171 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file mqtt_subscription_manager.c + * @brief Functions for managing MQTT subscriptions. + */ + +/* Standard includes. */ +#include + +/* Subscription manager header include. */ +#include "mqtt_subscription_manager.h" + + +bool SubscriptionManager_AddSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength, + IncomingPubCallback_t pxIncomingPublishCallback, + void * pvIncomingPublishCallbackContext ) +{ + int32_t lIndex = 0; + size_t xAvailableIndex = SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; + bool xReturnStatus = false; + + if( ( pxSubscriptionList == NULL ) || + ( pcTopicFilterString == NULL ) || + ( usTopicFilterLength == 0U ) || + ( pxIncomingPublishCallback == NULL ) ) + { + LogError( ( "Invalid parameter. pxSubscriptionList=%p, pcTopicFilterString=%p," + " usTopicFilterLength=%u, pxIncomingPublishCallback=%p.", + pxSubscriptionList, + pcTopicFilterString, + ( unsigned int ) usTopicFilterLength, + pxIncomingPublishCallback ) ); + } + else + { + /* Start at end of array, so that we will insert at the first available index. + * Scans backwards to find duplicates. */ + for( lIndex = ( int32_t ) SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS - 1; lIndex >= 0; lIndex-- ) + { + if( pxSubscriptionList[ lIndex ].usFilterStringLength == 0 ) + { + xAvailableIndex = lIndex; + } + else if( ( pxSubscriptionList[ lIndex ].usFilterStringLength == usTopicFilterLength ) && + ( strncmp( pcTopicFilterString, pxSubscriptionList[ lIndex ].pcSubscriptionFilterString, ( size_t ) usTopicFilterLength ) == 0 ) ) + { + /* If a subscription already exists, don't do anything. */ + if( ( pxSubscriptionList[ lIndex ].pxIncomingPublishCallback == pxIncomingPublishCallback ) && + ( pxSubscriptionList[ lIndex ].pvIncomingPublishCallbackContext == pvIncomingPublishCallbackContext ) ) + { + LogWarn( ( "Subscription already exists.\n" ) ); + xAvailableIndex = SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; + xReturnStatus = true; + break; + } + } + } + + if( xAvailableIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS ) + { + pxSubscriptionList[ xAvailableIndex ].pcSubscriptionFilterString = pcTopicFilterString; + pxSubscriptionList[ xAvailableIndex ].usFilterStringLength = usTopicFilterLength; + pxSubscriptionList[ xAvailableIndex ].pxIncomingPublishCallback = pxIncomingPublishCallback; + pxSubscriptionList[ xAvailableIndex ].pvIncomingPublishCallbackContext = pvIncomingPublishCallbackContext; + xReturnStatus = true; + } + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +void SubscriptionManager_RemoveSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength ) +{ + int32_t lIndex = 0; + + if( ( pxSubscriptionList == NULL ) || + ( pcTopicFilterString == NULL ) || + ( usTopicFilterLength == 0U ) ) + { + LogError( ( "Invalid parameter. pxSubscriptionList=%p, pcTopicFilterString=%p," + " usTopicFilterLength=%u.", + pxSubscriptionList, + pcTopicFilterString, + ( unsigned int ) usTopicFilterLength ) ); + } + else + { + for( lIndex = 0; lIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; lIndex++ ) + { + if( pxSubscriptionList[ lIndex ].usFilterStringLength == usTopicFilterLength ) + { + if( strncmp( pxSubscriptionList[ lIndex ].pcSubscriptionFilterString, pcTopicFilterString, usTopicFilterLength ) == 0 ) + { + memset( &( pxSubscriptionList[ lIndex ] ), 0x00, sizeof( SubscriptionElement_t ) ); + } + } + } + } +} + +/*-----------------------------------------------------------*/ + +bool SubscriptionManager_HandleIncomingPublishes( SubscriptionElement_t * pxSubscriptionList, + MQTTPublishInfo_t * pxPublishInfo ) +{ + int32_t lIndex = 0; + bool isMatched = false, publishHandled = false; + + if( ( pxSubscriptionList == NULL ) || + ( pxPublishInfo == NULL ) ) + { + LogError( ( "Invalid parameter. pxSubscriptionList=%p, pxPublishInfo=%p,", + pxSubscriptionList, + pxPublishInfo ) ); + } + else + { + for( lIndex = 0; lIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; lIndex++ ) + { + if( pxSubscriptionList[ lIndex ].usFilterStringLength > 0 ) + { + MQTT_MatchTopic( pxPublishInfo->pTopicName, + pxPublishInfo->topicNameLength, + pxSubscriptionList[ lIndex ].pcSubscriptionFilterString, + pxSubscriptionList[ lIndex ].usFilterStringLength, + &isMatched ); + + if( isMatched == true ) + { + pxSubscriptionList[ lIndex ].pxIncomingPublishCallback( pxSubscriptionList[ lIndex ].pvIncomingPublishCallbackContext, + pxPublishInfo ); + + publishHandled = true; + } + } + } + } + + return publishHandled; +} diff --git a/bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.h b/bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.h new file mode 100644 index 0000000..0bf080f --- /dev/null +++ b/bsp/aws_libraries/demos/common/mqtt_subscription_manager/mqtt_subscription_manager.h @@ -0,0 +1,145 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file mqtt_subscription_manager.h + * @brief Functions for managing MQTT subscriptions. + */ +#ifndef MQTT_SUBSCRIPTION_MANAGER_H +#define MQTT_SUBSCRIPTION_MANAGER_H + +/**************************************************/ +/******* DO NOT CHANGE the following order ********/ +/**************************************************/ + +/* Logging related header files are required to be included in the following order: + * 1. Include the header file "logging_levels.h". + * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. + * 3. Include the header file "logging_stack.h". + */ + +/* Include header that defines log levels. */ +#include "logging_levels.h" + +/* Logging configuration for the Subscription Manager module. */ +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME "Subscription Manager" +#endif +#ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL LOG_ERROR +#endif + +#include "logging_stack.h" + +/* core MQTT include. */ +#include "core_mqtt.h" + +/** + * @brief Maximum number of subscriptions maintained by the subscription manager + * simultaneously in a list. + */ +#ifndef SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS + #define SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS 10U +#endif + +/** + * @brief Callback function called when receiving a publish. + * + * @param[in] pvIncomingPublishCallbackContext The incoming publish callback context. + * @param[in] pxPublishInfo Deserialized publish information. + */ +typedef void (* IncomingPubCallback_t )( void * pvIncomingPublishCallbackContext, + MQTTPublishInfo_t * pxPublishInfo ); + +/** + * @brief An element in the list of subscriptions. + * + * This subscription manager implementation expects that the array of the + * subscription elements used for storing subscriptions to be initialized to 0. + * + * @note This implementation allows multiple tasks to subscribe to the same topic. + * In this case, another element is added to the subscription list, differing + * in the intended publish callback. Also note that the topic filters are not + * copied in the subscription manager and hence the topic filter strings need to + * stay in scope until unsubscribed. + */ +typedef struct subscriptionElement +{ + IncomingPubCallback_t pxIncomingPublishCallback; + void * pvIncomingPublishCallbackContext; + uint16_t usFilterStringLength; + const char * pcSubscriptionFilterString; +} SubscriptionElement_t; + +/** + * @brief Add a subscription to the subscription list. + * + * @note Multiple tasks can be subscribed to the same topic with different + * context-callback pairs. However, a single context-callback pair may only be + * associated to the same topic filter once. + * + * @param[in] pxSubscriptionList The pointer to the subscription list array. + * @param[in] pcTopicFilterString Topic filter string of subscription. + * @param[in] usTopicFilterLength Length of topic filter string. + * @param[in] pxIncomingPublishCallback Callback function for the subscription. + * @param[in] pvIncomingPublishCallbackContext Context for the subscription callback. + * + * @return `true` if subscription added or exists, `false` if insufficient memory. + */ +bool SubscriptionManager_AddSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength, + IncomingPubCallback_t pxIncomingPublishCallback, + void * pvIncomingPublishCallbackContext ); + +/** + * @brief Remove a subscription from the subscription list. + * + * @note If the topic filter exists multiple times in the subscription list, + * then every instance of the subscription will be removed. + * + * @param[in] pxSubscriptionList The pointer to the subscription list array. + * @param[in] pcTopicFilterString Topic filter of subscription. + * @param[in] usTopicFilterLength Length of topic filter. + */ +void SubscriptionManager_RemoveSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength ); + +/** + * @brief Handle incoming publishes by invoking the callbacks registered + * for the incoming publish's topic filter. + * + * @param[in] pxSubscriptionList The pointer to the subscription list array. + * @param[in] pxPublishInfo Info of incoming publish. + * + * @return `true` if an application callback could be invoked; + * `false` otherwise. + */ +bool SubscriptionManager_HandleIncomingPublishes( SubscriptionElement_t * pxSubscriptionList, + MQTTPublishInfo_t * pxPublishInfo ); + +#endif /* MQTT_SUBSCRIPTION_MANAGER_H */ diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipAnyScalar.c b/bsp/aws_libraries/demos/common/ota_demo_helpers/ota_application_version.c similarity index 61% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipAnyScalar.c rename to bsp/aws_libraries/demos/common/ota_demo_helpers/ota_application_version.c index db14807..8dc8f26 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipAnyScalar.c +++ b/bsp/aws_libraries/demos/common/ota_demo_helpers/ota_application_version.c @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * FreeRTOS V202012.00 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -20,25 +20,24 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "skipGeneric.h" - -/* - * This function is a replacement for the function of the same name from core_json.c. - * Please see core_json.c for documentation. +/** + * @file ota_application_version.c + * + * @brief This file defines the appFirmwareVersion variable that is required to + * build the OTA library. This variable has a dedicated file so that it can be + * referenced by multiple OTA demos. */ -bool skipAnyScalar( const char * buf, - size_t * start, - size_t max ) -{ - /* min argument is 1 for a single character scalar like 0, - * or 2 for an empty double-quoted string, i.e., "". */ - size_t min = 1; - - if( ( *start < max ) && ( buf[ *start ] == '"' ) ) - { - min = 2; - } +/* Includes the OTA Application version number. */ +#include "ota_appversion32.h" +#include "ota_config.h" - return skipGeneric( buf, start, max, min ); -} +/* Definition of the appFirmwareVersion variable that is used by the OTA + * library and is declared in the ota_appversion32.h file. The values for these + * firmware versions are set in the ota_demo_config.h file. */ +const AppVersion32_t appFirmwareVersion = +{ + .u.x.major = APP_VERSION_MAJOR, + .u.x.minor = APP_VERSION_MINOR, + .u.x.build = APP_VERSION_BUILD +}; diff --git a/bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.c b/bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.c new file mode 100644 index 0000000..5f9dce7 --- /dev/null +++ b/bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.c @@ -0,0 +1,103 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file pkcs11_helpers.c + * @brief Implementation of the helper functions for accessing PKCS11 module functionality. + */ + +/* Include corePKCS11 config file. */ +#include "core_pkcs11_config.h" + +/* Include PKCS11 headers. */ +#include "core_pkcs11.h" +#include "pkcs11.h" + +/* Include header. */ +#include "pkcs11_helpers.h" + +/*-----------------------------------------------------------*/ + +BaseType_t xPkcs11GenerateRandomNumber( uint8_t * pusRandomNumBuffer, + size_t xBufferLength ) +{ + BaseType_t xStatus = pdPASS; + CK_RV xResult = CKR_OK; + CK_FUNCTION_LIST_PTR pxFunctionList = NULL; + CK_SESSION_HANDLE xSession = CK_INVALID_HANDLE; + + if( ( pusRandomNumBuffer == NULL ) || ( xBufferLength == 0U ) ) + { + LogError( ( "Cannot generate random number. Invalid parameters passed. " + "buffer=%p,bufferLen=%lu", pusRandomNumBuffer, xBufferLength ) ); + xStatus = pdFAIL; + } + + if( xStatus == pdPASS ) + { + /* Get list of functions supported by the PKCS #11 port. */ + xResult = C_GetFunctionList( &pxFunctionList ); + + if( ( xResult != CKR_OK ) || ( pxFunctionList == NULL ) ) + { + LogError( ( "Failed to generate random number. " + "PKCS #11 API, C_GetFunctionList, failed." ) ); + xStatus = pdFAIL; + } + } + + if( xStatus == pdPASS ) + { + /* Initialize PKCS #11 module and create a new session. */ + xResult = xInitializePkcs11Session( &xSession ); + + if( ( xResult != CKR_OK ) || ( xSession == CK_INVALID_HANDLE ) ) + { + LogError( ( "Failed to generate random number. " + "Failed to initialize PKCS #11 session." ) ); + xStatus = pdFAIL; + } + } + + if( xStatus == pdPASS ) + { + if( pxFunctionList->C_GenerateRandom( xSession, + pusRandomNumBuffer, + xBufferLength ) != CKR_OK ) + { + xStatus = pdFAIL; + LogError( ( "Failed to generate random number. " + "PKCS #11 API, C_GenerateRandom, failed to generate random number." ) ); + } + } + + if( xStatus == pdPASS ) + { + if( pxFunctionList->C_CloseSession( xSession ) != CKR_OK ) + { + xStatus = pdFAIL; + LogError( ( " Failed to close PKCS #11 session after generating random number." ) ); + } + } + + return xStatus; +} diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipGeneric.c b/bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.h similarity index 54% rename from kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipGeneric.c rename to bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.h index 4d08029..63a9246 100644 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/test/cbmc/stubs/skipGeneric.c +++ b/bsp/aws_libraries/demos/common/pkcs11_helpers/pkcs11_helpers.h @@ -1,5 +1,5 @@ /* - * coreJSON v3.0.0 + * FreeRTOS V202012.00 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -20,40 +20,35 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "skipGeneric.h" +#ifndef PKCS11_HELPERS_H_ +#define PKCS11_HELPERS_H_ /** - * See skipGeneric.h for docs - * - * Advance buffer index beyond some minimum value. + * @file pkcs11_helpers.h + * @brief Helper functions for accessing PKCS11 module functionality. */ -static bool skipGeneric( const char * buf, - size_t * start, - size_t max, - size_t min ) -{ - bool ret = false; - assert( ( buf != NULL ) && ( start != NULL ) ); - assert( min > 0 ); +/* FreeRTOS include. */ +#include "FreeRTOS.h" - if( *start < max ) - { - assert( __CPROVER_r_ok( ( buf + *start ), ( max - *start ) ) ); +/*-----------------------------------------------------------*/ - if( nondet_bool() && ( min <= max ) ) - { - size_t x; - __CPROVER_assume( x >= min ); - __CPROVER_assume( x <= max ); +/** + * @brief Utility function to generate a random number using the + * PKCS11 module. + * + * This is a wrapper function for initiating a PKCS11 session, + * calling the C_GenerateRandom API function to generate a random + * number and closing the PKCS11 session. + * + * @param[in, out] pusRandomNumBuffer The buffer to store the generated random number. + * @param[in] xBufferLength The size of the @p pusRandomNumBuffer buffer. + * + * @return pdPASS if random number generation was successful; otherwise + * pdFAIL to indicate failure. + */ +BaseType_t xPkcs11GenerateRandomNumber( uint8_t * pusRandomNumBuffer, + size_t xBufferLength ); - if( ( *start + x ) <= max ) - { - *start = *start + x; - ret = true; - } - } - } - return ret; -} +#endif /* ifndef PKCS11_HELPERS_H_ */ diff --git a/bsp/aws_libraries/demos/coreMQTT_Agent/mqtt_agent_task.c b/bsp/aws_libraries/demos/coreMQTT_Agent/mqtt_agent_task.c new file mode 100644 index 0000000..ab07d92 --- /dev/null +++ b/bsp/aws_libraries/demos/coreMQTT_Agent/mqtt_agent_task.c @@ -0,0 +1,1037 @@ +/* + * FreeRTOS V202104.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* + * This demo creates multiple tasks, all of which use the MQTT agent API to + * communicate with an MQTT broker through the same MQTT connection. + * + * This file contains the initial task created after the TCP/IP stack connects + * to the network. The task: + * + * 1) Connects to the MQTT broker. + * 2) Creates the other demo tasks, in accordance with the #defines set in + * demo_config.h. For example, if demo_config.h contains the following + * setting: + * + * #define democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE 3 + * + * then the initial task will create three instances of the task + * implemented in simple_sub_pub_demo.c. See the comments at the top + * of that file for more information. + * + * 3) After creating the demo tasks the initial task will create the MQTT + * agent task. + */ + + +/* Standard includes. */ +#include +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "queue.h" +#include "task.h" + +/* Demo Specific configs. */ +#include "mqtt_agent_demo_config.h" + +/* MQTT agent include. */ +#include "core_mqtt_agent.h" + +/* MQTT Agent ports. */ +#include "freertos_agent_message.h" +#include "freertos_command_pool.h" + +/* Exponential backoff retry include. */ +#include "backoff_algorithm.h" + +/* Include PKCS11 helpers header. */ +#include "pkcs11_helpers.h" + +/* Subscription manager header include. */ +#include "subscription_manager.h" + +/* Transport interface implementation include header for TLS. */ +#include "transport_secure_sockets.h" + +/* Credentials for the MQTT broker endpoint. */ +#include "aws_clientcredential.h" + +/* Include header for root CA certificates. */ +#include "iot_default_root_certificates.h" + +/* Include AWS IoT metrics macros header. */ +#include "aws_iot_metrics.h" + +/** + * These configuration settings are required to run the demo. + */ +#ifndef democonfigCLIENT_IDENTIFIER + +/** + * @brief The MQTT client identifier used in this example. Each client identifier + * must be unique so edit as required to ensure no two clients connecting to the + * same broker use the same client identifier. + */ + #define democonfigCLIENT_IDENTIFIER clientcredentialIOT_THING_NAME +#endif + +/* Provide default values for undefined configs. */ +#ifndef democonfigMQTT_BROKER_ENDPOINT + #define democonfigMQTT_BROKER_ENDPOINT clientcredentialMQTT_BROKER_ENDPOINT +#endif + +#ifndef democonfigMQTT_BROKER_PORT + #define democonfigMQTT_BROKER_PORT clientcredentialMQTT_BROKER_PORT +#endif + +#ifndef democonfigROOT_CA_PEM + #define democonfigROOT_CA_PEM tlsATS1_ROOT_CERTIFICATE_PEM +#endif + +/* This demo uses compile time options to select the demo tasks to created. + * Ensure the compile time options are defined. These should be defined in + * demo_config.h. */ +#if !defined( democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE ) || ( democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE < 1 ) + #error Please set democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE to the number of tasks to create in vStartSimpleSubscribePublishTask(). +#endif + +#if ( democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE > 0 ) && !defined( democonfigSIMPLE_SUB_PUB_TASK_STACK_SIZE ) + #error Please define democonfigSIMPLE_SUB_PUB_TASK_STACK_SIZE in demo_config.h to set the stack size (in words, not bytes) for the tasks created by vStartSimpleSubscribePublishTask(). +#endif + +/** + * @brief Dimensions the buffer used to serialize and deserialize MQTT packets. + * @note Specified in bytes. Must be large enough to hold the maximum + * anticipated MQTT payload. + */ +#ifndef MQTT_AGENT_NETWORK_BUFFER_SIZE + #define MQTT_AGENT_NETWORK_BUFFER_SIZE ( 5000 ) +#endif + +/** + * @brief The length of the queue used to hold commands for the agent. + */ +#ifndef MQTT_AGENT_COMMAND_QUEUE_LENGTH + #define MQTT_AGENT_COMMAND_QUEUE_LENGTH ( 10 ) +#endif + +/** + * @brief Length of client identifier. + */ +#define democonfigCLIENT_IDENTIFIER_LENGTH ( ( uint16_t ) ( sizeof( democonfigCLIENT_IDENTIFIER ) - 1 ) ) + +/** + * @brief Length of MQTT server host name. + */ +#define democonfigBROKER_ENDPOINT_LENGTH ( ( uint16_t ) ( sizeof( democonfigMQTT_BROKER_ENDPOINT ) - 1 ) ) + +/** + * These configuration settings are required to run the demo. + */ + +/** + * @brief Timeout for receiving CONNACK after sending an MQTT CONNECT packet. + * Defined in milliseconds. + */ +#define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 1000U ) + +/** + * @brief The maximum number of retries for network operation with server. + */ +#define RETRY_MAX_ATTEMPTS ( 5U ) + +/** + * @brief The maximum back-off delay (in milliseconds) for retrying failed operation + * with server. + */ +#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) + +/** + * @brief The base back-off delay (in milliseconds) to use for network operation retry + * attempts. + */ +#define RETRY_BACKOFF_BASE_MS ( 500U ) + +/** + * @brief The maximum time interval in seconds which is allowed to elapse + * between two Control Packets. + * + * It is the responsibility of the Client to ensure that the interval between + * Control Packets being sent does not exceed the this Keep Alive value. In the + * absence of sending any other Control Packets, the Client MUST send a + * PINGREQ Packet. + *//*_RB_ Move to be the responsibility of the agent. */ +#define mqttexampleKEEP_ALIVE_INTERVAL_SECONDS ( 60U ) + +/** + * @brief Socket send and receive timeouts to use. Specified in milliseconds. + */ +#define mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ( 750 ) + +/** + * @brief Used to convert times to/from ticks and milliseconds. + */ +#define mqttexampleMILLISECONDS_PER_SECOND ( 1000U ) +#define mqttexampleMILLISECONDS_PER_TICK ( mqttexampleMILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) + +/*-----------------------------------------------------------*/ + +/** + * @brief Each compilation unit that consumes the NetworkContext must define it. + * It should contain a single pointer to the type of your desired transport. + * When using multiple transports in the same compilation unit, define this pointer as void *. + * + * @note Transport stacks are defined in amazon-freertos/libraries/abstractions/transport/secure_sockets/transport_secure_sockets.h. + */ +struct NetworkContext +{ + SecureSocketsTransportParams_t * pParams; +}; + +/** + * @brief Parameters for subscribe-publish tasks. + */ +struct DemoParams +{ + uint32_t ulTaskNumber; + bool xSuccess; +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Initializes an MQTT Agent context, including transport interface, + * network buffer, and publish callback. + * + * @return `MQTTSuccess` if the initialization succeeds, else `MQTTBadParameter`. + */ +static MQTTStatus_t prvMQTTAgentInit( void ); + +/** + * @brief Sends an MQTT Connect packet over the already connected TCP socket. + * + * @param[in] pxMQTTContext MQTT context pointer. + * @param[in] xCleanSession If a clean session should be established. + * + * @return `MQTTSuccess` if connection succeeds, else appropriate error code + * from MQTT_Connect. + */ +static MQTTStatus_t prvMQTTConnect( bool xCleanSession ); + +/** + * @brief Calculate and perform an exponential backoff with jitter delay for + * the next retry attempt of a failed network operation with the server. + * + * The function generates a random number, calculates the next backoff period + * with the generated random number, and performs the backoff delay operation if the + * number of retries have not exhausted. + * + * @note The PKCS11 module is used to generate the random number as it allows access + * to a True Random Number Generator (TRNG) if the vendor platform supports it. + * It is recommended to seed the random number generator with a device-specific entropy + * source so that probability of collisions from devices in connection retries is mitigated. + * + * @note The backoff period is calculated using the backoffAlgorithm library. + * + * @param[in, out] pxRetryAttempts The context to use for backoff period calculation + * with the backoffAlgorithm library. + * + * @return pdPASS if calculating the backoff period was successful; otherwise pdFAIL + * if there was failure in random number generation OR all retry attempts had exhausted. + */ +static BaseType_t prvBackoffForRetry( BackoffAlgorithmContext_t * pxRetryParams ); + +/** + * @brief Connect a TCP socket to the MQTT broker. + * + * @param[in] pxNetworkContext Network context. + * + * @return `pdPASS` if connection succeeds, else `pdFAIL`. + */ +static BaseType_t prvSocketConnect( NetworkContext_t * pxNetworkContext ); + +/** + * @brief Disconnect a TCP connection. + * + * @param[in] pxNetworkContext Network context. + * + * @return `pdPASS` if disconnect succeeds, else `pdFAIL`. + */ +static BaseType_t prvSocketDisconnect( NetworkContext_t * pxNetworkContext ); + +/** + * @brief Fan out the incoming publishes to the callbacks registered by different + * tasks. If there are no callbacks registered for the incoming publish, it will be + * passed to the unsolicited publish handler. + * + * @param[in] pMqttAgentContext Agent context. + * @param[in] packetId Packet ID of publish. + * @param[in] pxPublishInfo Info of incoming publish. + */ +static void prvIncomingPublishCallback( MQTTAgentContext_t * pMqttAgentContext, + uint16_t packetId, + MQTTPublishInfo_t * pxPublishInfo ); + +/** + * @brief Function to attempt to resubscribe to the topics already present in the + * subscription list. + * + * This function will be invoked when this demo requests the broker to + * reestablish the session and the broker cannot do so. This function will + * enqueue commands to the MQTT Agent queue and will be processed once the + * command loop starts. + * + * @return `MQTTSuccess` if adding subscribes to the command queue succeeds, else + * appropriate error code from MQTTAgent_Subscribe. + * */ +static MQTTStatus_t prvHandleResubscribe( void ); + +/** + * @brief Passed into MQTTAgent_Subscribe() as the callback to execute when the + * broker ACKs the SUBSCRIBE message. This callback implementation is used for + * handling the completion of resubscribes. Any topic filter failed to resubscribe + * will be removed from the subscription list. + * + * See https://freertos.org/mqtt/mqtt-agent-demo.html#example_mqtt_api_call + * + * @param[in] pxCommandContext Context of the initial command. + * @param[in] pxReturnInfo The result of the command. + */ +static void prvSubscriptionCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ); + +/** + * @brief Task used to run the MQTT agent. In this example the first task that + * is created is responsible for creating all the other demo tasks. Then, + * rather than create prvMQTTAgentTask() as a separate task, it simply calls + * prvMQTTAgentTask() to become the agent task itself. + * + * This task calls MQTTAgent_CommandLoop() in a loop, until MQTTAgent_Terminate() + * is called. If an error occurs in the command loop, then it will reconnect the + * TCP and MQTT connections. + * + * @param[in] pvParameters Parameters as passed at the time of task creation. Not + * used in this example. + */ +static void prvMQTTAgentTask( void * pvParameters ); + +/** + * @brief The main task used in the MQTT demo. + * + * This task creates the network connection and all other demo tasks. Then, + * rather than create prvMQTTAgentTask() as a separate task, it simply calls + * prvMQTTAgentTask() to become the agent task itself. + * + * @param[in] pvParameters Parameters as passed at the time of task creation. Not + * used in this example. + * + * @return EXIT_SUCCESS if demo completes successfully, else EXIT_FAILURE. + */ +static int prvConnectAndCreateDemoTasks( void * pvParameters ); + +/** + * @brief The timer query function provided to the MQTT context. + * + * @return Time in milliseconds. + */ +static uint32_t prvGetTimeMs( void ); + +/** + * @brief Connects a TCP socket to the MQTT broker, then creates and MQTT + * connection to the same. + * + * @param[in] xCreateCleanSession Whether to create a clean session. + */ +static BaseType_t prvConnectToMQTTBroker( bool xCreateCleanSession ); + +/* + * Function that starts the tasks demonstrated by this project. + */ +extern void vStartSimpleSubscribePublishTask( uint32_t ulTaskNumber, + configSTACK_DEPTH_TYPE uxStackSize, + UBaseType_t uxPriority, + struct DemoParams * pxParams ); + +/*-----------------------------------------------------------*/ + +/** + * @brief The network context used by the MQTT library transport interface. + * See https://www.freertos.org/network-interface.html + */ +static NetworkContext_t xNetworkContext; + +/** + * @brief The parameters for the network context using a TLS channel. + */ +static SecureSocketsTransportParams_t secureSocketsTransportParams; + +/** + * @brief Global entry time into the application to use as a reference timestamp + * in the #prvGetTimeMs function. #prvGetTimeMs will always return the difference + * between the current time and the global entry time. This will reduce the chances + * of overflow for the 32 bit unsigned integer used for holding the timestamp. + */ +static uint32_t ulGlobalEntryTimeMs; + +/** + * @brief Global MQTT Agent context used by every task. + */ +MQTTAgentContext_t xGlobalMqttAgentContext; + +/** + * @brief Network buffer for coreMQTT. + */ +static uint8_t xNetworkBuffer[ MQTT_AGENT_NETWORK_BUFFER_SIZE ]; + +/** + * @brief Message queue used to deliver commands to the agent task. + */ +static MQTTAgentMessageContext_t xCommandQueue; + +/** + * @brief Structs to hold input and output parameters for each subscribe-publish task. + */ +static struct DemoParams taskParameters[ democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE ]; + +/** + * @brief The global array of subscription elements. + * + * @note No thread safety is required to this array, since updates to the array + * elements are done only from the MQTT agent task. The subscription manager + * implementation expects that the array of the subscription elements used for + * storing subscriptions to be initialized to 0. As this is a global array, it + * will be initialized to 0 by default. + */ +SubscriptionElement_t xGlobalSubscriptionList[ SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS ]; + +/*-----------------------------------------------------------*/ + +/* + * @brief Create the task that demonstrates the sharing of an MQTT connection + * using the coreMQTT Agent library. + */ +int RunCoreMqttAgentDemo( bool awsIotMqttMode, + const char * pIdentifier, + void * pNetworkServerInfo, + void * pNetworkCredentialInfo, + const void * pNetworkInterface ) +{ + BaseType_t xNetworkStatus = pdFAIL; + BaseType_t xResult = pdFALSE; + BaseType_t xNetworkConnectionCreated = pdFALSE; + uint32_t ulNotification = 0UL; + + uint32_t ulDemoCount = 0UL; + uint32_t ulDemoSuccessCount = 0UL; + int ret = EXIT_SUCCESS; + + ( void ) awsIotMqttMode; + ( void ) pIdentifier; + ( void ) pNetworkServerInfo; + ( void ) pNetworkCredentialInfo; + ( void ) pNetworkInterface; + + for( ulDemoCount = 0UL; ( ulDemoCount < democonfigMQTT_MAX_DEMO_COUNT ); ulDemoCount++ ) + { + ret = prvConnectAndCreateDemoTasks( NULL ); + + if( ret == EXIT_SUCCESS ) + { + LogInfo( ( "Demo iteration %lu successful.", ( ulDemoCount + 1 ) ) ); + break; + } + else if( ulDemoCount < ( democonfigMQTT_MAX_DEMO_COUNT - 1 ) ) + { + LogWarn( ( "Demo iteration %lu failed. Retrying...", ( ulDemoCount + 1 ) ) ); + } + else + { + LogError( ( "All %d iterations failed", democonfigMQTT_MAX_DEMO_COUNT ) ); + } + } + + return ret; +} + +/*-----------------------------------------------------------*/ + +static MQTTStatus_t prvMQTTAgentInit( void ) +{ + TransportInterface_t xTransport; + MQTTStatus_t xReturn; + MQTTFixedBuffer_t xFixedBuffer = { .pBuffer = xNetworkBuffer, .size = MQTT_AGENT_NETWORK_BUFFER_SIZE }; + static uint8_t staticQueueStorageArea[ MQTT_AGENT_COMMAND_QUEUE_LENGTH * sizeof( MQTTAgentCommand_t * ) ]; + static StaticQueue_t staticQueueStructure; + MQTTAgentMessageInterface_t messageInterface = + { + .pMsgCtx = NULL, + .send = Agent_MessageSend, + .recv = Agent_MessageReceive, + .getCommand = Agent_GetCommand, + .releaseCommand = Agent_ReleaseCommand + }; + + LogDebug( ( "Creating command queue." ) ); + xCommandQueue.queue = xQueueCreateStatic( MQTT_AGENT_COMMAND_QUEUE_LENGTH, + sizeof( MQTTAgentCommand_t * ), + staticQueueStorageArea, + &staticQueueStructure ); + configASSERT( xCommandQueue.queue ); + messageInterface.pMsgCtx = &xCommandQueue; + + /* Initialize the command struct pool. */ + Agent_InitializePool(); + + /* Fill in Transport Interface send and receive function pointers. */ + xTransport.pNetworkContext = &xNetworkContext; + xTransport.send = SecureSocketsTransport_Send; + xTransport.recv = SecureSocketsTransport_Recv; + + /* Initialize MQTT library. */ + xReturn = MQTTAgent_Init( &xGlobalMqttAgentContext, + &messageInterface, + &xFixedBuffer, + &xTransport, + prvGetTimeMs, + prvIncomingPublishCallback, + /* Context to pass into the callback. Passing the pointer to subscription array. */ + xGlobalSubscriptionList ); + + return xReturn; +} + +/*-----------------------------------------------------------*/ + +static MQTTStatus_t prvMQTTConnect( bool xCleanSession ) +{ + MQTTStatus_t xResult; + MQTTConnectInfo_t xConnectInfo; + bool xSessionPresent = false; + + /* Many fields are not used in this demo so start with everything at 0. */ + memset( &xConnectInfo, 0x00, sizeof( xConnectInfo ) ); + + /* Start with a clean session i.e. direct the MQTT broker to discard any + * previous session data. Also, establishing a connection with clean session + * will ensure that the broker does not store any data when this client + * gets disconnected. */ + xConnectInfo.cleanSession = xCleanSession; + + /* The client identifier is used to uniquely identify this MQTT client to + * the MQTT broker. In a production device the identifier can be something + * unique, such as a device serial number. */ + xConnectInfo.pClientIdentifier = democonfigCLIENT_IDENTIFIER; + xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( democonfigCLIENT_IDENTIFIER ); + + /* Set MQTT keep-alive period. It is the responsibility of the application + * to ensure that the interval between Control Packets being sent does not + * exceed the Keep Alive value. In the absence of sending any other Control + * Packets, the Client MUST send a PINGREQ Packet. This responsibility will + * be moved inside the agent. */ + xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_INTERVAL_SECONDS; + + /* Append metrics when connecting to the AWS IoT Core broker. */ + #ifdef democonfigUSE_AWS_IOT_CORE_BROKER + #ifdef democonfigCLIENT_USERNAME + xConnectInfo.pUserName = CLIENT_USERNAME_WITH_METRICS; + xConnectInfo.userNameLength = ( uint16_t ) strlen( CLIENT_USERNAME_WITH_METRICS ); + xConnectInfo.pPassword = democonfigCLIENT_PASSWORD; + xConnectInfo.passwordLength = ( uint16_t ) strlen( democonfigCLIENT_PASSWORD ); + #else + xConnectInfo.pUserName = AWS_IOT_METRICS_STRING; + xConnectInfo.userNameLength = AWS_IOT_METRICS_STRING_LENGTH; + /* Password for authentication is not used. */ + xConnectInfo.pPassword = NULL; + xConnectInfo.passwordLength = 0U; + #endif + #else /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */ + #ifdef democonfigCLIENT_USERNAME + xConnectInfo.pUserName = democonfigCLIENT_USERNAME; + xConnectInfo.userNameLength = ( uint16_t ) strlen( democonfigCLIENT_USERNAME ); + xConnectInfo.pPassword = democonfigCLIENT_PASSWORD; + xConnectInfo.passwordLength = ( uint16_t ) strlen( democonfigCLIENT_PASSWORD ); + #endif /* ifdef democonfigCLIENT_USERNAME */ + #endif /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */ + + /* Send MQTT CONNECT packet to broker. MQTT's Last Will and Testament feature + * is not used in this demo, so it is passed as NULL. */ + xResult = MQTT_Connect( &( xGlobalMqttAgentContext.mqttContext ), + &xConnectInfo, + NULL, + mqttexampleCONNACK_RECV_TIMEOUT_MS, + &xSessionPresent ); + + LogInfo( ( "Session present: %d\n", xSessionPresent ) ); + + /* Resume a session if desired. */ + if( ( xResult == MQTTSuccess ) && ( xCleanSession == false ) ) + { + xResult = MQTTAgent_ResumeSession( &xGlobalMqttAgentContext, xSessionPresent ); + + /* Resubscribe to all the subscribed topics. */ + if( ( xResult == MQTTSuccess ) && ( xSessionPresent == false ) ) + { + xResult = prvHandleResubscribe(); + } + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +static MQTTStatus_t prvHandleResubscribe( void ) +{ + MQTTStatus_t xResult = MQTTBadParameter; + uint32_t ulIndex = 0U; + uint16_t usNumSubscriptions = 0U; + + /* These variables need to stay in scope until command completes. */ + static MQTTAgentSubscribeArgs_t xSubArgs = { 0 }; + static MQTTSubscribeInfo_t xSubInfo[ SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS ] = { 0 }; + static MQTTAgentCommandInfo_t xCommandParams = { 0 }; + + /* Loop through each subscription in the subscription list and add a subscribe + * command to the command queue. */ + for( ulIndex = 0U; ulIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; ulIndex++ ) + { + /* Check if there is a subscription in the subscription list. This demo + * doesn't check for duplicate subscriptions. */ + if( xGlobalSubscriptionList[ ulIndex ].usFilterStringLength != 0 ) + { + xSubInfo[ usNumSubscriptions ].pTopicFilter = xGlobalSubscriptionList[ ulIndex ].pcSubscriptionFilterString; + xSubInfo[ usNumSubscriptions ].topicFilterLength = xGlobalSubscriptionList[ ulIndex ].usFilterStringLength; + + /* QoS1 is used for all the subscriptions in this demo. */ + xSubInfo[ usNumSubscriptions ].qos = MQTTQoS1; + + LogInfo( ( "Resubscribe to the topic %.*s will be attempted.", + xSubInfo[ usNumSubscriptions ].topicFilterLength, + xSubInfo[ usNumSubscriptions ].pTopicFilter ) ); + + usNumSubscriptions++; + } + } + + if( usNumSubscriptions > 0U ) + { + xSubArgs.pSubscribeInfo = xSubInfo; + xSubArgs.numSubscriptions = usNumSubscriptions; + + /* The block time can be 0 as the command loop is not running at this point. */ + xCommandParams.blockTimeMs = 0U; + xCommandParams.cmdCompleteCallback = prvSubscriptionCommandCallback; + xCommandParams.pCmdCompleteCallbackContext = ( void * ) &xSubArgs; + + /* Enqueue subscribe to the command queue. These commands will be processed only + * when command loop starts. */ + xResult = MQTTAgent_Subscribe( &xGlobalMqttAgentContext, &xSubArgs, &xCommandParams ); + } + else + { + /* Mark the resubscribe as success if there is nothing to be subscribed. */ + xResult = MQTTSuccess; + } + + if( xResult != MQTTSuccess ) + { + LogError( ( "Failed to enqueue the MQTT subscribe command. xResult=%s.", + MQTT_Status_strerror( xResult ) ) ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +static void prvSubscriptionCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ) +{ + size_t lIndex = 0; + MQTTAgentSubscribeArgs_t * pxSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) pxCommandContext; + + /* If the return code is success, no further action is required as all the topic filters + * are already part of the subscription list. */ + if( pxReturnInfo->returnCode != MQTTSuccess ) + { + /* Check through each of the suback codes and determine if there are any failures. */ + for( lIndex = 0; lIndex < pxSubscribeArgs->numSubscriptions; lIndex++ ) + { + /* This demo doesn't attempt to resubscribe in the event that a SUBACK failed. */ + if( pxReturnInfo->pSubackCodes[ lIndex ] == MQTTSubAckFailure ) + { + LogError( ( "Failed to resubscribe to topic %.*s.", + pxSubscribeArgs->pSubscribeInfo[ lIndex ].topicFilterLength, + pxSubscribeArgs->pSubscribeInfo[ lIndex ].pTopicFilter ) ); + /* Remove subscription callback for unsubscribe. */ + removeSubscription( xGlobalSubscriptionList, + pxSubscribeArgs->pSubscribeInfo[ lIndex ].pTopicFilter, + pxSubscribeArgs->pSubscribeInfo[ lIndex ].topicFilterLength ); + } + } + } +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvBackoffForRetry( BackoffAlgorithmContext_t * pxRetryParams ) +{ + BaseType_t xReturnStatus = pdFAIL; + uint16_t usNextRetryBackOff = 0U; + BackoffAlgorithmStatus_t xBackoffAlgStatus = BackoffAlgorithmSuccess; + + /** + * To calculate the backoff period for the next retry attempt, we will + * generate a random number to provide to the backoffAlgorithm library. + * + * Note: The PKCS11 module is used to generate the random number as it allows access + * to a True Random Number Generator (TRNG) if the vendor platform supports it. + * It is recommended to use a random number generator seeded with a device-specific + * entropy source so that probability of collisions from devices in connection retries + * is mitigated. + */ + uint32_t ulRandomNum = 0; + + if( xPkcs11GenerateRandomNumber( ( uint8_t * ) &ulRandomNum, + sizeof( ulRandomNum ) ) == pdPASS ) + { + /* Get back-off value (in milliseconds) for the next retry attempt. */ + xBackoffAlgStatus = BackoffAlgorithm_GetNextBackoff( pxRetryParams, ulRandomNum, &usNextRetryBackOff ); + + if( xBackoffAlgStatus == BackoffAlgorithmRetriesExhausted ) + { + LogError( ( "All retry attempts have exhausted. Operation will not be retried" ) ); + } + else if( xBackoffAlgStatus == BackoffAlgorithmSuccess ) + { + /* Perform the backoff delay. */ + vTaskDelay( pdMS_TO_TICKS( usNextRetryBackOff ) ); + + xReturnStatus = pdPASS; + + LogInfo( ( "Retry attempt %lu out of maximum retry attempts %lu.", + ( pxRetryParams->attemptsDone + 1 ), + pxRetryParams->maxRetryAttempts ) ); + } + } + else + { + LogError( ( "Unable to retry operation with broker: Random number generation failed" ) ); + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvSocketConnect( NetworkContext_t * pxNetworkContext ) +{ + BaseType_t xConnected = pdFAIL; + TransportSocketStatus_t xNetworkStatus = TRANSPORT_SOCKET_STATUS_SUCCESS; + ServerInfo_t xServerInfo = { 0 }; + SocketsConfig_t xSocketConfig = { 0 }; + /* Set the receive timeout to a small nonzero value. */ + const TickType_t xTransportTimeout = 1UL; + + /* Initialize the MQTT broker information. */ + xServerInfo.pHostName = democonfigMQTT_BROKER_ENDPOINT; + xServerInfo.hostNameLength = sizeof( democonfigMQTT_BROKER_ENDPOINT ) - 1U; + xServerInfo.port = democonfigMQTT_BROKER_PORT; + + /* Set the Secure Socket configurations. */ + xSocketConfig.enableTls = true; + xSocketConfig.disableSni = false; + xSocketConfig.sendTimeoutMs = mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS; + xSocketConfig.recvTimeoutMs = mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS; + xSocketConfig.pRootCa = democonfigROOT_CA_PEM; + xSocketConfig.rootCaSize = sizeof( democonfigROOT_CA_PEM ); + + /* Establish a TCP connection with the MQTT broker. This example connects to + * the MQTT broker as specified in democonfigMQTT_BROKER_ENDPOINT and + * democonfigMQTT_BROKER_PORT at the top of this file. */ + LogInfo( ( "Creating a TLS connection to %s:%d.", + democonfigMQTT_BROKER_ENDPOINT, + democonfigMQTT_BROKER_PORT ) ); + + xNetworkStatus = SecureSocketsTransport_Connect( pxNetworkContext, &xServerInfo, &xSocketConfig ); + + xConnected = ( xNetworkStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) ? pdPASS : pdFAIL; + + /* Set the socket wakeup callback and ensure the read block time. */ + if( xConnected ) + { + SOCKETS_SetSockOpt( pxNetworkContext->pParams->tcpSocket, + 0, + SOCKETS_SO_RCVTIMEO, + &xTransportTimeout, + sizeof( TickType_t ) ); + } + + return xConnected; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvSocketDisconnect( NetworkContext_t * pxNetworkContext ) +{ + LogInfo( ( "Disconnecting TLS connection.\n" ) ); + TransportSocketStatus_t xNetworkStatus = SecureSocketsTransport_Disconnect( pxNetworkContext ); + + return ( xNetworkStatus == TRANSPORT_SOCKET_STATUS_SUCCESS ) ? pdPASS : pdFAIL; +} + +/*-----------------------------------------------------------*/ + +static void prvIncomingPublishCallback( MQTTAgentContext_t * pMqttAgentContext, + uint16_t packetId, + MQTTPublishInfo_t * pxPublishInfo ) +{ + bool xPublishHandled = false; + char cOriginalChar, * pcLocation; + + ( void ) packetId; + + /* Fan out the incoming publishes to the callbacks registered using + * subscription manager. */ + xPublishHandled = handleIncomingPublishes( ( SubscriptionElement_t * ) pMqttAgentContext->pIncomingCallbackContext, + pxPublishInfo ); + + /* If there are no callbacks to handle the incoming publishes, + * handle it as an unsolicited publish. */ + if( xPublishHandled != true ) + { + /* Ensure the topic string is terminated for printing. This will over- + * write the message ID, which is restored afterwards. */ + pcLocation = ( char * ) &( pxPublishInfo->pTopicName[ pxPublishInfo->topicNameLength ] ); + cOriginalChar = *pcLocation; + *pcLocation = 0x00; + LogWarn( ( "Received an unsolicited publish from topic %s", pxPublishInfo->pTopicName ) ); + *pcLocation = cOriginalChar; + } +} + +/*-----------------------------------------------------------*/ + +static void prvMQTTAgentTask( void * pvParameters ) +{ + BaseType_t xNetworkResult = pdFAIL; + MQTTStatus_t xMQTTStatus = MQTTSuccess, xConnectStatus = MQTTSuccess; + MQTTContext_t * pMqttContext = &( xGlobalMqttAgentContext.mqttContext ); + + ( void ) pvParameters; + + do + { + /* MQTTAgent_CommandLoop() is effectively the agent implementation. It + * will manage the MQTT protocol until such time that an error occurs, + * which could be a disconnect. If an error occurs the MQTT context on + * which the error happened is returned so there can be an attempt to + * clean up and reconnect however the application writer prefers. */ + xMQTTStatus = MQTTAgent_CommandLoop( &xGlobalMqttAgentContext ); + + /* Success is returned for disconnect or termination. The socket should + * be disconnected. */ + if( ( xMQTTStatus == MQTTSuccess ) && ( xGlobalMqttAgentContext.mqttContext.connectStatus == MQTTNotConnected ) ) + { + /* MQTT Disconnect. Disconnect the socket. */ + xNetworkResult = prvSocketDisconnect( &xNetworkContext ); + } + else if( xMQTTStatus == MQTTSuccess ) + { + /* MQTTAgent_Terminate() was called, but MQTT was not disconnected. */ + xConnectStatus = MQTT_Disconnect( &( xGlobalMqttAgentContext.mqttContext ) ); + xNetworkResult = prvSocketDisconnect( &xNetworkContext ); + break; + } + /* Any error. */ + else + { + /* Reconnect TCP. */ + xNetworkResult = prvSocketDisconnect( &xNetworkContext ); + + if( xNetworkResult == pdPASS ) + { + pMqttContext->connectStatus = MQTTNotConnected; + + /* MQTT Connect with a persistent session. */ + xNetworkResult = prvConnectToMQTTBroker( false ); + } + + if( xNetworkResult != pdPASS ) + { + LogError( ( "Could not reconnect to MQTT broker" ) ); + break; + } + } + } while( xMQTTStatus != MQTTSuccess ); + + /* Delete the task if it is complete. */ + LogInfo( ( "MQTT Agent task completed." ) ); + vTaskDelete( NULL ); +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvConnectToMQTTBroker( bool xCreateCleanSession ) +{ + MQTTStatus_t xMQTTStatus = MQTTBadParameter; + BaseType_t xConnected = pdFAIL; + BackoffAlgorithmContext_t xReconnectParams; + BaseType_t xBackoffStatus = pdFAIL; + + /* Initialize reconnect attempts and interval. */ + BackoffAlgorithm_InitializeParams( &xReconnectParams, + RETRY_BACKOFF_BASE_MS, + RETRY_MAX_BACKOFF_DELAY_MS, + RETRY_MAX_ATTEMPTS ); + + /* Attempt to connect to MQTT broker. If connection fails, retry after a + * timeout. Timeout value will exponentially increase until the maximum + * number of attempts are reached. + */ + do + { + /* Connect a TCP socket to the broker. */ + xConnected = prvSocketConnect( &xNetworkContext ); + + if( xConnected == pdPASS ) + { + /* Form an MQTT connection. */ + xMQTTStatus = prvMQTTConnect( xCreateCleanSession ); + + if( xMQTTStatus != MQTTSuccess ) + { + /* Close connection before next retry. */ + prvSocketDisconnect( &xNetworkContext ); + } + } + + if( xMQTTStatus != MQTTSuccess ) + { + LogWarn( ( "Connection to the broker failed. Attempting connection retry after backoff delay." ) ); + + /* As the connection attempt failed, we will retry the connection after an + * exponential backoff with jitter delay. */ + + /* Calculate the backoff period for the next retry attempt and perform the wait operation. */ + xBackoffStatus = prvBackoffForRetry( &xReconnectParams ); + } + } while( ( xMQTTStatus != MQTTSuccess ) && ( xBackoffStatus == pdPASS ) ); + + return ( xMQTTStatus == MQTTSuccess ) ? pdPASS : pdFAIL; +} +/*-----------------------------------------------------------*/ + +static int prvConnectAndCreateDemoTasks( void * pvParameters ) +{ + MQTTAgentCommandInfo_t xCommandParams = { 0 }; + uint32_t i, numSuccess = 0; + BaseType_t xResult = pdFAIL; + MQTTStatus_t xMQTTStatus = MQTTBadParameter; + + ( void ) pvParameters; + + /* Miscellaneous initialization. */ + ulGlobalEntryTimeMs = prvGetTimeMs(); + + /* Set the pParams member of the network context with desired transport. */ + xNetworkContext.pParams = &secureSocketsTransportParams; + + /* Initialize the MQTT context with the buffer and transport interface. */ + xMQTTStatus = prvMQTTAgentInit(); + + if( xMQTTStatus == MQTTSuccess ) + { + /* Create the TCP connection to the broker, then the MQTT connection to the + * same. */ + xResult = prvConnectToMQTTBroker( true ); + } + + if( xResult == pdPASS ) + { + /* Create demo tasks as per the configuration macro settings. */ + vStartSimpleSubscribePublishTask( democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE, + democonfigSIMPLE_SUB_PUB_TASK_STACK_SIZE, + tskIDLE_PRIORITY, + taskParameters ); + + /* Create an instance of the MQTT agent task. Give it higher priority than the + * subscribe-publish tasks so that the agent's command queue will not become full, + * as those tasks need to send commands to the queue. */ + xTaskCreate( prvMQTTAgentTask, + "MQTT Agent", + democonfigSIMPLE_SUB_PUB_TASK_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 1, + NULL ); + + /* Wait for all tasks to exit. */ + for( i = 0; i < democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE; i++ ) + { + ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); + } + + /* Terminate the agent task. */ + MQTTAgent_Terminate( &xGlobalMqttAgentContext, &xCommandParams ); + + for( i = 0; i < democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE; i++ ) + { + if( taskParameters[ i ].xSuccess ) + { + numSuccess++; + } + } + } + + LogInfo( ( "%lu/%lu tasks successful.", numSuccess, democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE ) ); + + return ( numSuccess == democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE ) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/*-----------------------------------------------------------*/ + +static uint32_t prvGetTimeMs( void ) +{ + TickType_t xTickCount = 0; + uint32_t ulTimeMs = 0UL; + + /* Get the current tick count. */ + xTickCount = xTaskGetTickCount(); + + /* Convert the ticks to milliseconds. */ + ulTimeMs = ( uint32_t ) xTickCount * mqttexampleMILLISECONDS_PER_TICK; + + /* Reduce ulGlobalEntryTimeMs from obtained time so as to always return the + * elapsed time in the application. */ + ulTimeMs = ( uint32_t ) ( ulTimeMs - ulGlobalEntryTimeMs ); + + return ulTimeMs; +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/demos/coreMQTT_Agent/simple_sub_pub_demo.c b/bsp/aws_libraries/demos/coreMQTT_Agent/simple_sub_pub_demo.c new file mode 100644 index 0000000..5e0e7a8 --- /dev/null +++ b/bsp/aws_libraries/demos/coreMQTT_Agent/simple_sub_pub_demo.c @@ -0,0 +1,569 @@ +/* + * FreeRTOS V202104.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* + * This file demonstrates numerous tasks all of which use the MQTT agent API + * to send unique MQTT payloads to unique topics over the same MQTT connection + * to the same MQTT agent. Some tasks use QoS0 and others QoS1. + * + * Each created task is a unique instance of the task implemented by + * prvSimpleSubscribePublishTask(). prvSimpleSubscribePublishTask() + * subscribes to a topic then periodically publishes a message to the same + * topic to which it has subscribed. The command context sent to + * MQTTAgent_Publish() contains a unique number that is sent back to the task + * as a task notification from the callback function that executes when the + * PUBLISH operation is acknowledged (or just sent in the case of QoS 0). The + * task checks the number it receives from the callback equals the number it + * previously set in the command context before printing out either a success + * or failure message. + */ + + +/* Standard includes. */ +#include +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo Specific configs. */ +#include "mqtt_agent_demo_config.h" + +/* MQTT library includes. */ +#include "core_mqtt.h" + +/* MQTT agent include. */ +#include "core_mqtt_agent.h" + +/* Subscription manager header include. */ +#include "subscription_manager.h" + +/** + * @brief This demo uses task notifications to signal tasks from MQTT callback + * functions. mqttexampleMS_TO_WAIT_FOR_NOTIFICATION defines the time, in ticks, + * to wait for such a callback. + */ +#define mqttexampleMS_TO_WAIT_FOR_NOTIFICATION ( 10000 ) + +/** + * @brief Size of statically allocated buffers for holding topic names and + * payloads. + */ +#define mqttexampleSTRING_BUFFER_LENGTH ( 100 ) + +/** + * @brief Delay for each task between publishes. + */ +#define mqttexampleDELAY_BETWEEN_PUBLISH_OPERATIONS_MS ( 1000U ) + +/** + * @brief Number of publishes done by each task in this demo. + */ +#define mqttexamplePUBLISH_COUNT ( 10UL ) + +/** + * @brief The maximum amount of time in milliseconds to wait for the commands + * to be posted to the MQTT agent should the MQTT agent's command queue be full. + * Tasks wait in the Blocked state, so don't use any CPU time. + */ +#define mqttexampleMAX_COMMAND_SEND_BLOCK_TIME_MS ( 500 ) + +/** + * @brief The modulus with which to reduce a task number to obtain the task's + * publish QoS value. Must be either to 1, 2, or 3, resulting in maximum QoS + * values of 0, 1, and 2, respectively. + */ +#define mqttexampleQOS_MODULUS ( 2UL ) + +/*-----------------------------------------------------------*/ + +/** + * @brief Defines the structure to use as the command callback context in this + * demo. + */ +struct MQTTAgentCommandContext +{ + MQTTStatus_t xReturnStatus; + TaskHandle_t xTaskToNotify; + uint32_t ulNotificationValue; + void * pArgs; +}; + +/** + * @brief Parameters for this task. + */ +struct DemoParams +{ + uint32_t ulTaskNumber; + bool xSuccess; +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Passed into MQTTAgent_Subscribe() as the callback to execute when the + * broker ACKs the SUBSCRIBE message. Its implementation sends a notification + * to the task that called MQTTAgent_Subscribe() to let the task know the + * SUBSCRIBE operation completed. It also sets the xReturnStatus of the + * structure passed in as the command's context to the value of the + * xReturnStatus parameter - which enables the task to check the status of the + * operation. + * + * See https://freertos.org/mqtt/mqtt-agent-demo.html#example_mqtt_api_call + * + * @param[in] pxCommandContext Context of the initial command. + * @param[in].xReturnStatus The result of the command. + */ +static void prvSubscribeCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ); + +/** + * @brief Passed into MQTTAgent_Publish() as the callback to execute when the + * broker ACKs the PUBLISH message. Its implementation sends a notification + * to the task that called MQTTAgent_Publish() to let the task know the + * PUBLISH operation completed. It also sets the xReturnStatus of the + * structure passed in as the command's context to the value of the + * xReturnStatus parameter - which enables the task to check the status of the + * operation. + * + * See https://freertos.org/mqtt/mqtt-agent-demo.html#example_mqtt_api_call + * + * @param[in] pxCommandContext Context of the initial command. + * @param[in].xReturnStatus The result of the command. + */ +static void prvPublishCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ); + +/** + * @brief Called by the task to wait for a notification from a callback function + * after the task first executes either MQTTAgent_Publish()* or + * MQTTAgent_Subscribe(). + * + * See https://freertos.org/mqtt/mqtt-agent-demo.html#example_mqtt_api_call + * + * @param[in] pxCommandContext Context of the initial command. + * @param[out] pulNotifiedValue The task's notification value after it receives + * a notification from the callback. + * + * @return pdTRUE if the task received a notification, otherwise pdFALSE. + */ +static BaseType_t prvWaitForCommandAcknowledgment( uint32_t * pulNotifiedValue ); + +/** + * @brief Passed into MQTTAgent_Subscribe() as the callback to execute when + * there is an incoming publish on the topic being subscribed to. Its + * implementation just logs information about the incoming publish including + * the publish messages source topic and payload. + * + * See https://freertos.org/mqtt/mqtt-agent-demo.html#example_mqtt_api_call + * + * @param[in] pvIncomingPublishCallbackContext Context of the initial command. + * @param[in] pxPublishInfo Deserialized publish. + */ +static void prvIncomingPublishCallback( void * pvIncomingPublishCallbackContext, + MQTTPublishInfo_t * pxPublishInfo ); + +/** + * @brief Subscribe to the topic the demo task will also publish to - that + * results in all outgoing publishes being published back to the task + * (effectively echoed back). + * + * @param[in] xQoS The quality of service (QoS) to use. Can be zero or one + * for all MQTT brokers. Can also be QoS2 if supported by the broker. AWS IoT + * does not support QoS2. + * @param[in] pcTopicFilter Topic filter to subscribe to. + */ +static bool prvSubscribeToTopic( MQTTQoS_t xQoS, + char * pcTopicFilter ); + +/** + * @brief The function that implements the task demonstrated by this file. + */ +static void prvSimpleSubscribePublishTask( void * pvParameters ); + +/*-----------------------------------------------------------*/ + +/** + * @brief The MQTT agent manages the MQTT contexts. This set the handle to the + * context used by this demo. + */ +extern MQTTAgentContext_t xGlobalMqttAgentContext; + +/*-----------------------------------------------------------*/ + +static TaskHandle_t xMainTask; + +/** + * @brief The buffer to hold the topic filter. The topic is generated at runtime + * by adding the task names. + * + * @note The topic strings must persist until unsubscribed. + */ +static char topicBuf[ democonfigNUM_SIMPLE_SUB_PUB_TASKS_TO_CREATE ][ mqttexampleSTRING_BUFFER_LENGTH ]; + +/*-----------------------------------------------------------*/ + +void vStartSimpleSubscribePublishTask( uint32_t ulNumberToCreate, + configSTACK_DEPTH_TYPE uxStackSize, + UBaseType_t uxPriority, + struct DemoParams * pxParams ) +{ + char pcTaskNameBuf[ 15 ]; + uint32_t ulTaskNumber; + + xMainTask = xTaskGetCurrentTaskHandle(); + + /* Each instance of prvSimpleSubscribePublishTask() generates a unique name + * and topic filter for itself from the number passed in as the task + * parameter. */ + /* Create a few instances of vSimpleSubscribePublishTask(). */ + for( ulTaskNumber = 0; ulTaskNumber < ulNumberToCreate; ulTaskNumber++ ) + { + memset( pcTaskNameBuf, 0x00, sizeof( pcTaskNameBuf ) ); + snprintf( pcTaskNameBuf, 10, "SubPub%d", ( int ) ulTaskNumber ); + pxParams[ ulTaskNumber ].ulTaskNumber = ulTaskNumber; + pxParams[ ulTaskNumber ].xSuccess = false; + xTaskCreate( prvSimpleSubscribePublishTask, + pcTaskNameBuf, + uxStackSize, + ( void * ) &pxParams[ ulTaskNumber ], + uxPriority, + NULL ); + } +} + +/*-----------------------------------------------------------*/ + +static void prvPublishCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ) +{ + /* Store the result in the application defined context so the task that + * initiated the publish can check the operation's status. */ + pxCommandContext->xReturnStatus = pxReturnInfo->returnCode; + + if( pxCommandContext->xTaskToNotify != NULL ) + { + /* Send the context's ulNotificationValue as the notification value so + * the receiving task can check the value it set in the context matches + * the value it receives in the notification. */ + xTaskNotify( pxCommandContext->xTaskToNotify, + pxCommandContext->ulNotificationValue, + eSetValueWithOverwrite ); + } +} + +/*-----------------------------------------------------------*/ + +static void prvSubscribeCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ) +{ + bool xSubscriptionAdded = false; + MQTTAgentSubscribeArgs_t * pxSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) pxCommandContext->pArgs; + + /* Store the result in the application defined context so the task that + * initiated the subscribe can check the operation's status. */ + pxCommandContext->xReturnStatus = pxReturnInfo->returnCode; + + /* Check if the subscribe operation is a success. Only one topic is + * subscribed by this demo. */ + if( pxReturnInfo->returnCode == MQTTSuccess ) + { + /* Add subscription so that incoming publishes are routed to the application + * callback. */ + xSubscriptionAdded = addSubscription( ( SubscriptionElement_t * ) xGlobalMqttAgentContext.pIncomingCallbackContext, + pxSubscribeArgs->pSubscribeInfo->pTopicFilter, + pxSubscribeArgs->pSubscribeInfo->topicFilterLength, + prvIncomingPublishCallback, + NULL ); + + if( xSubscriptionAdded == false ) + { + LogError( ( "Failed to register an incoming publish callback for topic %.*s.", + pxSubscribeArgs->pSubscribeInfo->topicFilterLength, + pxSubscribeArgs->pSubscribeInfo->pTopicFilter ) ); + } + } + + xTaskNotify( pxCommandContext->xTaskToNotify, + pxCommandContext->ulNotificationValue, + eSetValueWithOverwrite ); +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvWaitForCommandAcknowledgment( uint32_t * pulNotifiedValue ) +{ + BaseType_t xReturn; + + /* Wait for this task to get notified, passing out the value it gets + * notified with. */ + xReturn = xTaskNotifyWait( 0, + 0, + pulNotifiedValue, + pdMS_TO_TICKS( mqttexampleMS_TO_WAIT_FOR_NOTIFICATION ) ); + return xReturn; +} + +/*-----------------------------------------------------------*/ + +static void prvIncomingPublishCallback( void * pvIncomingPublishCallbackContext, + MQTTPublishInfo_t * pxPublishInfo ) +{ + static char cTerminatedString[ mqttexampleSTRING_BUFFER_LENGTH ]; + + ( void ) pvIncomingPublishCallbackContext; + + /* Create a message that contains the incoming MQTT payload to the logger, + * terminating the string first. */ + if( pxPublishInfo->payloadLength < mqttexampleSTRING_BUFFER_LENGTH ) + { + memcpy( ( void * ) cTerminatedString, pxPublishInfo->pPayload, pxPublishInfo->payloadLength ); + cTerminatedString[ pxPublishInfo->payloadLength ] = 0x00; + } + else + { + memcpy( ( void * ) cTerminatedString, pxPublishInfo->pPayload, mqttexampleSTRING_BUFFER_LENGTH ); + cTerminatedString[ mqttexampleSTRING_BUFFER_LENGTH - 1 ] = 0x00; + } + + LogInfo( ( "Received incoming publish message %s", cTerminatedString ) ); +} + +/*-----------------------------------------------------------*/ + +static bool prvSubscribeToTopic( MQTTQoS_t xQoS, + char * pcTopicFilter ) +{ + MQTTStatus_t xCommandAdded; + BaseType_t xCommandAcknowledged = pdFALSE; + uint32_t ulSubscribeMessageID, ulNotifiedValue = 0; + MQTTAgentSubscribeArgs_t xSubscribeArgs; + MQTTSubscribeInfo_t xSubscribeInfo; + static int32_t ulNextSubscribeMessageID = 0; + MQTTAgentCommandContext_t xApplicationDefinedContext = { 0 }; + MQTTAgentCommandInfo_t xCommandParams = { 0 }; + + /* Create a unique number of the subscribe that is about to be sent. The number + * is used as the command context and is sent back to this task as a notification + * in the callback that executed upon receipt of the subscription acknowledgment. + * That way this task can match an acknowledgment to a subscription. This is useful + * if there is more than one subscription, but only included for demonstration + * purposes here as there is only one subscription per task. */ + xTaskNotifyStateClear( NULL ); + taskENTER_CRITICAL(); + { + ulNextSubscribeMessageID++; + ulSubscribeMessageID = ulNextSubscribeMessageID; + } + taskEXIT_CRITICAL(); + + /* Complete the subscribe information. The topic string must persist for + * duration of subscription! */ + xSubscribeInfo.pTopicFilter = pcTopicFilter; + xSubscribeInfo.topicFilterLength = ( uint16_t ) strlen( pcTopicFilter ); + xSubscribeInfo.qos = xQoS; + xSubscribeArgs.pSubscribeInfo = &xSubscribeInfo; + xSubscribeArgs.numSubscriptions = 1; + + /* Complete an application defined context associated with this subscribe message. + * This gets updated in the callback function so the variable must persist until + * the callback executes. */ + xApplicationDefinedContext.ulNotificationValue = ulSubscribeMessageID; + xApplicationDefinedContext.xTaskToNotify = xTaskGetCurrentTaskHandle(); + xApplicationDefinedContext.pArgs = ( void * ) &xSubscribeArgs; + + xCommandParams.blockTimeMs = mqttexampleMAX_COMMAND_SEND_BLOCK_TIME_MS; + xCommandParams.cmdCompleteCallback = prvSubscribeCommandCallback; + xCommandParams.pCmdCompleteCallbackContext = ( void * ) &xApplicationDefinedContext; + + /* The queue will not become full if the priority of the MQTT agent task is + * higher than the priority of the task calling this function. */ + LogInfo( ( "Sending subscribe request to agent for topic filter: %s with id %d", + pcTopicFilter, + ( int ) ulSubscribeMessageID ) ); + + xCommandAdded = MQTTAgent_Subscribe( &xGlobalMqttAgentContext, + &xSubscribeArgs, + &xCommandParams ); + + if( xCommandAdded == MQTTSuccess ) + { + /* Wait for acks to the subscribe message - this is optional but done here + * so the code below can check the notification sent by the callback matches + * the ulNextSubscribeMessageID value set in the context above. */ + xCommandAcknowledged = prvWaitForCommandAcknowledgment( &ulNotifiedValue ); + } + else + { + LogError( ( "Failed to enqueue subscribe command." ) ); + } + + /* Check all ways the status was passed back just for demonstration + * purposes. */ + if( ( xCommandAcknowledged != pdTRUE ) || + ( xApplicationDefinedContext.xReturnStatus != MQTTSuccess ) || + ( ulNotifiedValue != ulSubscribeMessageID ) ) + { + LogWarn( ( "Error or timed out waiting for ack to subscribe message topic %s", + pcTopicFilter ) ); + } + else + { + LogInfo( ( "Received subscribe ack for topic %s containing ID %d", + pcTopicFilter, + ( int ) xApplicationDefinedContext.ulNotificationValue ) ); + } + + return xCommandAcknowledged; +} + +/*-----------------------------------------------------------*/ + +static void prvSimpleSubscribePublishTask( void * pvParameters ) +{ + MQTTPublishInfo_t xPublishInfo = { 0 }; + char payloadBuf[ mqttexampleSTRING_BUFFER_LENGTH ]; + char taskName[ mqttexampleSTRING_BUFFER_LENGTH ]; + MQTTAgentCommandContext_t xCommandContext; + uint32_t ulNotification = 0U, ulValueToNotify = 0UL; + MQTTStatus_t xCommandAdded; + struct DemoParams * pxParams = ( struct DemoParams * ) pvParameters; + uint32_t ulTaskNumber = pxParams->ulTaskNumber; + MQTTQoS_t xQoS; + TickType_t xTicksToDelay; + MQTTAgentCommandInfo_t xCommandParams = { 0 }; + char * pcTopicBuffer = topicBuf[ ulTaskNumber ]; + uint32_t numSuccesses = 0U; + + /* Have different tasks use different QoS. 0 and 1. 2 can also be used + * if supported by the broker. */ + xQoS = ( MQTTQoS_t ) ( ulTaskNumber % mqttexampleQOS_MODULUS ); + + /* Create a unique name for this task from the task number that is passed into + * the task using the task's parameter. */ + snprintf( taskName, mqttexampleSTRING_BUFFER_LENGTH, "Publisher%d", ( int ) ulTaskNumber ); + + /* Create a topic name for this task to publish to. */ + snprintf( pcTopicBuffer, mqttexampleSTRING_BUFFER_LENGTH, "/filter/%s", taskName ); + + /* Subscribe to the same topic to which this task will publish. That will + * result in each published message being published from the server back to + * the target. */ + prvSubscribeToTopic( xQoS, pcTopicBuffer ); + + /* Configure the publish operation. */ + memset( ( void * ) &xPublishInfo, 0x00, sizeof( xPublishInfo ) ); + xPublishInfo.qos = xQoS; + xPublishInfo.pTopicName = pcTopicBuffer; + xPublishInfo.topicNameLength = ( uint16_t ) strlen( pcTopicBuffer ); + xPublishInfo.pPayload = payloadBuf; + + /* Store the handler to this task in the command context so the callback + * that executes when the command is acknowledged can send a notification + * back to this task. */ + memset( ( void * ) &xCommandContext, 0x00, sizeof( xCommandContext ) ); + xCommandContext.xTaskToNotify = xTaskGetCurrentTaskHandle(); + + xCommandParams.blockTimeMs = mqttexampleMAX_COMMAND_SEND_BLOCK_TIME_MS; + xCommandParams.cmdCompleteCallback = prvPublishCommandCallback; + xCommandParams.pCmdCompleteCallbackContext = &xCommandContext; + + /* For a finite number of publishes... */ + for( ulValueToNotify = 0UL; ulValueToNotify < mqttexamplePUBLISH_COUNT; ulValueToNotify++ ) + { + /* Create a payload to send with the publish message. This contains + * the task name and an incrementing number. */ + snprintf( payloadBuf, + mqttexampleSTRING_BUFFER_LENGTH, + "%s publishing message %d", + taskName, + ( int ) ulValueToNotify ); + + xPublishInfo.payloadLength = ( uint16_t ) strlen( payloadBuf ); + + /* Also store the incrementing number in the command context so it can + * be accessed by the callback that executes when the publish operation + * is acknowledged. */ + xCommandContext.ulNotificationValue = ulValueToNotify; + + LogInfo( ( "Sending publish request to agent with message \"%s\" on topic \"%s\"", + payloadBuf, + pcTopicBuffer ) ); + + /* To ensure ulNotification doesn't accidentally hold the expected value + * as it is to be checked against the value sent from the callback.. */ + ulNotification = ~ulValueToNotify; + + xCommandAdded = MQTTAgent_Publish( &xGlobalMqttAgentContext, + &xPublishInfo, + &xCommandParams ); + + if( xCommandAdded == MQTTSuccess ) + { + /* For QoS 1 and 2, wait for the publish acknowledgment. For QoS0, + * wait for the publish to be sent. */ + LogInfo( ( "Task %s waiting for publish %d to complete.", + taskName, + ulValueToNotify ) ); + prvWaitForCommandAcknowledgment( &ulNotification ); + } + else + { + LogError( ( "Failed to enqueue publish command. Error code=%s", MQTT_Status_strerror( xCommandAdded ) ) ); + } + + /* The value received by the callback that executed when the publish was + * completed came from the context passed into MQTTAgent_Publish() above, + * so should match the value set in the context above. */ + if( ulNotification == ulValueToNotify ) + { + numSuccesses++; + /* Log statement to indicate successful reception of publish. */ + LogInfo( ( "Publish %d completed successfully.\r\n", ulValueToNotify ) ); + } + + LogInfo( ( "Short delay before next publish... \r\n\r\n" ) ); + + xTicksToDelay = pdMS_TO_TICKS( mqttexampleDELAY_BETWEEN_PUBLISH_OPERATIONS_MS ); + vTaskDelay( xTicksToDelay ); + } + + /* Mark this task as successful if every publish was successfully completed. */ + if( numSuccesses == mqttexamplePUBLISH_COUNT ) + { + pxParams->xSuccess = true; + LogInfo( ( "Task %s successful.", taskName ) ); + } + + /* Notify the main task this one has completed. */ + xTaskNotifyGive( xMainTask ); + + /* Delete the task if it is complete. */ + LogInfo( ( "Task %s completed.", taskName ) ); + vTaskDelete( NULL ); +} diff --git a/bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.c b/bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.c new file mode 100644 index 0000000..59f0636 --- /dev/null +++ b/bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.c @@ -0,0 +1,170 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file subscription_manager.c + * @brief Functions for managing MQTT subscriptions. + */ + +/* Standard includes. */ +#include + +/* Subscription manager header include. */ +#include "subscription_manager.h" + + +bool addSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength, + IncomingPubCallback_t pxIncomingPublishCallback, + void * pvIncomingPublishCallbackContext ) +{ + int32_t lIndex = 0; + size_t xAvailableIndex = SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; + bool xReturnStatus = false; + + if( ( pxSubscriptionList == NULL ) || + ( pcTopicFilterString == NULL ) || + ( usTopicFilterLength == 0U ) || + ( pxIncomingPublishCallback == NULL ) ) + { + LogError( ( "Invalid parameter. pxSubscriptionList=%p, pcTopicFilterString=%p," + " usTopicFilterLength=%u, pxIncomingPublishCallback=%p.", + pxSubscriptionList, + pcTopicFilterString, + ( unsigned int ) usTopicFilterLength, + pxIncomingPublishCallback ) ); + } + else + { + /* Start at end of array, so that we will insert at the first available index. + * Scans backwards to find duplicates. */ + for( lIndex = ( int32_t ) SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS - 1; lIndex >= 0; lIndex-- ) + { + if( pxSubscriptionList[ lIndex ].usFilterStringLength == 0 ) + { + xAvailableIndex = lIndex; + } + else if( ( pxSubscriptionList[ lIndex ].usFilterStringLength == usTopicFilterLength ) && + ( strncmp( pcTopicFilterString, pxSubscriptionList[ lIndex ].pcSubscriptionFilterString, ( size_t ) usTopicFilterLength ) == 0 ) ) + { + /* If a subscription already exists, don't do anything. */ + if( ( pxSubscriptionList[ lIndex ].pxIncomingPublishCallback == pxIncomingPublishCallback ) && + ( pxSubscriptionList[ lIndex ].pvIncomingPublishCallbackContext == pvIncomingPublishCallbackContext ) ) + { + LogWarn( ( "Subscription already exists.\n" ) ); + xAvailableIndex = SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; + xReturnStatus = true; + break; + } + } + } + + if( xAvailableIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS ) + { + pxSubscriptionList[ xAvailableIndex ].pcSubscriptionFilterString = pcTopicFilterString; + pxSubscriptionList[ xAvailableIndex ].usFilterStringLength = usTopicFilterLength; + pxSubscriptionList[ xAvailableIndex ].pxIncomingPublishCallback = pxIncomingPublishCallback; + pxSubscriptionList[ xAvailableIndex ].pvIncomingPublishCallbackContext = pvIncomingPublishCallbackContext; + xReturnStatus = true; + } + } + + return xReturnStatus; +} + +/*-----------------------------------------------------------*/ + +void removeSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength ) +{ + int32_t lIndex = 0; + + if( ( pxSubscriptionList == NULL ) || + ( pcTopicFilterString == NULL ) || + ( usTopicFilterLength == 0U ) ) + { + LogError( ( "Invalid parameter. pxSubscriptionList=%p, pcTopicFilterString=%p," + " usTopicFilterLength=%u.", + pxSubscriptionList, + pcTopicFilterString, + ( unsigned int ) usTopicFilterLength ) ); + } + else + { + for( lIndex = 0; lIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; lIndex++ ) + { + if( pxSubscriptionList[ lIndex ].usFilterStringLength == usTopicFilterLength ) + { + if( strncmp( pxSubscriptionList[ lIndex ].pcSubscriptionFilterString, pcTopicFilterString, usTopicFilterLength ) == 0 ) + { + memset( &( pxSubscriptionList[ lIndex ] ), 0x00, sizeof( SubscriptionElement_t ) ); + } + } + } + } +} + +/*-----------------------------------------------------------*/ + +bool handleIncomingPublishes( SubscriptionElement_t * pxSubscriptionList, + MQTTPublishInfo_t * pxPublishInfo ) +{ + int32_t lIndex = 0; + bool isMatched = false, publishHandled = false; + + if( ( pxSubscriptionList == NULL ) || + ( pxPublishInfo == NULL ) ) + { + LogError( ( "Invalid parameter. pxSubscriptionList=%p, pxPublishInfo=%p,", + pxSubscriptionList, + pxPublishInfo ) ); + } + else + { + for( lIndex = 0; lIndex < SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS; lIndex++ ) + { + if( pxSubscriptionList[ lIndex ].usFilterStringLength > 0 ) + { + MQTT_MatchTopic( pxPublishInfo->pTopicName, + pxPublishInfo->topicNameLength, + pxSubscriptionList[ lIndex ].pcSubscriptionFilterString, + pxSubscriptionList[ lIndex ].usFilterStringLength, + &isMatched ); + + if( isMatched == true ) + { + pxSubscriptionList[ lIndex ].pxIncomingPublishCallback( pxSubscriptionList[ lIndex ].pvIncomingPublishCallbackContext, + pxPublishInfo ); + publishHandled = true; + } + } + } + } + + return publishHandled; +} diff --git a/bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.h b/bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.h new file mode 100644 index 0000000..a27cdd9 --- /dev/null +++ b/bsp/aws_libraries/demos/coreMQTT_Agent/subscription_manager.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://aws.amazon.com/freertos + * + */ + +/** + * @file subscription_manager.h + * @brief Functions for managing MQTT subscriptions. + */ +#ifndef SUBSCRIPTION_MANAGER_H +#define SUBSCRIPTION_MANAGER_H + +/**************************************************/ +/******* DO NOT CHANGE the following order ********/ +/**************************************************/ + +/* Logging related header files are required to be included in the following order: + * 1. Include the header file "logging_levels.h". + * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. + * 3. Include the header file "logging_stack.h". + */ + +/* Include header that defines log levels. */ +#include "logging_levels.h" + +/* Logging configuration for the Subscription Manager module. */ +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME "Subscription Manager" +#endif +#ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL LOG_ERROR +#endif + +#include "logging_stack.h" + + +/* Demo config include. */ +#include "mqtt_agent_demo_config.h" + +/* core MQTT include. */ +#include "core_mqtt.h" + + +/** + * @brief Maximum number of subscriptions maintained by the subscription manager + * simultaneously in a list. + */ +#ifndef SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS + #define SUBSCRIPTION_MANAGER_MAX_SUBSCRIPTIONS 10U +#endif + +/** + * @brief Callback function called when receiving a publish. + * + * @param[in] pvIncomingPublishCallbackContext The incoming publish callback context. + * @param[in] pxPublishInfo Deserialized publish information. + */ +typedef void (* IncomingPubCallback_t )( void * pvIncomingPublishCallbackContext, + MQTTPublishInfo_t * pxPublishInfo ); + +/** + * @brief An element in the list of subscriptions. + * + * This subscription manager implementation expects that the array of the + * subscription elements used for storing subscriptions to be initialized to 0. + * + * @note This implementation allows multiple tasks to subscribe to the same topic. + * In this case, another element is added to the subscription list, differing + * in the intended publish callback. Also note that the topic filters are not + * copied in the subscription manager and hence the topic filter strings need to + * stay in scope until unsubscribed. + */ +typedef struct subscriptionElement +{ + IncomingPubCallback_t pxIncomingPublishCallback; + void * pvIncomingPublishCallbackContext; + uint16_t usFilterStringLength; + const char * pcSubscriptionFilterString; +} SubscriptionElement_t; + +/** + * @brief Add a subscription to the subscription list. + * + * @note Multiple tasks can be subscribed to the same topic with different + * context-callback pairs. However, a single context-callback pair may only be + * associated to the same topic filter once. + * + * @param[in] pxSubscriptionList The pointer to the subscription list array. + * @param[in] pcTopicFilterString Topic filter string of subscription. + * @param[in] usTopicFilterLength Length of topic filter string. + * @param[in] pxIncomingPublishCallback Callback function for the subscription. + * @param[in] pvIncomingPublishCallbackContext Context for the subscription callback. + * + * @return `true` if subscription added or exists, `false` if insufficient memory. + */ +bool addSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength, + IncomingPubCallback_t pxIncomingPublishCallback, + void * pvIncomingPublishCallbackContext ); + +/** + * @brief Remove a subscription from the subscription list. + * + * @note If the topic filter exists multiple times in the subscription list, + * then every instance of the subscription will be removed. + * + * @param[in] pxSubscriptionList The pointer to the subscription list array. + * @param[in] pcTopicFilterString Topic filter of subscription. + * @param[in] usTopicFilterLength Length of topic filter. + */ +void removeSubscription( SubscriptionElement_t * pxSubscriptionList, + const char * pcTopicFilterString, + uint16_t usTopicFilterLength ); + +/** + * @brief Handle incoming publishes by invoking the callbacks registered + * for the incoming publish's topic filter. + * + * @param[in] pxSubscriptionList The pointer to the subscription list array. + * @param[in] pxPublishInfo Info of incoming publish. + * + * @return `true` if an application callback could be invoked; + * `false` otherwise. + */ +bool handleIncomingPublishes( SubscriptionElement_t * pxSubscriptionList, + MQTTPublishInfo_t * pxPublishInfo ); + +#endif /* SUBSCRIPTION_MANAGER_H */ diff --git a/bsp/aws_libraries/demos/demo_runner/aws_demo.c b/bsp/aws_libraries/demos/demo_runner/aws_demo.c new file mode 100644 index 0000000..3aae7be --- /dev/null +++ b/bsp/aws_libraries/demos/demo_runner/aws_demo.c @@ -0,0 +1,95 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_demo.c + * @brief Demo + */ +/* The config header is always included first. */ +#include "iot_config.h" + +#include "FreeRTOS.h" +#include "aws_clientcredential.h" + + +/*-----------------------------------------------------------*/ + +/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) +{ + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle + * task's state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} +/*-----------------------------------------------------------*/ + +/** + * @brief This is to provide the memory that is used by the RTOS daemon/time task. + * + * If configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetTimerTaskMemory() to provide the memory that is + * used by the RTOS daemon/time task. + */ +void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ) +{ + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle + * task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/demos/demo_runner/aws_demo_network_addr.c b/bsp/aws_libraries/demos/demo_runner/aws_demo_network_addr.c new file mode 100644 index 0000000..132cd4f --- /dev/null +++ b/bsp/aws_libraries/demos/demo_runner/aws_demo_network_addr.c @@ -0,0 +1,106 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file aws_demo_network_addr.c + * @brief Demo default network address information + */ +#include "iot_config.h" + +#include "FreeRTOS.h" +#include "FreeRTOS_IP.h" +#include "aws_clientcredential.h" + +/* Default MAC address configuration. The demo creates a virtual network + * connection that uses this MAC address by accessing the raw Ethernet data + * to and from a real network connection on the host PC. See the + * configNETWORK_INTERFACE_TO_USE definition for information on how to configure + * the real network connection to use. */ +uint8_t ucMACAddress[ 6 ] = +{ + configMAC_ADDR0, + configMAC_ADDR1, + configMAC_ADDR2, + configMAC_ADDR3, + configMAC_ADDR4, + configMAC_ADDR5 +}; + +/* The default IP and MAC address used by the demo. The address configuration + * defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is + * 1 but a DHCP server could not be contacted. See the online documentation for + * more information. In both cases the node can be discovered using + * "ping RTOSDemo". */ +static const uint8_t ucIPAddress[ 4 ] = +{ + configIP_ADDR0, + configIP_ADDR1, + configIP_ADDR2, + configIP_ADDR3 +}; +static const uint8_t ucNetMask[ 4 ] = +{ + configNET_MASK0, + configNET_MASK1, + configNET_MASK2, + configNET_MASK3 +}; +static const uint8_t ucGatewayAddress[ 4 ] = +{ + configGATEWAY_ADDR0, + configGATEWAY_ADDR1, + configGATEWAY_ADDR2, + configGATEWAY_ADDR3 +}; +static const uint8_t ucDNSServerAddress[ 4 ] = +{ + configDNS_SERVER_ADDR0, + configDNS_SERVER_ADDR1, + configDNS_SERVER_ADDR2, + configDNS_SERVER_ADDR3 +}; + + +void vApplicationIPInit( void ) +{ + FreeRTOS_IPInit( ucIPAddress, + ucNetMask, + ucGatewayAddress, + ucDNSServerAddress, + ucMACAddress ); +} + + +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 ) + + const char * pcApplicationHostnameHook( void ) + { + /* This function will be called during the DHCP: the machine will be registered + * with an IP address plus this name. */ + return clientcredentialIOT_THING_NAME; + } + +#endif +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/demos/demo_runner/iot_demo_freertos.c b/bsp/aws_libraries/demos/demo_runner/iot_demo_freertos.c new file mode 100644 index 0000000..d4ca395 --- /dev/null +++ b/bsp/aws_libraries/demos/demo_runner/iot_demo_freertos.c @@ -0,0 +1,446 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_demo_freertos.c + * @brief Generic demo runner for C SDK libraries on FreeRTOS. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +#include +#include "aws_clientcredential.h" +#include "aws_clientcredential_keys.h" +#include "iot_demo_logging.h" +#include "iot_network_manager_private.h" +#include "platform/iot_threads.h" +#include "aws_demo.h" +#include "iot_init.h" + +static IotNetworkManagerSubscription_t subscription = IOT_NETWORK_MANAGER_SUBSCRIPTION_INITIALIZER; + +/* Semaphore used to wait for a network to be available. */ +static IotSemaphore_t demoNetworkSemaphore; + +/* Variable used to indicate the connected network. */ +static uint32_t demoConnectedNetwork = AWSIOT_NETWORK_TYPE_NONE; + +/*-----------------------------------------------------------*/ + +static uint32_t _getConnectedNetworkForDemo( demoContext_t * pDemoContext ) +{ + uint32_t ret = ( AwsIotNetworkManager_GetConnectedNetworks() & pDemoContext->networkTypes ); + + if( ( ret & AWSIOT_NETWORK_TYPE_WIFI ) == AWSIOT_NETWORK_TYPE_WIFI ) + { + ret = AWSIOT_NETWORK_TYPE_WIFI; + } + else if( ( ret & AWSIOT_NETWORK_TYPE_BLE ) == AWSIOT_NETWORK_TYPE_BLE ) + { + ret = AWSIOT_NETWORK_TYPE_BLE; + } + else if( ( ret & AWSIOT_NETWORK_TYPE_ETH ) == AWSIOT_NETWORK_TYPE_ETH ) + { + ret = AWSIOT_NETWORK_TYPE_ETH; + } + else + { + ret = AWSIOT_NETWORK_TYPE_NONE; + } + + return ret; +} + +/*-----------------------------------------------------------*/ + +static uint32_t _waitForDemoNetworkConnection( demoContext_t * pDemoContext ) +{ + IotSemaphore_Wait( &demoNetworkSemaphore ); + + return _getConnectedNetworkForDemo( pDemoContext ); +} + +/*-----------------------------------------------------------*/ + +static void _onNetworkStateChangeCallback( uint32_t network, + AwsIotNetworkState_t state, + void * pContext ) +{ + const IotNetworkInterface_t * pNetworkInterface = NULL; + void * pConnectionParams = NULL, * pCredentials = NULL; + uint32_t disconnectedNetworks = AWSIOT_NETWORK_TYPE_NONE; + + demoContext_t * pDemoContext = ( demoContext_t * ) pContext; + + if( ( state == eNetworkStateConnected ) && ( demoConnectedNetwork == AWSIOT_NETWORK_TYPE_NONE ) ) + { + demoConnectedNetwork = network; + IotSemaphore_Post( &demoNetworkSemaphore ); + + /* Disable the disconnected networks to save power and reclaim any unused memory. */ + disconnectedNetworks = configENABLED_NETWORKS & ( ~demoConnectedNetwork ); + + if( disconnectedNetworks != AWSIOT_NETWORK_TYPE_NONE ) + { + AwsIotNetworkManager_DisableNetwork( disconnectedNetworks ); + } + + if( pDemoContext->networkConnectedCallback != NULL ) + { + pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( network ); + pConnectionParams = AwsIotNetworkManager_GetConnectionParams( network ); + pCredentials = AwsIotNetworkManager_GetCredentials( network ), + + pDemoContext->networkConnectedCallback( true, + clientcredentialIOT_THING_NAME, + pConnectionParams, + pCredentials, + pNetworkInterface ); + } + } + else if( ( state == eNetworkStateEnabled ) && ( demoConnectedNetwork == network ) ) + { + if( pDemoContext->networkDisconnectedCallback != NULL ) + { + pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( network ); + pDemoContext->networkDisconnectedCallback( pNetworkInterface ); + } + + /* Re-enable all the networks for the demo for reconnection. */ + disconnectedNetworks = configENABLED_NETWORKS & ( ~demoConnectedNetwork ); + + if( disconnectedNetworks != AWSIOT_NETWORK_TYPE_NONE ) + { + AwsIotNetworkManager_EnableNetwork( disconnectedNetworks ); + } + + demoConnectedNetwork = _getConnectedNetworkForDemo( pDemoContext ); + + if( demoConnectedNetwork != AWSIOT_NETWORK_TYPE_NONE ) + { + if( pDemoContext->networkConnectedCallback != NULL ) + { + pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( demoConnectedNetwork ); + pConnectionParams = AwsIotNetworkManager_GetConnectionParams( demoConnectedNetwork ); + pCredentials = AwsIotNetworkManager_GetCredentials( demoConnectedNetwork ); + + pDemoContext->networkConnectedCallback( true, + clientcredentialIOT_THING_NAME, + pConnectionParams, + pCredentials, + pNetworkInterface ); + } + } + } +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Initialize the common libraries, Mqtt library and network manager. + * + * @return `EXIT_SUCCESS` if all libraries were successfully initialized; + * `EXIT_FAILURE` otherwise. + */ +static int _initialize( demoContext_t * pContext ) +{ + int status = EXIT_SUCCESS; + bool commonLibrariesInitialized = false; + bool semaphoreCreated = false; + + /* Initialize the C-SDK common libraries. This function must be called + * once (and only once) before calling any other C-SDK function. */ + if( IotSdk_Init() == true ) + { + commonLibrariesInitialized = true; + } + else + { + IotLogInfo( "Failed to initialize the common library." ); + status = EXIT_FAILURE; + } + + if( status == EXIT_SUCCESS ) + { + if( AwsIotNetworkManager_Init() != pdTRUE ) + { + IotLogError( "Failed to initialize network manager library." ); + status = EXIT_FAILURE; + } + } + + if( status == EXIT_SUCCESS ) + { + /* Create semaphore to signal that a network is available for the demo. */ + if( IotSemaphore_Create( &demoNetworkSemaphore, 0, 1 ) != true ) + { + IotLogError( "Failed to create semaphore to wait for a network connection." ); + status = EXIT_FAILURE; + } + else + { + semaphoreCreated = true; + } + } + + if( status == EXIT_SUCCESS ) + { + /* Subscribe for network state change from Network Manager. */ + if( AwsIotNetworkManager_SubscribeForStateChange( pContext->networkTypes, + _onNetworkStateChangeCallback, + pContext, + &subscription ) != pdTRUE ) + { + IotLogError( "Failed to subscribe network state change callback." ); + status = EXIT_FAILURE; + } + } + + /* Initialize all the networks configured for the device. */ + if( status == EXIT_SUCCESS ) + { + if( AwsIotNetworkManager_EnableNetwork( configENABLED_NETWORKS ) != configENABLED_NETWORKS ) + { + IotLogError( "Failed to initialize all the networks configured for the device." ); + status = EXIT_FAILURE; + } + } + + if( status == EXIT_SUCCESS ) + { + /* Wait for network configured for the demo to be initialized. */ + if( pContext->networkTypes != AWSIOT_NETWORK_TYPE_NONE ) + { + demoConnectedNetwork = _getConnectedNetworkForDemo( pContext ); + + if( demoConnectedNetwork == AWSIOT_NETWORK_TYPE_NONE ) + { + /* Network not yet initialized. Block for a network to be initialized. */ + IotLogInfo( "No networks connected for the demo. Waiting for a network connection. " ); + demoConnectedNetwork = _waitForDemoNetworkConnection( pContext ); + } + } + } + + if( status == EXIT_FAILURE ) + { + if( semaphoreCreated == true ) + { + IotSemaphore_Destroy( &demoNetworkSemaphore ); + } + + if( commonLibrariesInitialized == true ) + { + IotSdk_Cleanup(); + } + } + + return status; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Clean up the common libraries and the MQTT library. + */ +static void _cleanup( void ) +{ + /* Remove network manager subscription */ + AwsIotNetworkManager_RemoveSubscription( subscription ); + /* Disable all the networks used by the demo.*/ + AwsIotNetworkManager_DisableNetwork( configENABLED_NETWORKS ); + IotSemaphore_Destroy( &demoNetworkSemaphore ); + IotSdk_Cleanup(); +} + +/*-----------------------------------------------------------*/ + +void runDemoTask( void * pArgument ) +{ + demoContext_t * pContext = ( demoContext_t * ) pArgument; + const IotNetworkInterface_t * pNetworkInterface = NULL; + void * pConnectionParams = NULL, * pCredentials = NULL; + int status; + + + #ifdef democonfigMEMORY_ANALYSIS + democonfigMEMORY_ANALYSIS_STACK_DEPTH_TYPE xBeforeDemoTaskWaterMark, xAfterDemoTaskWaterMark = 0; + xBeforeDemoTaskWaterMark = democonfigMEMORY_ANALYSIS_STACK_WATERMARK( NULL ); + + size_t xBeforeDemoHeapSize, xAfterDemoHeapSize = 0; + xBeforeDemoHeapSize = democonfigMEMORY_ANALYSIS_MIN_EVER_HEAP_SIZE(); + #endif /* democonfigMEMORY_ANALYSIS */ + + + /* DO NOT EDIT - This demo start marker is used in the test framework to + * determine the start of a demo. */ + IotLogInfo( "---------STARTING DEMO---------\n" ); + + status = _initialize( pContext ); + + if( status == EXIT_SUCCESS ) + { + IotLogInfo( "Successfully initialized the demo. Network type for the demo: %d", demoConnectedNetwork ); + + pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( demoConnectedNetwork ); + pConnectionParams = AwsIotNetworkManager_GetConnectionParams( demoConnectedNetwork ); + pCredentials = AwsIotNetworkManager_GetCredentials( demoConnectedNetwork ); + + /* Run the demo. */ + status = pContext->demoFunction( true, + clientcredentialIOT_THING_NAME, + pConnectionParams, + pCredentials, + pNetworkInterface ); + + #ifdef democonfigMEMORY_ANALYSIS + /* If memory analysis is enabled metrics regarding the heap and stack usage of the demo will print. */ + /* This format is used for easier parsing and creates an avenue for future metrics to be added. */ + xAfterDemoHeapSize = democonfigMEMORY_ANALYSIS_MIN_EVER_HEAP_SIZE(); + IotLogInfo( "memory_metrics::freertos_heap::before::bytes::%u", xBeforeDemoHeapSize ); + IotLogInfo( "memory_metrics::freertos_heap::after::bytes::%u", xAfterDemoHeapSize ); + + xAfterDemoTaskWaterMark = democonfigMEMORY_ANALYSIS_STACK_WATERMARK( NULL ); + IotLogInfo( "memory_metrics::demo_task_stack::before::bytes::%u", xBeforeDemoTaskWaterMark ); + IotLogInfo( "memory_metrics::demo_task_stack::after::bytes::%u", xAfterDemoTaskWaterMark ); + #endif /* democonfigMEMORY_ANALYSIS */ + + /* Give a chance to drain the logging queue to increase the probability + * of the following messages used by the test framework not getting + * dropped. */ + vTaskDelay( pdMS_TO_TICKS( 1000 ) ); + + /* Log the demo status. */ + if( status == EXIT_SUCCESS ) + { + /* DO NOT EDIT - This message is used in the test framework to + * determine whether or not the demo was successful. */ + IotLogInfo( "Demo completed successfully." ); + } + else + { + IotLogError( "Error running demo." ); + } + + _cleanup(); + } + else + { + IotLogError( "Failed to initialize the demo. exiting..." ); + } + + /* DO NOT EDIT - This demo end marker is used in the test framework to + * determine the end of a demo. */ + IotLogInfo( "-------DEMO FINISHED-------\n" ); +} + +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) + + BaseType_t xApplicationDNSQueryHook( const char * pcName ) + { + BaseType_t xReturn; + + /* Determine if a name lookup is for this node. Two names are given + * to this node: that returned by pcApplicationHostnameHook() and that set + * by mainDEVICE_NICK_NAME. */ + if( strcmp( pcName, pcApplicationHostnameHook() ) == 0 ) + { + xReturn = pdPASS; + } + else if( strcmp( pcName, mainDEVICE_NICK_NAME ) == 0 ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) */ + +/*-----------------------------------------------------------*/ + +/* It is recommended to implement hooks that use platform specific APIs. This allows + * for better error messages and recovery. Should platform specific hooks be implemented, + * add this macro to iot_config.h to avoid compiling these symbols.*/ +#ifndef iotconfigUSE_PORT_SPECIFIC_HOOKS + +/** + * @brief Warn user if pvPortMalloc fails. + * + * Called if a call to pvPortMalloc() fails because there is insufficient + * free memory available in the FreeRTOS heap. pvPortMalloc() is called + * internally by FreeRTOS API functions that create tasks, queues, software + * timers, and semaphores. The size of the FreeRTOS heap is set by the + * configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. + * + */ + void vApplicationMallocFailedHook() + { + configPRINT_STRING( ( "ERROR: Malloc failed to allocate memory\r\n" ) ); + taskDISABLE_INTERRUPTS(); + + /* Loop forever */ + for( ; ; ) + { + } + } + +/*-----------------------------------------------------------*/ + +/** + * @brief Loop forever if stack overflow is detected. + * + * If configCHECK_FOR_STACK_OVERFLOW is set to 1, + * this hook provides a location for applications to + * define a response to a stack overflow. + * + * Use this hook to help identify that a stack overflow + * has occurred. + * + */ + void vApplicationStackOverflowHook( TaskHandle_t xTask, + char * pcTaskName ) + { + configPRINT_STRING( ( "ERROR: stack overflow\r\n" ) ); + portDISABLE_INTERRUPTS(); + + /* Unused Parameters */ + ( void ) xTask; + ( void ) pcTaskName; + + /* Loop forever */ + for( ; ; ) + { + } + } +#endif /* iotconfigUSE_PORT_SPECIFIC_HOOKS */ +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/demos/demo_runner/iot_demo_runner.c b/bsp/aws_libraries/demos/demo_runner/iot_demo_runner.c new file mode 100644 index 0000000..6c03003 --- /dev/null +++ b/bsp/aws_libraries/demos/demo_runner/iot_demo_runner.c @@ -0,0 +1,96 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/* Called from all the example projects to start tasks that demonstrate Amazon + * FreeRTOS libraries. + * + * If the project was created using the AWS console then this file will have been + * auto generated and only reference and start the demos that were selected in the + * console. If the project was obtained from a source control repository then this + * file will reference all the available and the developer can selectively comment + * in or out the demos to execute. */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Includes for library initialization. */ +#include "iot_demo_runner.h" +#include "platform/iot_threads.h" +#include "types/iot_network_types.h" + +#include "aws_demo.h" +#include "aws_demo_config.h" + +/* Forward declaration of demo entry function to be renamed from #define in + * aws_demo_config.h */ +int DEMO_entryFUNCTION( bool awsIotMqttMode, + const char * pIdentifier, + void * pNetworkServerInfo, + void * pNetworkCredentialInfo, + const IotNetworkInterface_t * pNetworkInterface ); + + +/* Forward declaration of network connected DEMO callback to be renamed from + * #define in aws_demo_config.h */ +#ifdef DEMO_networkConnectedCallback + void DEMO_networkConnectedCallback( bool awsIotMqttMode, + const char * pIdentifier, + void * pNetworkServerInfo, + void * pNetworkCredentialInfo, + const IotNetworkInterface_t * pNetworkInterface ); +#else + #define DEMO_networkConnectedCallback ( NULL ) +#endif + + +/* Forward declaration of network disconnected DEMO callback to be renamed from #define in aws_demo_config.h */ +#ifdef DEMO_networkDisconnectedCallback + void DEMO_networkDisconnectedCallback( const IotNetworkInterface_t * pNetworkInterface ); +#else + #define DEMO_networkDisconnectedCallback ( NULL ) +#endif + +/*-----------------------------------------------------------*/ + +/** + * @brief Runs the one demo configured in the config file. + */ +void DEMO_RUNNER_RunDemos( void ) +{ + /* These demos are shared with the C SDK and perform their own initialization and cleanup. */ + + static demoContext_t mqttDemoContext = + { + .networkTypes = democonfigNETWORK_TYPES, + .demoFunction = DEMO_entryFUNCTION, + .networkConnectedCallback = DEMO_networkConnectedCallback, + .networkDisconnectedCallback = DEMO_networkDisconnectedCallback + }; + + Iot_CreateDetachedThread( runDemoTask, + &mqttDemoContext, + democonfigDEMO_PRIORITY, + democonfigDEMO_STACKSIZE ); +} diff --git a/bsp/aws_libraries/demos/dev_mode_key_provisioning/include/aws_dev_mode_key_provisioning.h b/bsp/aws_libraries/demos/dev_mode_key_provisioning/include/aws_dev_mode_key_provisioning.h new file mode 100644 index 0000000..1afe272 --- /dev/null +++ b/bsp/aws_libraries/demos/dev_mode_key_provisioning/include/aws_dev_mode_key_provisioning.h @@ -0,0 +1,258 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + + + +/** + * @file aws_dev_mode_key_provsioning.h + * @brief Provisioning example code for developers. + * + * Helpers for importing device private key and device + * certificate for use with AWS connectivity libraries. + * + * \warn This code is provided for example purposes only, and + * should not be used in production code. + */ + +#ifndef _AWS_DEV_MODE_KEY_PROVISIONING_H_ +#define _AWS_DEV_MODE_KEY_PROVISIONING_H_ + +#include "core_pkcs11_config.h" +#include "core_pkcs11.h" + +typedef struct ProvisioningParams_t +{ + uint8_t * pucClientPrivateKey; /**< Pointer to the device private key in PEM format. + * See tools/certificate_configuration/PEMfileToCString.html + * for help with formatting.*/ + uint32_t ulClientPrivateKeyLength; /**< Length of the private key data, in bytes. */ + uint8_t * pucClientCertificate; /**< Pointer to the device certificate in PEM format. + * See tools/certificate_configuration/PEMfileToCString.html + * for help with formatting.*/ + uint32_t ulClientCertificateLength; /**< Length of the device certificate in bytes. */ + uint8_t * pucJITPCertificate; /**< Pointer to the Just-In-Time Provisioning (JITP) certificate in + * PEM format. + * - This is REQUIRED if JITP is being used. + * - If you are not using JITP, this certificate + * is not needed and should be set to NULL. + * - See tools/certificate_configuration/PEMfileToCString.html + * for help with formatting. + * - See https://aws.amazon.com/blogs/iot/setting-up-just-in-time-provisioning-with-aws-iot-core/ + * for more information about getting started with JITP */ + uint32_t ulJITPCertificateLength; /**< Length of the Just-In-Time Provisioning (JITP) certificate in bytes. + * If JITP is not being used, this value should be set to 0. */ +} ProvisioningParams_t; + +/** \brief Provisions device with default credentials. + * + * Imports the certificate and private key located in + * aws_clientcredential_keys.h to device NVM. + * + * \return CKR_OK upon successful credential setup. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV vDevModeKeyProvisioning( void ); + +/** \brief Provisiong a device given a valid PKCS #11 session. + * + * \param[in] xSession A valid PKCS #11 session. + * \param[in] pxParams Pointer to an initialized provisioning + * structure. + * + * \return CKR_OK upon successful credential setup. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xProvisionDevice( CK_SESSION_HANDLE xSession, + ProvisioningParams_t * pxParams ); + +/** \brief Provisions device with provided credentials. + * + * \param[in] xParams Provisioning parameters for credentials + * to be provisioned. + * + * \return CKR_OK upon successful credential setup. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV vAlternateKeyProvisioning( ProvisioningParams_t * xParams ); + +/** \brief Provisions a private key using PKCS #11 library. + * + * \param[in] xSession An initialized session handle. + * \param[in] pucPrivateKey Pointer to private key. Key may either be PEM formatted + * or ASN.1 DER encoded. + * \param[in] xPrivateKeyLength Length of the data at pucPrivateKey, in bytes. + * \param[in] pucLabel PKCS #11 CKA_LABEL attribute value to be used for key. + * This should be a string values. See core_pkcs11_config.h + * \param[out] pxObjectHandle Points to the location that receives the PKCS #11 + * private key handle created. + * + * \return CKR_OK upon successful key creation. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xProvisionPrivateKey( CK_SESSION_HANDLE xSession, + uint8_t * pucPrivateKey, + size_t xPrivateKeyLength, + uint8_t * pucLabel, + CK_OBJECT_HANDLE_PTR pxObjectHandle ); + +/** \brief Imports a public key into the PKCS #11 module. + * + * \param[in] xSession A valid PKCS #11 session handle. + * \param[in] pucKey Pointer to public key. Key may either be PEM formatted + * or ASN.1 DER encoded. + * \param[in] xKeyLength Length of the data at pucPrivateKey, in bytes. + * \param[in] xPublicKeyType The type of key- either CKK_RSA or CKK_EC. + * \param[in] pucPublicKeyLabel PKCS #11 CKA_LABEL attribute value to be used for key. + * This should be a string values. See core_pkcs11_config.h. + * \param[out] pxPublicKeyHandle Points to the location that receives the PKCS #11 public + * key handle created. + * + * \return CKR_OK upon successful key creation. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xProvisionPublicKey( CK_SESSION_HANDLE xSession, + uint8_t * pucKey, + size_t xKeyLength, + CK_KEY_TYPE xPublicKeyType, + uint8_t * pucPublicKeyLabel, + CK_OBJECT_HANDLE_PTR pxPublicKeyHandle ); + + +/** \brief Imports a certificate into the PKCS #11 module. + * + * \param[in] xSession A valid PKCS #11 session handle. + * \param[in] pucCertificate Pointer to a PEM certificate. + * See tools/certificate_configuration/PEMfileToCString.html + * for help with formatting. + * \param[in] xCertificateLength Length of pucCertificate, in bytes. + * \param[in] pucLabel PKCS #11 label attribute value for certificate to be imported. + * This should be a string value. See core_pkcs11.h. + * This should be a string value. See core_pkcs11_config.h. + * \param[out] pxObjectHandle Points to the location that receives the PKCS #11 + * certificate handle created. + * + * \return CKR_OK if certificate import succeeded. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xProvisionCertificate( CK_SESSION_HANDLE xSession, + uint8_t * pucCertificate, + size_t xCertificateLength, + uint8_t * pucLabel, + CK_OBJECT_HANDLE_PTR pxObjectHandle ); + +/** \brief Generates an RSA key pair. + * + * \param[in] xSession A valid PKCS #11 session handle. + * \param[in] pucPrivateKeyLabel PKCS #11 label attribute value for private key to be created. + * This should be a string value. See core_pkcs11_config.h. + * \param[in] pucPublicKeyLabel PKCS #11 label attribute value for public key to be created. + * This should be a string value. See core_pkcs11_config.h. + * \param[out] pxPrivateKeyHandle Points to the location that receives the PKCS #11 private + * key handle created. + * \param[out] pxPublicKeyHandle Points to the location that receives the PKCS #11 public + * key handle created. + * + * \return CKR_OK if RSA key pair generation succeeded. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xProvisionGenerateKeyPairRSA( CK_SESSION_HANDLE xSession, + uint8_t * pucPrivateKeyLabel, + uint8_t * pucPublicKeyLabel, + CK_OBJECT_HANDLE_PTR pxPrivateKeyHandle, + CK_OBJECT_HANDLE_PTR pxPublicKeyHandle ); + +/** \brief Generates an elliptic curve key pair. + * + * \param[in] xSession A valid PKCS #11 session handle. + * \param[in] pucPrivateKeyLabel PKCS #11 label attribute value for private key to be created. + * This should be a string value. See core_pkcs11_config.h. + * \param[in] pucPublicKeyLabel PKCS #11 label attribute value for public key to be created. + * This should be a string value. See core_pkcs11_config.h. + * \param[out] pxPrivateKeyHandle Points to the location that receives the PKCS #11 private + * key handle created. + * \param[out] pxPublicKeyHandle Points to the location that receives the PKCS #11 public + * key handle created. + * + * \return CKR_OK if EC key pair generation succeeded. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xProvisionGenerateKeyPairEC( CK_SESSION_HANDLE xSession, + uint8_t * pucPrivateKeyLabel, + uint8_t * pucPublicKeyLabel, + CK_OBJECT_HANDLE_PTR pxPrivateKeyHandle, + CK_OBJECT_HANDLE_PTR pxPublicKeyHandle ); + +/** + *\brief Destroys FreeRTOS credentials stored in device PKCS #11 module. + * + * \note Not all ports support the deletion of all objects. Successful + * function return only indicates that all objects for which destroy is + * supported on the port were erased from non-volatile memory. + * + * Destroys objects with the following labels, if applicable: + * pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS, + * pkcs11configLABEL_CODE_VERIFICATION_KEY, + * pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + * pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS + * + * \param[in] xSession A valid PKCS #11 session handle. + * + * \return CKR_OK if all credentials were destroyed. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xDestroyDefaultCryptoObjects( CK_SESSION_HANDLE xSession ); + +/** + * \brief Destroys specified credentials in PKCS #11 module. + * + * \note Some ports only support lookup of objects by label (and + * not label + class). For these ports, only the label field is used + * for determining what objects to destroy. + * + * \note Not all ports support the deletion of all objects. Successful + * function return only indicates that all objects for which destroy is + * supported on the port were erased from non-volatile memory. + * + * \param[in] xSession A valid PKCS #11 session handle. + * \param[in] ppxPkcsLabels An array of pointers to object labels. + * Labels are assumed to be NULL terminated + * strings. + * \param[in] pxClass An array of object classes, corresponding + * to the array of ppxPkcsLabels. For example + * the first label pointer and first class in + * ppxPkcsLabels are used in combination for + * lookup of the object to be deleted. + * \param[in] ulCount The number of label-class pairs passed in + * to be destroyed. + * + * \return CKR_OK if all credentials were destroyed. + * Otherwise, a positive PKCS #11 error code. + */ +CK_RV xDestroyProvidedObjects( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR * ppxPkcsLabels, + CK_OBJECT_CLASS * pxClass, + CK_ULONG ulCount ); + +#endif /* _AWS_DEV_MODE_KEY_PROVISIONING_H_ */ diff --git a/bsp/aws_libraries/demos/dev_mode_key_provisioning/src/aws_dev_mode_key_provisioning.c b/bsp/aws_libraries/demos/dev_mode_key_provisioning/src/aws_dev_mode_key_provisioning.c new file mode 100644 index 0000000..23b8873 --- /dev/null +++ b/bsp/aws_libraries/demos/dev_mode_key_provisioning/src/aws_dev_mode_key_provisioning.c @@ -0,0 +1,1344 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + + +/** + * @file aws_dev_mode_key_provisioning.c + * @brief Simple key provisioning example using PKCS #11 + * + * A simple example to demonstrate key and certificate provisioning in + * flash using PKCS #11 interface. This should be replaced + * by production ready key provisioning mechanism. + */ + +/* Standard includes. */ +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* PKCS#11 includes. */ +#include "core_pkcs11_config.h" +#include "core_pkcs11.h" + +/* Client credential includes. */ +#include "aws_clientcredential.h" +#include "aws_clientcredential_keys.h" +#include "iot_default_root_certificates.h" + +/* Key provisioning include. */ +#include "aws_dev_mode_key_provisioning.h" + +/* Utilities include. */ +#include "core_pki_utils.h" + +/* mbedTLS includes. */ +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" + +/* Default FreeRTOS API for console logging. */ +#define DEV_MODE_KEY_PROVISIONING_PRINT( X ) vLoggingPrintf X + +/* For writing log lines without a prefix. */ +extern void vLoggingPrint( const char * pcFormat ); + +/* Developer convenience override, for lab testing purposes, for generating + * a new default key pair, regardless of whether an existing key pair is present. */ +#define keyprovisioningFORCE_GENERATE_NEW_KEY_PAIR 0 + +/* Internal structure for parsing RSA keys. */ + +/* Length parameters for importing RSA-2048 private keys. */ +#define MODULUS_LENGTH pkcs11RSA_2048_MODULUS_BITS / 8 +#define E_LENGTH 3 +#define D_LENGTH pkcs11RSA_2048_MODULUS_BITS / 8 +#define PRIME_1_LENGTH 128 +#define PRIME_2_LENGTH 128 +#define EXPONENT_1_LENGTH 128 +#define EXPONENT_2_LENGTH 128 +#define COEFFICIENT_LENGTH 128 + +/* Adding one to all of the lengths because ASN1 may pad a leading 0 byte + * to numbers that could be interpreted as negative */ +typedef struct RsaParams_t +{ + CK_BYTE modulus[ MODULUS_LENGTH + 1 ]; + CK_BYTE e[ E_LENGTH + 1 ]; + CK_BYTE d[ D_LENGTH + 1 ]; + CK_BYTE prime1[ PRIME_1_LENGTH + 1 ]; + CK_BYTE prime2[ PRIME_2_LENGTH + 1 ]; + CK_BYTE exponent1[ EXPONENT_1_LENGTH + 1 ]; + CK_BYTE exponent2[ EXPONENT_2_LENGTH + 1 ]; + CK_BYTE coefficient[ COEFFICIENT_LENGTH + 1 ]; +} RsaParams_t; + +/* Internal structure for capturing the provisioned state of the host device. */ +typedef struct ProvisionedState_t +{ + CK_OBJECT_HANDLE xPrivateKey; + CK_OBJECT_HANDLE xClientCertificate; + CK_OBJECT_HANDLE xPublicKey; + uint8_t * pucDerPublicKey; + uint32_t ulDerPublicKeyLength; + char * pcIdentifier; /* The token label. On some devices, a unique device + * ID might be stored here which can be used as a field + * in the subject of the device certificate. */ +} ProvisionedState_t; + +/* This function can be found in libraries/3rdparty/mbedtls_utils/mbedtls_utils.c. */ +extern int convert_pem_to_der( const unsigned char * pucInput, + size_t xLen, + unsigned char * pucOutput, + size_t * pxOlen ); + +/*-----------------------------------------------------------*/ + +/* Import the specified ECDSA private key into storage. */ +static CK_RV prvProvisionPrivateECKey( CK_SESSION_HANDLE xSession, + uint8_t * pucLabel, + CK_OBJECT_HANDLE_PTR pxObjectHandle, + mbedtls_pk_context * pxMbedPkContext ) +{ + CK_RV xResult = CKR_OK; + CK_FUNCTION_LIST_PTR pxFunctionList = NULL; + CK_BYTE * pxD; /* Private value D. */ + CK_BYTE * pxEcParams = NULL; /* DER-encoding of an ANSI X9.62 Parameters value */ + int lMbedResult = 0; + CK_BBOOL xTrue = CK_TRUE; + CK_KEY_TYPE xPrivateKeyType = CKK_EC; + CK_OBJECT_CLASS xPrivateKeyClass = CKO_PRIVATE_KEY; + mbedtls_ecp_keypair * pxKeyPair = ( mbedtls_ecp_keypair * ) pxMbedPkContext->pk_ctx; + + xResult = C_GetFunctionList( &pxFunctionList ); + +#define EC_PARAMS_LENGTH 10 +#define EC_D_LENGTH 32 + + pxD = pvPortMalloc( EC_D_LENGTH ); + + if( ( pxD == NULL ) ) + { + xResult = CKR_HOST_MEMORY; + } + + if( xResult == CKR_OK ) + { + lMbedResult = mbedtls_mpi_write_binary( &( pxKeyPair->d ), pxD, EC_D_LENGTH ); + + if( lMbedResult != 0 ) + { + DEV_MODE_KEY_PROVISIONING_PRINT( ( "Failed to parse EC private key components. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + } + + if( xResult == CKR_OK ) + { + if( pxKeyPair->grp.id == MBEDTLS_ECP_DP_SECP256R1 ) + { + pxEcParams = ( CK_BYTE * ) ( "\x06\x08" MBEDTLS_OID_EC_GRP_SECP256R1 ); + } + else + { + xResult = CKR_CURVE_NOT_SUPPORTED; + } + } + + if( xResult == CKR_OK ) + { + CK_ATTRIBUTE xPrivateKeyTemplate[] = + { + { CKA_CLASS, NULL /* &xPrivateKeyClass*/, sizeof( CK_OBJECT_CLASS ) }, + { CKA_KEY_TYPE, NULL /* &xPrivateKeyType*/, sizeof( CK_KEY_TYPE ) }, + { CKA_LABEL, pucLabel, ( CK_ULONG ) strlen( ( const char * ) pucLabel ) }, + { CKA_TOKEN, NULL /* &xTrue*/, sizeof( CK_BBOOL ) }, + { CKA_SIGN, NULL /* &xTrue*/, sizeof( CK_BBOOL ) }, + { CKA_EC_PARAMS, NULL /* pxEcParams*/, EC_PARAMS_LENGTH }, + { CKA_VALUE, NULL /* pxD*/, EC_D_LENGTH } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPrivateKeyTemplate[ 0 ].pValue = &xPrivateKeyClass; + xPrivateKeyTemplate[ 1 ].pValue = &xPrivateKeyType; + xPrivateKeyTemplate[ 3 ].pValue = &xTrue; + xPrivateKeyTemplate[ 4 ].pValue = &xTrue; + xPrivateKeyTemplate[ 5 ].pValue = pxEcParams; + xPrivateKeyTemplate[ 6 ].pValue = pxD; + + xResult = pxFunctionList->C_CreateObject( xSession, + ( CK_ATTRIBUTE_PTR ) &xPrivateKeyTemplate, + sizeof( xPrivateKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + pxObjectHandle ); + } + + if( pxD != NULL ) + { + vPortFree( pxD ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Import the specified RSA private key into storage. */ +static CK_RV prvProvisionPrivateRSAKey( CK_SESSION_HANDLE xSession, + uint8_t * pucLabel, + CK_OBJECT_HANDLE_PTR pxObjectHandle, + mbedtls_pk_context * pxMbedPkContext ) +{ + CK_RV xResult = CKR_OK; + CK_FUNCTION_LIST_PTR pxFunctionList = NULL; + int lMbedResult = 0; + CK_KEY_TYPE xPrivateKeyType = CKK_RSA; + mbedtls_rsa_context * xRsaContext = pxMbedPkContext->pk_ctx; + CK_OBJECT_CLASS xPrivateKeyClass = CKO_PRIVATE_KEY; + RsaParams_t * pxRsaParams = NULL; + CK_BBOOL xTrue = CK_TRUE; + + xResult = C_GetFunctionList( &pxFunctionList ); + + pxRsaParams = pvPortMalloc( sizeof( RsaParams_t ) ); + + if( pxRsaParams == NULL ) + { + xResult = CKR_HOST_MEMORY; + } + + if( xResult == CKR_OK ) + { + memset( pxRsaParams, 0, sizeof( RsaParams_t ) ); + + lMbedResult = mbedtls_rsa_export_raw( xRsaContext, + pxRsaParams->modulus, MODULUS_LENGTH + 1, + pxRsaParams->prime1, PRIME_1_LENGTH + 1, + pxRsaParams->prime2, PRIME_2_LENGTH + 1, + pxRsaParams->d, D_LENGTH + 1, + pxRsaParams->e, E_LENGTH + 1 ); + + if( lMbedResult != 0 ) + { + DEV_MODE_KEY_PROVISIONING_PRINT( ( "Failed to parse RSA private key components. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + /* Export Exponent 1, Exponent 2, Coefficient. */ + lMbedResult |= mbedtls_mpi_write_binary( ( mbedtls_mpi const * ) &xRsaContext->DP, pxRsaParams->exponent1, EXPONENT_1_LENGTH + 1 ); + lMbedResult |= mbedtls_mpi_write_binary( ( mbedtls_mpi const * ) &xRsaContext->DQ, pxRsaParams->exponent2, EXPONENT_2_LENGTH + 1 ); + lMbedResult |= mbedtls_mpi_write_binary( ( mbedtls_mpi const * ) &xRsaContext->QP, pxRsaParams->coefficient, COEFFICIENT_LENGTH + 1 ); + + if( lMbedResult != 0 ) + { + DEV_MODE_KEY_PROVISIONING_PRINT( ( "Failed to parse RSA private key Chinese Remainder Theorem variables. \r\n" ) ); + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + } + + if( xResult == CKR_OK ) + { + /* When importing the fields, the pointer is incremented by 1 + * to remove the leading 0 padding (if it existed) and the original field length is used */ + + + CK_ATTRIBUTE xPrivateKeyTemplate[] = + { + { CKA_CLASS, NULL /* &xPrivateKeyClass */, sizeof( CK_OBJECT_CLASS ) }, + { CKA_KEY_TYPE, NULL /* &xPrivateKeyType */, sizeof( CK_KEY_TYPE ) }, + { CKA_LABEL, pucLabel, ( CK_ULONG ) strlen( ( const char * ) pucLabel ) }, + { CKA_TOKEN, NULL /* &xTrue */, sizeof( CK_BBOOL ) }, + { CKA_SIGN, NULL /* &xTrue */, sizeof( CK_BBOOL ) }, + { CKA_MODULUS, pxRsaParams->modulus + 1, MODULUS_LENGTH }, + { CKA_PRIVATE_EXPONENT, pxRsaParams->d + 1, D_LENGTH }, + { CKA_PUBLIC_EXPONENT, pxRsaParams->e + 1, E_LENGTH }, + { CKA_PRIME_1, pxRsaParams->prime1 + 1, PRIME_1_LENGTH }, + { CKA_PRIME_2, pxRsaParams->prime2 + 1, PRIME_2_LENGTH }, + { CKA_EXPONENT_1, pxRsaParams->exponent1 + 1, EXPONENT_1_LENGTH }, + { CKA_EXPONENT_2, pxRsaParams->exponent2 + 1, EXPONENT_2_LENGTH }, + { CKA_COEFFICIENT, pxRsaParams->coefficient + 1, COEFFICIENT_LENGTH } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPrivateKeyTemplate[ 0 ].pValue = &xPrivateKeyClass; + xPrivateKeyTemplate[ 1 ].pValue = &xPrivateKeyType; + xPrivateKeyTemplate[ 3 ].pValue = &xTrue; + xPrivateKeyTemplate[ 4 ].pValue = &xTrue; + + xResult = pxFunctionList->C_CreateObject( xSession, + ( CK_ATTRIBUTE_PTR ) &xPrivateKeyTemplate, + sizeof( xPrivateKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + pxObjectHandle ); + } + + if( NULL != pxRsaParams ) + { + vPortFree( pxRsaParams ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Import the specified private key into storage. */ +CK_RV xProvisionPrivateKey( CK_SESSION_HANDLE xSession, + uint8_t * pucPrivateKey, + size_t xPrivateKeyLength, + uint8_t * pucLabel, + CK_OBJECT_HANDLE_PTR pxObjectHandle ) +{ + CK_RV xResult = CKR_OK; + mbedtls_pk_type_t xMbedKeyType = MBEDTLS_PK_NONE; + int lMbedResult = 0; + mbedtls_pk_context xMbedPkContext = { 0 }; + + mbedtls_pk_init( &xMbedPkContext ); + lMbedResult = mbedtls_pk_parse_key( &xMbedPkContext, pucPrivateKey, xPrivateKeyLength, NULL, 0 ); + + if( lMbedResult != 0 ) + { + DEV_MODE_KEY_PROVISIONING_PRINT( ( "Unable to parse private key.\r\n" ) ); + xResult = CKR_ARGUMENTS_BAD; + } + + /* Determine whether the key to be imported is RSA or EC. */ + if( xResult == CKR_OK ) + { + xMbedKeyType = mbedtls_pk_get_type( &xMbedPkContext ); + + if( xMbedKeyType == MBEDTLS_PK_RSA ) + { + xResult = prvProvisionPrivateRSAKey( xSession, + pucLabel, + pxObjectHandle, + &xMbedPkContext ); + } + else if( ( xMbedKeyType == MBEDTLS_PK_ECDSA ) || ( xMbedKeyType == MBEDTLS_PK_ECKEY ) || ( xMbedKeyType == MBEDTLS_PK_ECKEY_DH ) ) + { + xResult = prvProvisionPrivateECKey( xSession, + pucLabel, + pxObjectHandle, + &xMbedPkContext ); + } + else + { + DEV_MODE_KEY_PROVISIONING_PRINT( ( "Invalid private key type provided. RSA-2048 and EC P-256 keys are supported.\r\n" ) ); + xResult = CKR_ARGUMENTS_BAD; + } + } + + mbedtls_pk_free( &xMbedPkContext ); + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Import the specified public key into storage. */ +CK_RV xProvisionPublicKey( CK_SESSION_HANDLE xSession, + uint8_t * pucKey, + size_t xKeyLength, + CK_KEY_TYPE xPublicKeyType, + uint8_t * pucPublicKeyLabel, + CK_OBJECT_HANDLE_PTR pxPublicKeyHandle ) +{ + CK_RV xResult; + CK_BBOOL xTrue = CK_TRUE; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_OBJECT_CLASS xClass = CKO_PUBLIC_KEY; + int lMbedResult = 0; + mbedtls_pk_context xMbedPkContext = { 0 }; + + xResult = C_GetFunctionList( &pxFunctionList ); + + mbedtls_pk_init( &xMbedPkContext ); + + /* Try parsing the private key using mbedtls_pk_parse_key. */ + lMbedResult = mbedtls_pk_parse_key( &xMbedPkContext, pucKey, xKeyLength, NULL, 0 ); + + /* If mbedtls_pk_parse_key didn't work, maybe the private key is not included in the input passed in. + * Try to parse just the public key. */ + if( lMbedResult != 0 ) + { + lMbedResult = mbedtls_pk_parse_public_key( &xMbedPkContext, pucKey, xKeyLength ); + } + + if( lMbedResult != 0 ) + { + DEV_MODE_KEY_PROVISIONING_PRINT( ( "Failed to parse the public key. \r\n" ) ); + xResult = CKR_ARGUMENTS_BAD; + } + + if( ( xResult == CKR_OK ) && ( xPublicKeyType == CKK_RSA ) ) + { + CK_BYTE xPublicExponent[] = { 0x01, 0x00, 0x01 }; + CK_BYTE xModulus[ MODULUS_LENGTH + 1 ] = { 0 }; + + lMbedResult = mbedtls_rsa_export_raw( ( mbedtls_rsa_context * ) xMbedPkContext.pk_ctx, + ( unsigned char * ) &xModulus, MODULUS_LENGTH + 1, + NULL, 0, + NULL, 0, + NULL, 0, + NULL, 0 ); + CK_ATTRIBUTE xPublicKeyTemplate[] = + { + { CKA_CLASS, NULL /* &xClass */, sizeof( CK_OBJECT_CLASS ) }, + { CKA_KEY_TYPE, NULL /* &xPublicKeyType */, sizeof( CK_KEY_TYPE ) }, + { CKA_TOKEN, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_MODULUS, NULL /* &xModulus + 1 */, MODULUS_LENGTH }, /* Extra byte allocated at beginning for 0 padding. */ + { CKA_VERIFY, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_PUBLIC_EXPONENT, NULL /* xPublicExponent */, sizeof( xPublicExponent ) }, + { CKA_LABEL, pucPublicKeyLabel, strlen( ( const char * ) pucPublicKeyLabel ) } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPublicKeyTemplate[ 0 ].pValue = &xClass; + xPublicKeyTemplate[ 1 ].pValue = &xPublicKeyType; + xPublicKeyTemplate[ 2 ].pValue = &xTrue; + xPublicKeyTemplate[ 3 ].pValue = &xModulus + 1; + xPublicKeyTemplate[ 4 ].pValue = &xTrue; + xPublicKeyTemplate[ 5 ].pValue = xPublicExponent; + + xResult = pxFunctionList->C_CreateObject( xSession, + ( CK_ATTRIBUTE_PTR ) xPublicKeyTemplate, + sizeof( xPublicKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + pxPublicKeyHandle ); + } + else if( ( xResult == CKR_OK ) && ( xPublicKeyType == CKK_EC ) ) + { + CK_BYTE xEcParams[] = pkcs11DER_ENCODED_OID_P256; + size_t xLength; + CK_BYTE xEcPoint[ 256 ] = { 0 }; + + mbedtls_ecdsa_context * pxEcdsaContext = ( mbedtls_ecdsa_context * ) xMbedPkContext.pk_ctx; + + /* DER encoded EC point. Leave 2 bytes for the tag and length. */ + lMbedResult = mbedtls_ecp_point_write_binary( &pxEcdsaContext->grp, + &pxEcdsaContext->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &xLength, + xEcPoint + 2, + sizeof( xEcPoint ) - 2 ); + xEcPoint[ 0 ] = 0x04; /* Octet string. */ + xEcPoint[ 1 ] = ( CK_BYTE ) xLength; + + CK_ATTRIBUTE xPublicKeyTemplate[] = + { + { CKA_CLASS, NULL /* &xClass */, sizeof( xClass ) }, + { CKA_KEY_TYPE, NULL /* &xPublicKeyType */, sizeof( xPublicKeyType ) }, + { CKA_TOKEN, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_VERIFY, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_EC_PARAMS, NULL /* xEcParams */, sizeof( xEcParams ) }, + { CKA_EC_POINT, NULL /* xEcPoint */, xLength + 2 }, + { CKA_LABEL, pucPublicKeyLabel, strlen( ( const char * ) pucPublicKeyLabel ) } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPublicKeyTemplate[ 0 ].pValue = &xClass; + xPublicKeyTemplate[ 1 ].pValue = &xPublicKeyType; + xPublicKeyTemplate[ 2 ].pValue = &xTrue; + xPublicKeyTemplate[ 3 ].pValue = &xTrue; + xPublicKeyTemplate[ 4 ].pValue = xEcParams; + xPublicKeyTemplate[ 5 ].pValue = xEcPoint; + + xResult = pxFunctionList->C_CreateObject( xSession, + ( CK_ATTRIBUTE_PTR ) xPublicKeyTemplate, + sizeof( xPublicKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + pxPublicKeyHandle ); + } + else + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + configPRINTF( ( "Invalid key type. Supported options are CKK_RSA and CKK_EC" ) ); + } + + mbedtls_pk_free( &xMbedPkContext ); + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Generate a new 2048-bit RSA key pair. Please note that C_GenerateKeyPair for + * RSA keys is not supported by the FreeRTOS mbedTLS PKCS #11 port. */ +CK_RV xProvisionGenerateKeyPairRSA( CK_SESSION_HANDLE xSession, + uint8_t * pucPrivateKeyLabel, + uint8_t * pucPublicKeyLabel, + CK_OBJECT_HANDLE_PTR pxPrivateKeyHandle, + CK_OBJECT_HANDLE_PTR pxPublicKeyHandle ) +{ + CK_RV xResult; + CK_MECHANISM xMechanism = + { + CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 + }; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_ULONG xModulusBits = pkcs11RSA_2048_MODULUS_BITS; + CK_BYTE xPublicExponent[] = pkcs11RSA_PUBLIC_EXPONENT; + + CK_BBOOL xTrue = CK_TRUE; + CK_ATTRIBUTE xPublicKeyTemplate[] = + { + { CKA_ENCRYPT, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_VERIFY, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_MODULUS_BITS, NULL /* &xModulusBits */, sizeof( xModulusBits ) }, + { CKA_PUBLIC_EXPONENT, NULL /* xPublicExponent */, sizeof( xPublicExponent ) }, + { CKA_LABEL, pucPublicKeyLabel, strlen( ( const char * ) pucPublicKeyLabel ) } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPublicKeyTemplate[ 0 ].pValue = &xTrue; + xPublicKeyTemplate[ 1 ].pValue = &xTrue; + xPublicKeyTemplate[ 2 ].pValue = &xModulusBits; + xPublicKeyTemplate[ 3 ].pValue = &xPublicExponent; + + CK_ATTRIBUTE xPrivateKeyTemplate[] = + { + { CKA_TOKEN, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_PRIVATE, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_DECRYPT, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_SIGN, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_LABEL, pucPrivateKeyLabel, strlen( ( const char * ) pucPrivateKeyLabel ) } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPrivateKeyTemplate[ 0 ].pValue = &xTrue; + xPrivateKeyTemplate[ 1 ].pValue = &xTrue; + xPrivateKeyTemplate[ 2 ].pValue = &xTrue; + xPrivateKeyTemplate[ 3 ].pValue = &xTrue; + + xResult = C_GetFunctionList( &pxFunctionList ); + + xResult = pxFunctionList->C_GenerateKeyPair( xSession, + &xMechanism, + xPublicKeyTemplate, + sizeof( xPublicKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + xPrivateKeyTemplate, sizeof( xPrivateKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + pxPublicKeyHandle, + pxPrivateKeyHandle ); + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Generate a new ECDSA key pair using curve P256. */ +CK_RV xProvisionGenerateKeyPairEC( CK_SESSION_HANDLE xSession, + uint8_t * pucPrivateKeyLabel, + uint8_t * pucPublicKeyLabel, + CK_OBJECT_HANDLE_PTR pxPrivateKeyHandle, + CK_OBJECT_HANDLE_PTR pxPublicKeyHandle ) +{ + CK_RV xResult; + CK_MECHANISM xMechanism = + { + CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 + }; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_BYTE xEcParams[] = pkcs11DER_ENCODED_OID_P256; /* prime256v1 */ + CK_KEY_TYPE xKeyType = CKK_EC; + + CK_BBOOL xTrue = CK_TRUE; + CK_ATTRIBUTE xPublicKeyTemplate[] = + { + { CKA_KEY_TYPE, NULL /* &xKeyType */, sizeof( xKeyType ) }, + { CKA_VERIFY, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_EC_PARAMS, NULL /* xEcParams */, sizeof( xEcParams ) }, + { CKA_LABEL, pucPublicKeyLabel, strlen( ( const char * ) pucPublicKeyLabel ) } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPublicKeyTemplate[ 0 ].pValue = &xKeyType; + xPublicKeyTemplate[ 1 ].pValue = &xTrue; + xPublicKeyTemplate[ 2 ].pValue = &xEcParams; + + CK_ATTRIBUTE xPrivateKeyTemplate[] = + { + { CKA_KEY_TYPE, NULL /* &xKeyType */, sizeof( xKeyType ) }, + { CKA_TOKEN, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_PRIVATE, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_SIGN, NULL /* &xTrue */, sizeof( xTrue ) }, + { CKA_LABEL, pucPrivateKeyLabel, strlen( ( const char * ) pucPrivateKeyLabel ) } + }; + + /* Aggregate initializers must not use the address of an automatic variable. */ + /* See MSVC Compiler Warning C4221 */ + xPrivateKeyTemplate[ 0 ].pValue = &xKeyType; + xPrivateKeyTemplate[ 1 ].pValue = &xTrue; + xPrivateKeyTemplate[ 2 ].pValue = &xTrue; + xPrivateKeyTemplate[ 3 ].pValue = &xTrue; + + xResult = C_GetFunctionList( &pxFunctionList ); + + xResult = pxFunctionList->C_GenerateKeyPair( xSession, + &xMechanism, + xPublicKeyTemplate, + sizeof( xPublicKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + xPrivateKeyTemplate, sizeof( xPrivateKeyTemplate ) / sizeof( CK_ATTRIBUTE ), + pxPublicKeyHandle, + pxPrivateKeyHandle ); + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Import the specified X.509 client certificate into storage. */ +CK_RV xProvisionCertificate( CK_SESSION_HANDLE xSession, + uint8_t * pucCertificate, + size_t xCertificateLength, + uint8_t * pucLabel, + CK_OBJECT_HANDLE_PTR pxObjectHandle ) +{ + PKCS11_CertificateTemplate_t xCertificateTemplate; + CK_OBJECT_CLASS xCertificateClass = CKO_CERTIFICATE; + CK_CERTIFICATE_TYPE xCertificateType = CKC_X_509; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_RV xResult; + uint8_t * pucDerObject = NULL; + int32_t lConversionReturn = 0; + size_t xDerLen = 0; + CK_BBOOL xTokenStorage = CK_TRUE; + + /* TODO: Subject is a required attribute. + * Currently, this field is not used by FreeRTOS ports, + * this should be updated so that subject matches proper + * format for future ports. */ + CK_BYTE xSubject[] = "TestSubject"; + + /* Initialize the client certificate template. */ + xCertificateTemplate.xObjectClass.type = CKA_CLASS; + xCertificateTemplate.xObjectClass.pValue = &xCertificateClass; + xCertificateTemplate.xObjectClass.ulValueLen = sizeof( xCertificateClass ); + xCertificateTemplate.xSubject.type = CKA_SUBJECT; + xCertificateTemplate.xSubject.pValue = xSubject; + xCertificateTemplate.xSubject.ulValueLen = strlen( ( const char * ) xSubject ); + xCertificateTemplate.xValue.type = CKA_VALUE; + xCertificateTemplate.xValue.pValue = ( CK_VOID_PTR ) pucCertificate; + xCertificateTemplate.xValue.ulValueLen = ( CK_ULONG ) xCertificateLength; + xCertificateTemplate.xLabel.type = CKA_LABEL; + xCertificateTemplate.xLabel.pValue = ( CK_VOID_PTR ) pucLabel; + xCertificateTemplate.xLabel.ulValueLen = strlen( ( const char * ) pucLabel ); + xCertificateTemplate.xCertificateType.type = CKA_CERTIFICATE_TYPE; + xCertificateTemplate.xCertificateType.pValue = &xCertificateType; + xCertificateTemplate.xCertificateType.ulValueLen = sizeof( CK_CERTIFICATE_TYPE ); + xCertificateTemplate.xTokenObject.type = CKA_TOKEN; + xCertificateTemplate.xTokenObject.pValue = &xTokenStorage; + xCertificateTemplate.xTokenObject.ulValueLen = sizeof( xTokenStorage ); + + xResult = C_GetFunctionList( &pxFunctionList ); + + /* Test for a valid certificate: 0x2d is '-', as in ----- BEGIN CERTIFICATE. */ + if( ( pucCertificate == NULL ) || ( pucCertificate[ 0 ] != 0x2d ) ) + { + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + } + + if( xResult == CKR_OK ) + { + /* Convert the certificate to DER format if it was in PEM. The DER key + * should be about 3/4 the size of the PEM key, so mallocing the PEM key + * size is sufficient. */ + pucDerObject = pvPortMalloc( xCertificateTemplate.xValue.ulValueLen ); + xDerLen = xCertificateTemplate.xValue.ulValueLen; + + if( pucDerObject != NULL ) + { + lConversionReturn = convert_pem_to_der( xCertificateTemplate.xValue.pValue, + xCertificateTemplate.xValue.ulValueLen, + pucDerObject, + &xDerLen ); + + if( 0 != lConversionReturn ) + { + xResult = CKR_ARGUMENTS_BAD; + } + } + else + { + xResult = CKR_HOST_MEMORY; + } + } + + if( xResult == CKR_OK ) + { + /* Set the template pointers to refer to the DER converted objects. */ + xCertificateTemplate.xValue.pValue = pucDerObject; + xCertificateTemplate.xValue.ulValueLen = xDerLen; + } + + /* Best effort clean-up of the existing object, if it exists. */ + if( xResult == CKR_OK ) + { + xDestroyProvidedObjects( xSession, + &pucLabel, + &xCertificateClass, + 1 ); + } + + /* Create an object using the encoded client certificate. */ + if( xResult == CKR_OK ) + { + configPRINTF( ( "Write certificate...\r\n" ) ); + + xResult = pxFunctionList->C_CreateObject( xSession, + ( CK_ATTRIBUTE_PTR ) &xCertificateTemplate, + sizeof( xCertificateTemplate ) / sizeof( CK_ATTRIBUTE ), + pxObjectHandle ); + } + + if( pucDerObject != NULL ) + { + vPortFree( pucDerObject ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Delete the specified crypto object from storage. */ +CK_RV xDestroyProvidedObjects( CK_SESSION_HANDLE xSession, + CK_BYTE_PTR * ppxPkcsLabels, + CK_OBJECT_CLASS * xClass, + CK_ULONG ulCount ) +{ + CK_RV xResult; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_OBJECT_HANDLE xObjectHandle; + CK_BYTE * pxLabel; + CK_ULONG uiIndex = 0; + + xResult = C_GetFunctionList( &pxFunctionList ); + + for( uiIndex = 0; uiIndex < ulCount; uiIndex++ ) + { + pxLabel = ppxPkcsLabels[ uiIndex ]; + + xResult = xFindObjectWithLabelAndClass( xSession, + ( char * ) pxLabel, + strlen( ( char * ) pxLabel ), + xClass[ uiIndex ], + &xObjectHandle ); + + while( ( xResult == CKR_OK ) && ( xObjectHandle != CK_INVALID_HANDLE ) ) + { + xResult = pxFunctionList->C_DestroyObject( xSession, xObjectHandle ); + + /* PKCS #11 allows a module to maintain multiple objects with the same + * label and type. The intent of this loop is to try to delete all of them. + * However, to avoid getting stuck, we won't try to find another object + * of the same label/type if the previous delete failed. */ + if( xResult == CKR_OK ) + { + xResult = xFindObjectWithLabelAndClass( xSession, + ( char * ) pxLabel, + strlen( ( char * ) pxLabel ), + xClass[ uiIndex ], + &xObjectHandle ); + } + else + { + break; + } + } + + if( xResult == CKR_FUNCTION_NOT_SUPPORTED ) + { + break; + } + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Delete well-known crypto objects from storage. */ +CK_RV xDestroyDefaultCryptoObjects( CK_SESSION_HANDLE xSession ) +{ + CK_RV xResult; + CK_BYTE * pxPkcsLabels[] = + { + ( CK_BYTE * ) pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS, + ( CK_BYTE * ) pkcs11configLABEL_CODE_VERIFICATION_KEY, + ( CK_BYTE * ) pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + ( CK_BYTE * ) pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS + }; + CK_OBJECT_CLASS xClass[] = + { + CKO_CERTIFICATE, + CKO_PUBLIC_KEY, + CKO_PRIVATE_KEY, + CKO_PUBLIC_KEY + }; + + xResult = xDestroyProvidedObjects( xSession, + pxPkcsLabels, + xClass, + sizeof( xClass ) / sizeof( CK_OBJECT_CLASS ) ); + + return xResult; +} + +/*-----------------------------------------------------------*/ + +static CK_RV prvExportPublicKey( CK_SESSION_HANDLE xSession, + CK_OBJECT_HANDLE xPublicKeyHandle, + uint8_t ** ppucDerPublicKey, + uint32_t * pulDerPublicKeyLength ) +{ + CK_RV xResult; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_KEY_TYPE xKeyType = 0; + CK_ATTRIBUTE xTemplate = { 0 }; + uint8_t pucEcP256AsnAndOid[] = + { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00 + }; + uint8_t pucUnusedKeyTag[] = { 0x04, 0x41 }; + + /* This variable is used only for its size. This gets rid of compiler warnings. */ + ( void ) pucUnusedKeyTag; + + xResult = C_GetFunctionList( &pxFunctionList ); + + /* Query the key type. */ + if( CKR_OK == xResult ) + { + xTemplate.type = CKA_KEY_TYPE; + xTemplate.pValue = &xKeyType; + xTemplate.ulValueLen = sizeof( xKeyType ); + xResult = pxFunctionList->C_GetAttributeValue( xSession, + xPublicKeyHandle, + &xTemplate, + 1 ); + } + + /* Scope to ECDSA keys only, since there's currently no use case for + * onboard keygen and certificate enrollment for RSA. */ + if( ( CKR_OK == xResult ) && ( CKK_ECDSA == xKeyType ) ) + { + /* Query the size of the public key. */ + xTemplate.type = CKA_EC_POINT; + xTemplate.pValue = NULL; + xTemplate.ulValueLen = 0; + xResult = pxFunctionList->C_GetAttributeValue( xSession, + xPublicKeyHandle, + &xTemplate, + 1 ); + + /* Allocate a buffer large enough for the full, encoded public key. */ + if( CKR_OK == xResult ) + { + /* Add space for the full DER header. */ + xTemplate.ulValueLen += sizeof( pucEcP256AsnAndOid ) - sizeof( pucUnusedKeyTag ); + *pulDerPublicKeyLength = xTemplate.ulValueLen; + + /* Get a heap buffer. */ + *ppucDerPublicKey = pvPortMalloc( xTemplate.ulValueLen ); + + /* Check for resource exhaustion. */ + if( NULL == *ppucDerPublicKey ) + { + xResult = CKR_HOST_MEMORY; + } + } + + /* Export the public key. */ + if( CKR_OK == xResult ) + { + xTemplate.pValue = *ppucDerPublicKey + sizeof( pucEcP256AsnAndOid ) - sizeof( pucUnusedKeyTag ); + xTemplate.ulValueLen -= ( sizeof( pucEcP256AsnAndOid ) - sizeof( pucUnusedKeyTag ) ); + xResult = pxFunctionList->C_GetAttributeValue( xSession, + xPublicKeyHandle, + &xTemplate, + 1 ); + } + + /* Prepend the full DER header. */ + if( CKR_OK == xResult ) + { + memcpy( *ppucDerPublicKey, pucEcP256AsnAndOid, sizeof( pucEcP256AsnAndOid ) ); + } + } + + /* Free memory if there was an error after allocation. */ + if( ( NULL != *ppucDerPublicKey ) && ( CKR_OK != xResult ) ) + { + vPortFree( *ppucDerPublicKey ); + *ppucDerPublicKey = NULL; + } + + return xResult; +} + +/* Determine which required client crypto objects are already present in + * storage. */ +static CK_RV prvGetProvisionedState( CK_SESSION_HANDLE xSession, + ProvisionedState_t * pxProvisionedState ) +{ + CK_RV xResult; + CK_FUNCTION_LIST_PTR pxFunctionList; + CK_SLOT_ID_PTR pxSlotId = NULL; + CK_ULONG ulSlotCount = 0; + CK_TOKEN_INFO xTokenInfo = { 0 }; + unsigned int i = 0; + + xResult = C_GetFunctionList( &pxFunctionList ); + + /* Check for a private key. */ + if( CKR_OK == xResult ) + { + xResult = xFindObjectWithLabelAndClass( xSession, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + sizeof( pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) - 1, + CKO_PRIVATE_KEY, + &pxProvisionedState->xPrivateKey ); + } + + if( ( CKR_OK == xResult ) && ( CK_INVALID_HANDLE != pxProvisionedState->xPrivateKey ) ) + { + /* Check also for the corresponding public. */ + xResult = xFindObjectWithLabelAndClass( xSession, + pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS, + sizeof( pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) - 1, + CKO_PUBLIC_KEY, + &pxProvisionedState->xPublicKey ); + } + + if( ( CKR_OK == xResult ) && ( CK_INVALID_HANDLE != pxProvisionedState->xPublicKey ) ) + { + /* Export the public key. */ + xResult = prvExportPublicKey( xSession, + pxProvisionedState->xPublicKey, + &pxProvisionedState->pucDerPublicKey, + &pxProvisionedState->ulDerPublicKeyLength ); + } + + /* Check for the client certificate. */ + if( CKR_OK == xResult ) + { + xResult = xFindObjectWithLabelAndClass( xSession, + pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS, + sizeof( pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS ) - 1, + CKO_CERTIFICATE, + &pxProvisionedState->xClientCertificate ); + } + + /* Check for a crypto element identifier. */ + if( CKR_OK == xResult ) + { + xResult = xGetSlotList( &pxSlotId, &ulSlotCount ); + } + + if( CKR_OK == xResult ) + { + xResult = pxFunctionList->C_GetTokenInfo( pxSlotId[ 0 ], &xTokenInfo ); + vPortFree( pxSlotId ); + } + + if( ( CKR_OK == xResult ) && ( '\0' != xTokenInfo.label[ 0 ] ) && ( ' ' != xTokenInfo.label[ 0 ] ) ) + { + /* PKCS #11 requires that token info fields are padded out with space + * characters. However, a NULL terminated copy will be more useful to the + * caller. */ + for( i = 0; i < sizeof( xTokenInfo.label ); i++ ) + { + if( xTokenInfo.label[ i ] == ' ' ) + { + break; + } + } + + if( 0 != i ) + { + pxProvisionedState->pcIdentifier = ( char * ) pvPortMalloc( 1 + i * sizeof( xTokenInfo.label[ 0 ] ) ); + + if( NULL != pxProvisionedState->pcIdentifier ) + { + memcpy( pxProvisionedState->pcIdentifier, + xTokenInfo.label, + i ); + pxProvisionedState->pcIdentifier[ i ] = '\0'; + } + else + { + xResult = CKR_HOST_MEMORY; + } + } + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Write the ASN.1 encoded bytes of the device public key to the console. + * This is for debugging purposes as well as to faciliate developer-driven + * certificate enrollment for onboard crypto hardware (i.e. if available). */ +static void prvWriteHexBytesToConsole( char * pcDescription, + uint8_t * pucData, + uint32_t ulDataLength ) +{ +#define BYTES_TO_DISPLAY_PER_ROW 16 + char pcByteRow[ 1 + ( BYTES_TO_DISPLAY_PER_ROW * 2 ) + ( BYTES_TO_DISPLAY_PER_ROW / 2 ) ]; + char * pcNextChar = pcByteRow; + uint32_t ulIndex = 0; + uint8_t ucByteValue = 0; + + /* Write help text to the console. */ + configPRINTF( ( "%s, %d bytes:\r\n", pcDescription, ulDataLength ) ); + + /* Iterate over the bytes of the encoded public key. */ + for( ; ulIndex < ulDataLength; ulIndex++ ) + { + /* Convert one byte to ASCII hex. */ + ucByteValue = *( pucData + ulIndex ); + snprintf( pcNextChar, + sizeof( pcByteRow ) - ( pcNextChar - pcByteRow ), + "%02x", + ucByteValue ); + pcNextChar += 2; + + /* Check for the end of a two-byte display word. */ + if( 0 == ( ( ulIndex + 1 ) % sizeof( uint16_t ) ) ) + { + *pcNextChar = ' '; + pcNextChar++; + } + + /* Check for the end of a row. */ + if( 0 == ( ( ulIndex + 1 ) % BYTES_TO_DISPLAY_PER_ROW ) ) + { + *pcNextChar = '\0'; + vLoggingPrint( pcByteRow ); + vLoggingPrint( "\r\n" ); + pcNextChar = pcByteRow; + } + } + + /* Check for a partial line to print. */ + if( pcNextChar > pcByteRow ) + { + *pcNextChar = '\0'; + vLoggingPrint( pcByteRow ); + vLoggingPrint( "\r\n" ); + } +} + +/*-----------------------------------------------------------*/ + +/* Attempt to provision the device with a client certificate, associated + * private and public key pair, and optional Just-in-Time Registration certificate. + * If either component of the key pair is unavailable in storage, generate a new + * pair. */ +CK_RV xProvisionDevice( CK_SESSION_HANDLE xSession, + ProvisioningParams_t * pxParams ) +{ + CK_RV xResult; + CK_FUNCTION_LIST_PTR pxFunctionList; + ProvisionedState_t xProvisionedState = { 0 }; + CK_OBJECT_HANDLE xObject = 0; + CK_BBOOL xImportedPrivateKey = CK_FALSE; + CK_BBOOL xKeyPairGenerationMode = CK_FALSE; + + xResult = C_GetFunctionList( &pxFunctionList ); + + #if ( pkcs11configIMPORT_PRIVATE_KEYS_SUPPORTED == 1 ) + + /* Attempt to clean-up old crypto objects, but only if private key import is + * supported by this application, and only if the caller has provided new + * objects to use instead. */ + if( ( CKR_OK == xResult ) && + ( NULL != pxParams->pucClientCertificate ) && + ( NULL != pxParams->pucClientPrivateKey ) ) + { + xResult = xDestroyDefaultCryptoObjects( xSession ); + + if( xResult != CKR_OK ) + { + configPRINTF( ( "Warning: could not clean-up old crypto objects. %d \r\n", xResult ) ); + } + } + #endif /* if ( pkcs11configIMPORT_PRIVATE_KEYS_SUPPORTED == 1 ) */ + + /* If a client certificate has been provided by the caller, attempt to + * import it. */ + if( ( xResult == CKR_OK ) && ( NULL != pxParams->pucClientCertificate ) ) + { + xResult = xProvisionCertificate( xSession, + pxParams->pucClientCertificate, + pxParams->ulClientCertificateLength, + ( uint8_t * ) pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS, + &xObject ); + + if( ( xResult != CKR_OK ) || ( xObject == CK_INVALID_HANDLE ) ) + { + configPRINTF( ( "ERROR: Failed to provision device certificate. %d \r\n", xResult ) ); + } + } + + #if ( pkcs11configIMPORT_PRIVATE_KEYS_SUPPORTED == 1 ) + + /* If this application supports importing private keys, and if a private + * key has been provided by the caller, attempt to import it. */ + if( ( xResult == CKR_OK ) && ( NULL != pxParams->pucClientPrivateKey ) ) + { + xResult = xProvisionPrivateKey( xSession, + pxParams->pucClientPrivateKey, + pxParams->ulClientPrivateKeyLength, + ( uint8_t * ) pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + &xObject ); + + if( ( xResult != CKR_OK ) || ( xObject == CK_INVALID_HANDLE ) ) + { + configPRINTF( ( "ERROR: Failed to provision device private key with status %d.\r\n", xResult ) ); + } + else + { + xImportedPrivateKey = CK_TRUE; + } + } + #endif /* if ( pkcs11configIMPORT_PRIVATE_KEYS_SUPPORTED == 1 ) */ + + /* If a Just-in-Time Provisioning certificate has been provided by the + * caller, attempt to import it. Not all crypto tokens + * and PKCS #11 module implementations provide storage for this particular + * object. In that case, the statically defined object, if any, will be used + * during TLS session negotiation with AWS IoT. */ + if( ( xResult == CKR_OK ) && ( NULL != pxParams->pucJITPCertificate ) ) + { + xResult = xProvisionCertificate( xSession, + pxParams->pucJITPCertificate, + pxParams->ulJITPCertificateLength, + ( uint8_t * ) pkcs11configLABEL_JITP_CERTIFICATE, + &xObject ); + + if( xResult == CKR_DEVICE_MEMORY ) + { + xResult = CKR_OK; + configPRINTF( ( "Warning: no persistent storage is available for the JITP certificate. The certificate in aws_clientcredential_keys.h will be used instead.\r\n" ) ); + } + } + + /* Check whether a key pair is now present. In order to support X.509 + * certificate enrollment, the public and private key objects must both be + * available. */ + if( ( xResult == CKR_OK ) && ( CK_FALSE == xImportedPrivateKey ) ) + { + xResult = prvGetProvisionedState( xSession, + &xProvisionedState ); + + if( ( CK_INVALID_HANDLE == xProvisionedState.xPrivateKey ) || + ( CK_INVALID_HANDLE == xProvisionedState.xPublicKey ) || + ( NULL == xProvisionedState.pucDerPublicKey ) ) + { + xKeyPairGenerationMode = CK_TRUE; + } + + /* Ignore errors, since the board may have been previously used with a + * different crypto middleware or app. If any of the above objects + * couldn't be read, try to generate new ones below. */ + xResult = CKR_OK; + } + + #if ( 1 == keyprovisioningFORCE_GENERATE_NEW_KEY_PAIR ) + xKeyPairGenerationMode = CK_TRUE; + #endif + + if( ( xResult == CKR_OK ) && ( CK_TRUE == xKeyPairGenerationMode ) ) + { + /* Generate a new default key pair. */ + xResult = xProvisionGenerateKeyPairEC( xSession, + ( uint8_t * ) pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + ( uint8_t * ) pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS, + &xProvisionedState.xPrivateKey, + &xProvisionedState.xPublicKey ); + + if( CKR_OK == xResult ) + { + /* Clean-up the previous buffer, if any. */ + if( NULL != xProvisionedState.pucDerPublicKey ) + { + vPortFree( xProvisionedState.pucDerPublicKey ); + xProvisionedState.pucDerPublicKey = NULL; + } + + /* Get the bytes of the new public key. */ + prvExportPublicKey( xSession, + xProvisionedState.xPublicKey, + &xProvisionedState.pucDerPublicKey, + &xProvisionedState.ulDerPublicKeyLength ); + } + + /* Ensure that an error condition is set if either object is still + * missing. */ + if( ( CKR_OK == xResult ) && + ( ( CK_INVALID_HANDLE == xProvisionedState.xPrivateKey ) || + ( CK_INVALID_HANDLE == xProvisionedState.xPublicKey ) ) ) + { + xResult = CKR_KEY_HANDLE_INVALID; + } + } + + /* Log the device public key for developer enrollment purposes, but only if + * there's not already a certificate, or if a new key was just generated. */ + if( ( CKR_OK == xResult ) && + ( ( CK_INVALID_HANDLE == xProvisionedState.xClientCertificate ) || + ( CK_TRUE == xKeyPairGenerationMode ) ) && + ( CK_FALSE == xImportedPrivateKey ) ) + { + configPRINTF( ( "Warning: the client certificate should be updated. Please see https://aws.amazon.com/freertos/getting-started/.\r\n" ) ); + + if( NULL != xProvisionedState.pcIdentifier ) + { + configPRINTF( ( "Recommended certificate subject name: CN=%s\r\n", xProvisionedState.pcIdentifier ) ); + } + + prvWriteHexBytesToConsole( "Device public key", + xProvisionedState.pucDerPublicKey, + xProvisionedState.ulDerPublicKeyLength ); + + /* Delay since the downstream demo code is likely to fail quickly if + * provisioning isn't complete, and device certificate creation in the + * lab may depend on the developer obtaining the public key. */ + /*vTaskDelay( pdMS_TO_TICKS( 100 ) ); */ + } + + /* Free memory. */ + if( NULL != xProvisionedState.pucDerPublicKey ) + { + vPortFree( xProvisionedState.pucDerPublicKey ); + } + + if( NULL != xProvisionedState.pcIdentifier ) + { + vPortFree( xProvisionedState.pcIdentifier ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Perform device provisioning using the specified TLS client credentials. */ +CK_RV vAlternateKeyProvisioning( ProvisioningParams_t * xParams ) +{ + CK_RV xResult = CKR_OK; + CK_FUNCTION_LIST_PTR pxFunctionList = NULL; + CK_SESSION_HANDLE xSession = 0; + + xResult = C_GetFunctionList( &pxFunctionList ); + + /* Initialize the PKCS Module */ + if( xResult == CKR_OK ) + { + xResult = xInitializePkcs11Token(); + } + + if( xResult == CKR_OK ) + { + xResult = xInitializePkcs11Session( &xSession ); + } + + if( xResult == CKR_OK ) + { + xResult = xProvisionDevice( xSession, xParams ); + + pxFunctionList->C_CloseSession( xSession ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/* Perform device provisioning using the default TLS client credentials. */ +CK_RV vDevModeKeyProvisioning( void ) +{ + ProvisioningParams_t xParams; + + xParams.pucJITPCertificate = ( uint8_t * ) keyJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM; + xParams.pucClientPrivateKey = ( uint8_t * ) keyCLIENT_PRIVATE_KEY_PEM; + xParams.pucClientCertificate = ( uint8_t * ) keyCLIENT_CERTIFICATE_PEM; + + /* If using a JITR flow, a JITR certificate must be supplied. If using credentials generated by + * AWS, this certificate is not needed. */ + if( ( NULL != xParams.pucJITPCertificate ) && + ( 0 != strcmp( "", ( const char * ) xParams.pucJITPCertificate ) ) ) + { + /* We want the NULL terminator to be written to storage, so include it + * in the length calculation. */ + xParams.ulJITPCertificateLength = sizeof( char ) + strlen( ( const char * ) xParams.pucJITPCertificate ); + } + else + { + xParams.pucJITPCertificate = NULL; + } + + /* The hard-coded client certificate and private key can be useful for + * first-time lab testing. They are optional after the first run, though, and + * not recommended at all for going into production. */ + if( ( NULL != xParams.pucClientPrivateKey ) && + ( 0 != strcmp( "", ( const char * ) xParams.pucClientPrivateKey ) ) ) + { + /* We want the NULL terminator to be written to storage, so include it + * in the length calculation. */ + xParams.ulClientPrivateKeyLength = sizeof( char ) + strlen( ( const char * ) xParams.pucClientPrivateKey ); + } + else + { + xParams.pucClientPrivateKey = NULL; + } + + if( ( NULL != xParams.pucClientCertificate ) && + ( 0 != strcmp( "", ( const char * ) xParams.pucClientCertificate ) ) ) + { + /* We want the NULL terminator to be written to storage, so include it + * in the length calculation. */ + xParams.ulClientCertificateLength = sizeof( char ) + strlen( ( const char * ) xParams.pucClientCertificate ); + } + else + { + xParams.pucClientCertificate = NULL; + } + + return vAlternateKeyProvisioning( &xParams ); +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/demos/network_manager/aws_iot_network_manager.c b/bsp/aws_libraries/demos/network_manager/aws_iot_network_manager.c new file mode 100644 index 0000000..0f25fb9 --- /dev/null +++ b/bsp/aws_libraries/demos/network_manager/aws_iot_network_manager.c @@ -0,0 +1,1204 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file aws_iot_network_manager.c + * @brief Network manager is used to handled different types of network connections and their connection/disconnection events at the application layer. + */ +#include + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#include "iot_demo_logging.h" +#include "iot_network_manager_private.h" + +#include "aws_clientcredential.h" +#include "aws_clientcredential_keys.h" + +#if BLE_ENABLED + #include "iot_ble_config.h" + #include "iot_ble.h" + #include "iot_ble_numericComparison.h" + #include "platform/iot_network_ble.h" +#endif + +#if WIFI_ENABLED + #include "iot_wifi.h" +#endif + +#if TCPIP_NETWORK_ENABLED + #include "platform/iot_network_freertos.h" +#endif + + +#if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 1 ) + #include "iot_ble_wifi_provisioning.h" + #include "aws_wifi_connect_task.h" +#endif +#if ( IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 1 ) + #include "iot_softap_wifi_provisioning.h" + #include "aws_wifi_connect_task.h" +#endif + +#define _NM_PARAMS( networkType, networkState ) ( ( ( uint32_t ) networkType ) << 16 | ( ( uint16_t ) networkState ) ) + +#define _NM_GET_NETWORK_TYPE( params ) ( ( uint32_t ) ( ( params ) >> 16 ) & 0x0000FFFFUL ) + +#define _NM_GET_NETWORK_STATE( params ) ( ( AwsIotNetworkState_t ) ( ( params ) & 0x0000FFFFUL ) ) + +#define _NM_WIFI_CONNECTION_RETRY_INTERVAL_MS ( 1000 ) + +#define _NM_WIFI_CONNECTION_RETRIES ( 5 ) + +/** + * @brief Maximum number of application subscriptions allowed with network manager. + * Applications can subscribe callbacks to be notified of network state change events from network manager. + */ +#define NETWORK_MANAGER_MAX_SUBSCRIPTIONS ( 5 ) + +/** + * @brief Maximum number of events from underlying layers pending in network manager queue at any time. + * Events could be generated from underlying layer at a faster rate than they are processed with in network manager + * subscription callbacks. Queue holds pending events to be procesed by network manager any time. + */ +#define NETWORK_MANAGER_EVENT_QUEUE_SIZE ( 10 ) + +/** + * @brief Priority of the network manager task. + */ +#define NETWORK_MANAGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) + +/** + * @brief Stack size for network manager task. + */ +#define NETWORK_MANAGER_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 ) + +/** + * @brief Structure holds information for each network and the runtime state of it. + */ +typedef struct IotNMNetwork +{ + uint32_t type; + AwsIotNetworkState_t state; + const IotNetworkInterface_t * pNetworkInterface; + void * pConnectionParams; + void * pCredentials; +} IotNMNetwork_t; + +/** + * @brief Structure holds information for each of the network state change subscription. + */ +typedef struct IotNMSubscription +{ + uint32_t networkTypes; + AwsIotNetworkStateChangeCb_t callback; + void * pContext; + BaseType_t isActive; +} IotNMSubscription_t; + +/** + * @brief Enum defines the types of events received by the network manager from underlying network driver. + */ +typedef enum IotNetworkEventType +{ + IOT_NETWORK_EVENT_CONNECTED = 0, + IOT_NETWORK_EVENT_DISCONNECTED = 1 +} IotNetworkEventType_t; + +/** + * @brief Structure holds the event information associated with an event received from the underlying network driver. + * Structure is used queue network events for the network manager task to process. + */ +typedef struct IotNetworkEvent +{ + uint32_t networkType; + IotNetworkEventType_t eventType; +} IotNetworkEvent_t; + +/** + * @brief Network manager object, holds the list of supported networks and the list of network state change subscriptions. + */ +typedef struct IotNetworkManager +{ + IotNMNetwork_t * pNetworks; + size_t numNetworks; + IotNMSubscription_t subscriptions[ NETWORK_MANAGER_MAX_SUBSCRIPTIONS ]; + QueueHandle_t eventQueue; + SemaphoreHandle_t globalMutex; + SemaphoreHandle_t subscriptionsMutex; +} IotNetworkManagerInfo_t; + +#if BLE_ENABLED + +/** + * @brief Register/unregister callbacks related to BLE middleware. + * + * @param[in] unRegister Set to true to unRegister + * @return true if success false otherwise. + * + */ + static bool _bleRegisterUnregisterCb( bool unRegister ); + +/** + * @brief Function used to enable a BLE network. + * + * @return true if BLE is enabled successfully. + */ + static bool _bleEnable( void ); + + +/** + * @brief Function used to disable a BLE network. + * + * @return true if BLE is disable successfully, false if already disabled + */ + static bool _bleDisable( void ); + + +/** + * @brief Callback invokedon a new BLE connection or disconnection. + */ + static void _bleConnectionCallback( BTStatus_t status, + uint16_t connectionID, + bool isConnected, + BTBdaddr_t * pRemoteAddress ); + +#endif /* if BLE_ENABLED */ + + +#if WIFI_ENABLED + + #if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 0 && IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 0 ) + +/** + * Connects to the WIFI using credentials configured statically + * @return true if connected successfully. + */ + static bool _wifiConnectAccessPoint( void ); + + #endif + +/** + * @brief Function used to enable a WIFI network. + * + * @return true if WIFI is enabled successfully. + */ + static bool _wifiEnable( void ); + +/** + * @brief Function used to disable a WIFI network. + * + * @return true if WIFI is disable successfully, false if already disabled + */ + static bool _wifiDisable( void ); + +/** + * @brief The callback invoked for WiFi events from the driver. The callback + * is used to change the WiFi state in network manager. + */ + static void _wifiEventHandler( WIFIEvent_t * xEvent ); + +#endif /* if WIFI_ENABLED */ + +#if ETH_ENABLED + +/** + * @brief Function used to enable a WIFI network. + * + * @return true if WIFI is enabled successfully. + */ + static bool _ethEnable( void ); + +/** + * @brief Function used to disable a WIFI network. + * + * @return true if WIFI is disable successfully, false if already disabled + */ + static bool _ethDisable( void ); + +#endif /* if ETH_ENABLED */ + + +/** + * @brief Get the network instance associated with the network type. + * + * @param[in] networkType Type of the network. + * @return Pointer to the network instance. NULL if network is not configured. + * + */ +static IotNMNetwork_t * prvGetNetworkInstance( uint32_t networkType ); + +/** + * @brief Dispatch a network event to the application subscription callbacks. + * @param[in] pEvent Pointer to the event struct for the event. + */ +static void prvDispatch( uint32_t networkType, + AwsIotNetworkState_t state ); + +/** + * @brief Initialize TCP/IP credentials for WIFI and ethernet networks. + */ +static void _initializeTCPIPCredentials( void ); + +/** + * @brief The credentials placeholder for a TCP/IP network. + * + */ +static IotNetworkCredentials_t tcpIPCredentials = { 0 }; + +/* + * @brief Connection parameters placeholder for a TCP/IP network. + */ +static IotNetworkServerInfo_t tcpIPConnectionParams = { 0 }; + +static IotNMNetwork_t networks[] = +{ + #if BLE_ENABLED + + /** + * @brief Configuration and state for a BLE Network. + */ + { + .type = AWSIOT_NETWORK_TYPE_BLE, + .state = eNetworkStateDisabled, + .pNetworkInterface = IOT_NETWORK_INTERFACE_BLE, + .pCredentials = NULL, + .pConnectionParams = NULL + }, + #endif /* if BLE_ENABLED */ + + #if WIFI_ENABLED + { + .type = AWSIOT_NETWORK_TYPE_WIFI, + .state = eNetworkStateDisabled, + .pNetworkInterface = IOT_NETWORK_INTERFACE_AFR, + .pCredentials = &tcpIPCredentials, + .pConnectionParams = &tcpIPConnectionParams + }, + #endif + + #if ETH_ENABLED + { + .type = AWSIOT_NETWORK_TYPE_ETH, + .state = eNetworkStateDisabled, + .pNetworkInterface = IOT_NETWORK_INTERFACE_AFR, + .pCredentials = &tcpIPCredentials, + .pConnectionParams = &tcpIPConnectionParams + }, + #endif +}; + +static IotNetworkManagerInfo_t networkManager; + + +#if BLE_ENABLED + + static bool _bleRegisterUnregisterCb( bool unRegister ) + { + IotBleEventsCallbacks_t eventCallback; + BTStatus_t status = eBTStatusSuccess; + bool ret = false; + + eventCallback.pConnectionCb = _bleConnectionCallback; + + if( unRegister == false ) + { + status = IotBle_RegisterEventCb( eBLEConnection, eventCallback ); + } + else + { + status = IotBle_UnRegisterEventCb( eBLEConnection, eventCallback ); + } + + if( status == eBTStatusSuccess ) + { + eventCallback.pGAPPairingStateChangedCb = &vDemoBLEGAPPairingStateChangedCb; + + if( unRegister == false ) + { + status = IotBle_RegisterEventCb( eBLEPairingStateChanged, eventCallback ); + } + else + { + status = IotBle_UnRegisterEventCb( eBLEPairingStateChanged, eventCallback ); + } + } + + #if ( IOT_BLE_ENABLE_NUMERIC_COMPARISON == 1 ) + if( status == eBTStatusSuccess ) + { + eventCallback.pNumericComparisonCb = &vDemoBLENumericComparisonCb; + + if( unRegister == false ) + { + status = IotBle_RegisterEventCb( eBLENumericComparisonCallback, eventCallback ); + } + else + { + status = IotBle_UnRegisterEventCb( eBLENumericComparisonCallback, eventCallback ); + } + } + #endif /* if ( IOT_BLE_ENABLE_NUMERIC_COMPARISON == 1 ) */ + + if( status == eBTStatusSuccess ) + { + ret = true; + } + + return ret; + } + + static bool _bleEnable( void ) + { + bool status = false; + static bool bleInited = false; + IotNMNetwork_t * pNetwork = NULL; + + + pNetwork = prvGetNetworkInstance( AWSIOT_NETWORK_TYPE_BLE ); + configASSERT( pNetwork != NULL ); + + if( pNetwork->state == eNetworkStateDisabled ) + { + if( bleInited == false ) + { + /* Perform BLE one time initialization. */ + if( IotBle_Init() != eBTStatusSuccess ) + { + IotLogError( "Failed to initialize BLE stack." ); + } + else + { + bleInited = true; + status = true; + } + + #if ( IOT_BLE_ENABLE_NUMERIC_COMPARISON == 1 ) + if( status == true ) + { + vDemoBLENumericComparisonInit(); + } + #endif + } + else + { + /* BLE one time initialization done. */ + status = true; + } + + if( status == true ) + { + status = _bleRegisterUnregisterCb( false ); + } + + if( status == true ) + { + if( IotBle_On() != eBTStatusSuccess ) + { + IotLogError( "Failed to turn on BLE." ); + status = false; + } + } + + if( status == true ) + { + pNetwork->state = eNetworkStateEnabled; + } + } + + return status; + } + +/*-----------------------------------------------------------*/ +/* TODO make same function to register/unregister or risk of memory leak. */ + static bool _bleDisable( void ) + { + bool ret = false; + IotNMNetwork_t * pNetwork = NULL; + + pNetwork = prvGetNetworkInstance( AWSIOT_NETWORK_TYPE_BLE ); + configASSERT( pNetwork != NULL ); + + if( pNetwork->state != eNetworkStateDisabled ) + { + /* Unregister the callbacks */ + ret = _bleRegisterUnregisterCb( true ); + + if( ret == true ) + { + /* Turn off BLE */ + if( IotBle_Off() != eBTStatusSuccess ) + { + ret = false; + } + } + + if( ret == true ) + { + pNetwork->state = eNetworkStateDisabled; + } + } + + return ret; + } + + static void _bleConnectionCallback( BTStatus_t status, + uint16_t connectionID, + bool isConnected, + BTBdaddr_t * pRemoteAddress ) + { + IotNetworkEvent_t event = + { + .networkType = AWSIOT_NETWORK_TYPE_BLE + }; + BaseType_t sendStatus; + + if( isConnected == true ) + { + IotLogInfo( "BLE Connected to remote device, connId = %d\n", connectionID ); + IotBle_StopAdv( NULL ); + event.eventType = IOT_NETWORK_EVENT_CONNECTED; + sendStatus = xQueueSend( networkManager.eventQueue, &event, ( TickType_t ) 1U ); + configASSERT( sendStatus == pdTRUE ); + } + else + { + IotLogInfo( "BLE disconnected with remote device, connId = %d \n", connectionID ); + ( void ) IotBle_StartAdv( NULL ); + event.eventType = IOT_NETWORK_EVENT_DISCONNECTED; + sendStatus = xQueueSend( networkManager.eventQueue, &event, ( TickType_t ) 1U ); + configASSERT( sendStatus == pdTRUE ); + } + } + + +#endif /* if BLE_ENABLED */ +/*-----------------------------------------------------------*/ +#if WIFI_ENABLED + + #if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 0 && IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 0 ) + + static bool _wifiConnectAccessPoint( void ) + { + bool status = true; + WIFINetworkParams_t xConnectParams; + size_t xSSIDLength, xPasswordLength; + const char * pcSSID = clientcredentialWIFI_SSID; + const char * pcPassword = clientcredentialWIFI_PASSWORD; + WIFISecurity_t xSecurity = clientcredentialWIFI_SECURITY; + uint32_t numRetries = _NM_WIFI_CONNECTION_RETRIES; + uint32_t delayMilliseconds = _NM_WIFI_CONNECTION_RETRY_INTERVAL_MS; + + if( pcSSID != NULL ) + { + xSSIDLength = strlen( pcSSID ); + + if( ( xSSIDLength > 0 ) && ( xSSIDLength < wificonfigMAX_SSID_LEN ) ) + { + xConnectParams.ucSSIDLength = xSSIDLength; + memcpy( xConnectParams.ucSSID, clientcredentialWIFI_SSID, xSSIDLength ); + } + else + { + status = false; + } + } + else + { + status = false; + } + + xConnectParams.xSecurity = xSecurity; + + switch( xSecurity ) + { + case eWiFiSecurityWPA: + case eWiFiSecurityWPA2: + + if( pcPassword != NULL ) + { + xPasswordLength = strlen( clientcredentialWIFI_PASSWORD ); + + if( ( xPasswordLength > 0 ) && ( xPasswordLength < wificonfigMAX_PASSPHRASE_LEN ) ) + { + xConnectParams.xPassword.xWPA.ucLength = xPasswordLength; + memcpy( xConnectParams.xPassword.xWPA.cPassphrase, clientcredentialWIFI_PASSWORD, xPasswordLength ); + } + else + { + status = false; + } + } + else + { + status = false; + } + + break; + + case eWiFiSecurityOpen: + /* Nothing to do. */ + break; + + case eWiFiSecurityWPA3: + case eWiFiSecurityWPA2_ent: + case eWiFiSecurityWEP: + default: + IotLogError( "The configured WiFi security option is not supported." ); + status = false; + break; + } + + if( status == true ) + { + /* Try to connect to wifi access point with retry and exponential delay */ + do + { + if( WIFI_ConnectAP( &( xConnectParams ) ) == eWiFiSuccess ) + { + break; + } + else + { + if( numRetries > 0 ) + { + vTaskDelay( pdMS_TO_TICKS( delayMilliseconds ) ); + delayMilliseconds = delayMilliseconds * 2; + } + else + { + status = false; + } + } + } while( numRetries-- > 0 ); + } + + return status; + } + + #endif /* if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 0 && IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 0 ) */ + + + static bool _wifiEnable( void ) + { + bool ret = true; + WIFIReturnCode_t wifiRet; + IotNMNetwork_t * pNetwork = NULL; + + pNetwork = prvGetNetworkInstance( AWSIOT_NETWORK_TYPE_WIFI ); + configASSERT( pNetwork != NULL ); + + if( pNetwork->state == eNetworkStateDisabled ) + { + if( WIFI_On() != eWiFiSuccess ) + { + ret = false; + } + + if( ret == true ) + { + /* Network is enabled now. */ + pNetwork->state = eNetworkStateEnabled; + + /* Register network state change callback with the Wi-Fi driver */ + wifiRet = WIFI_RegisterEvent( eWiFiEventIPReady, _wifiEventHandler ); + + if( wifiRet == eWiFiSuccess ) + { + wifiRet = WIFI_RegisterEvent( eWiFiEventDisconnected, _wifiEventHandler ); + } + + if( ( wifiRet != eWiFiSuccess ) && ( wifiRet != eWiFiNotSupported ) ) + { + ret = false; + } + } + + #if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 0 && IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 0 ) + if( ret == true ) + { + ret = _wifiConnectAccessPoint(); + + if( ret == true ) + { + pNetwork->state = eNetworkStateConnected; + } + } + #else + if( ret == true ) + { + if( xWiFiConnectTaskInitialize() != pdTRUE ) + { + ret = false; + } + } + #endif /* if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 0 && IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 0 ) */ + } + + return ret; + } + + static bool _wifiDisable( void ) + { + bool ret = true; + + IotNMNetwork_t * pNetwork = NULL; + + pNetwork = prvGetNetworkInstance( AWSIOT_NETWORK_TYPE_WIFI ); + configASSERT( pNetwork != NULL ); + + if( pNetwork->state != eNetworkStateDisabled ) + { + #if ( IOT_BLE_ENABLE_WIFI_PROVISIONING == 1 ) || ( IOT_WIFI_ENABLE_SOFTAP_PROVISIONING == 1 ) + vWiFiConnectTaskDestroy(); + #endif + + WIFI_RegisterEvent( eWiFiEventDisconnected, NULL ); + + if( ret == true ) + { + if( WIFI_IsConnected( NULL ) == pdTRUE ) + { + if( WIFI_Disconnect() != eWiFiSuccess ) + { + ret = false; + } + } + } + + if( ret == true ) + { + if( WIFI_Off() != eWiFiSuccess ) + { + ret = false; + } + } + + if( ret == true ) + { + pNetwork->state = eNetworkStateDisabled; + } + } + else + { + IotLogError( "WiFi network in UNKNOWN state, cannot be disabled." ); + ret = false; + } + + return ret; + } + + static void _wifiEventHandler( WIFIEvent_t * pxEvent ) + { + uint8_t * pucIpAddr; + IotNetworkEvent_t event = + { + .networkType = AWSIOT_NETWORK_TYPE_WIFI + }; + BaseType_t status; + + if( pxEvent->xEventType == eWiFiEventIPReady ) + { + pucIpAddr = ( uint8_t * ) ( &pxEvent->xInfo.xIPReady.xIPAddress.ulAddress[ 0 ] ); + IotLogInfo( "Connected to WiFi access point, ip address: %d.%d.%d.%d.", pucIpAddr[ 0 ], pucIpAddr[ 1 ], pucIpAddr[ 2 ], pucIpAddr[ 3 ] ); + event.eventType = IOT_NETWORK_EVENT_CONNECTED; + status = xQueueSend( networkManager.eventQueue, &event, ( TickType_t ) 1U ); + configASSERT( status == pdTRUE ); + } + else if( pxEvent->xEventType == eWiFiEventDisconnected ) + { + IotLogInfo( "Disconnected from WiFi access point, reason code: %d.", pxEvent->xInfo.xDisconnected.xReason ); + event.eventType = IOT_NETWORK_EVENT_DISCONNECTED; + status = xQueueSend( networkManager.eventQueue, &event, ( TickType_t ) 1U ); + configASSERT( status == pdTRUE ); + } + } + +#endif /* if WIFI_ENABLED */ + + +#if ETH_ENABLED + + static bool _ethEnable( void ) + { + IotNMNetwork_t * pNetwork = NULL; + bool ret = false; + + pNetwork = prvGetNetworkInstance( AWSIOT_NETWORK_TYPE_ETH ); + configASSERT( pNetwork != NULL ); + + if( pNetwork->state == eNetworkStateDisabled ) + { + pNetwork->state = eNetworkStateConnected; + ret = true; + } + + return ret; + } + + static bool _ethDisable( void ) + { + IotNMNetwork_t * pNetwork = NULL; + bool ret = false; + + pNetwork = prvGetNetworkInstance( AWSIOT_NETWORK_TYPE_ETH ); + configASSERT( pNetwork != NULL ); + + if( pNetwork->state != eNetworkStateDisabled ) + { + pNetwork->state = eNetworkStateDisabled; + ret = true; + } + + return ret; + } + +#endif /* if ETH_ENABLED */ + +/*-----------------------------------------------------------*/ + +static IotNMNetwork_t * prvGetNetworkInstance( uint32_t networkType ) +{ + size_t index; + IotNMNetwork_t * pNetwork = NULL; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + if( networkManager.pNetworks[ index ].type == networkType ) + { + pNetwork = &networkManager.pNetworks[ index ]; + break; + } + } + + return pNetwork; +} + +/*-----------------------------------------------------------*/ + +static void prvDispatch( uint32_t networkType, + AwsIotNetworkState_t state ) +{ + size_t index; + + for( index = 0; index < NETWORK_MANAGER_MAX_SUBSCRIPTIONS; index++ ) + { + if( ( ( networkManager.subscriptions[ index ].networkTypes & networkType ) == networkType ) && + ( networkManager.subscriptions[ index ].isActive == true ) ) + { + IotLogInfo( "Invoked callback for network state change event." ); + networkManager.subscriptions[ index ].callback( networkType, state, networkManager.subscriptions[ index ].pContext ); + } + } +} + +/*-----------------------------------------------------------*/ + +static void prvNetworkManagerTask( void * pvParams ) +{ + BaseType_t status; + IotNetworkEvent_t event = { 0 }; + IotNMNetwork_t * pNetwork = NULL; + bool stateChange = false; + + for( ; ; ) + { + status = xQueueReceive( networkManager.eventQueue, &event, portMAX_DELAY ); + + if( status == pdTRUE ) + { + stateChange = false; + pNetwork = prvGetNetworkInstance( event.networkType ); + configASSERT( pNetwork != NULL ); + + xSemaphoreTake( networkManager.globalMutex, portMAX_DELAY ); + + if( ( pNetwork->state == eNetworkStateEnabled ) && ( event.eventType == IOT_NETWORK_EVENT_CONNECTED ) ) + { + pNetwork->state = eNetworkStateConnected; + stateChange = true; + } + else if( ( pNetwork->state == eNetworkStateConnected ) && ( event.eventType == IOT_NETWORK_EVENT_DISCONNECTED ) ) + { + pNetwork->state = eNetworkStateEnabled; + stateChange = true; + } + + xSemaphoreGive( networkManager.globalMutex ); + + if( stateChange ) + { + xSemaphoreTake( networkManager.subscriptionsMutex, portMAX_DELAY ); + prvDispatch( event.networkType, pNetwork->state ); + xSemaphoreGive( networkManager.subscriptionsMutex ); + } + } + } +} + + +/*-----------------------------------------------------------*/ + +static void _initializeTCPIPCredentials( void ) +{ + #if TCPIP_NETWORK_ENABLED + tcpIPConnectionParams.pHostName = clientcredentialMQTT_BROKER_ENDPOINT; + tcpIPConnectionParams.port = clientcredentialMQTT_BROKER_PORT; + + if( tcpIPConnectionParams.port == 443 ) + { + tcpIPCredentials.pAlpnProtos = socketsAWS_IOT_ALPN_MQTT; + } + else + { + tcpIPCredentials.pAlpnProtos = NULL; + } + + tcpIPCredentials.maxFragmentLength = 0; + tcpIPCredentials.disableSni = false; + tcpIPCredentials.pRootCa = NULL; + tcpIPCredentials.rootCaSize = 0; + tcpIPCredentials.pClientCert = keyCLIENT_CERTIFICATE_PEM; + tcpIPCredentials.clientCertSize = sizeof( keyCLIENT_CERTIFICATE_PEM ); + tcpIPCredentials.pPrivateKey = keyCLIENT_PRIVATE_KEY_PEM; + tcpIPCredentials.privateKeySize = sizeof( keyCLIENT_PRIVATE_KEY_PEM ); + #endif /* if TCPIP_NETWORK_ENABLED */ +} + +/*-----------------------------------------------------------*/ + +BaseType_t AwsIotNetworkManager_Init( void ) +{ + BaseType_t status = pdTRUE; + static bool isInit = false; + + if( !isInit ) + { + isInit = true; + + memset( &networkManager, 0x00, sizeof( IotNetworkManagerInfo_t ) ); + + networkManager.globalMutex = xSemaphoreCreateMutex(); + + if( networkManager.globalMutex == NULL ) + { + IotLogError( "Failed to create global mutex for network manager." ); + status = pdFALSE; + } + + if( status == pdTRUE ) + { + networkManager.subscriptionsMutex = xSemaphoreCreateMutex(); + + if( networkManager.subscriptionsMutex == NULL ) + { + IotLogError( "Failed to create subscription mutex for network manager." ); + status = pdFALSE; + } + } + + if( status == pdTRUE ) + { + networkManager.eventQueue = xQueueCreate( NETWORK_MANAGER_EVENT_QUEUE_SIZE, sizeof( IotNetworkEvent_t ) ); + + if( networkManager.eventQueue == NULL ) + { + IotLogError( "Failed to create event queue for network manager." ); + status = pdFALSE; + } + } + + if( status == pdTRUE ) + { + if( ( status = xTaskCreate( prvNetworkManagerTask, + "NetworkManager", + NETWORK_MANAGER_TASK_STACK_SIZE, + NULL, + NETWORK_MANAGER_TASK_PRIORITY, + NULL ) ) != pdPASS ) + { + IotLogError( "Failed to create network manager task." ); + } + } + + if( status == pdTRUE ) + { + networkManager.pNetworks = networks; + networkManager.numNetworks = sizeof( networks ) / sizeof( IotNMNetwork_t ); + _initializeTCPIPCredentials(); + } + } + + return status; +} + +BaseType_t AwsIotNetworkManager_SubscribeForStateChange( uint32_t networkTypes, + AwsIotNetworkStateChangeCb_t callback, + void * pContext, + IotNetworkManagerSubscription_t * pHandle ) +{ + BaseType_t ret = pdFALSE; + size_t index; + IotNMSubscription_t * pSubscription = NULL; + + xSemaphoreTake( networkManager.subscriptionsMutex, portMAX_DELAY ); + + for( index = 0; index < NETWORK_MANAGER_MAX_SUBSCRIPTIONS; index++ ) + { + pSubscription = &networkManager.subscriptions[ index ]; + + if( pSubscription->isActive == pdFALSE ) + { + pSubscription->isActive = pdTRUE; + pSubscription->networkTypes = networkTypes; + pSubscription->callback = callback; + pSubscription->pContext = pContext; + ( *pHandle ) = ( IotNetworkManagerSubscription_t ) pSubscription; + ret = pdTRUE; + break; + } + } + + xSemaphoreGive( networkManager.subscriptionsMutex ); + + if( ret == pdFALSE ) + { + IotLogError( "Not enough memory to store new subscription" ); + } + + return ret; +} + +BaseType_t AwsIotNetworkManager_RemoveSubscription( IotNetworkManagerSubscription_t handle ) +{ + BaseType_t ret = pdFALSE; + size_t index; + IotNMSubscription_t * pSubscription = NULL; + + xSemaphoreTake( networkManager.subscriptionsMutex, portMAX_DELAY ); + + for( index = 0; index < NETWORK_MANAGER_MAX_SUBSCRIPTIONS; index++ ) + { + pSubscription = &networkManager.subscriptions[ index ]; + + if( pSubscription == ( IotNMSubscription_t * ) handle ) + { + memset( pSubscription, 0x00, sizeof( IotNMSubscription_t ) ); + ret = pdTRUE; + break; + } + } + + xSemaphoreGive( networkManager.subscriptionsMutex ); + + if( ret == pdFALSE ) + { + IotLogError( "Cannot find the subscription to be removed." ); + } + + return ret; +} + +uint32_t AwsIotNetworkManager_GetConfiguredNetworks( void ) +{ + uint32_t networks = AWSIOT_NETWORK_TYPE_NONE; + size_t index; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + networks |= networkManager.pNetworks[ index ].type; + } + + return networks; +} + +uint32_t AwsIotNetworkManager_GetEnabledNetworks( void ) +{ + uint32_t networks = AWSIOT_NETWORK_TYPE_NONE; + size_t index; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + if( networkManager.pNetworks[ index ].state == eNetworkStateEnabled ) + { + networks |= networkManager.pNetworks[ index ].type; + } + } + + return networks; +} + +uint32_t AwsIotNetworkManager_GetConnectedNetworks( void ) +{ + uint32_t networks = AWSIOT_NETWORK_TYPE_NONE; + size_t index; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + if( networkManager.pNetworks[ index ].state == eNetworkStateConnected ) + { + networks |= networkManager.pNetworks[ index ].type; + } + } + + return networks; +} + +uint32_t AwsIotNetworkManager_EnableNetwork( uint32_t networkTypes ) +{ + uint32_t enabled = AWSIOT_NETWORK_TYPE_NONE; + + xSemaphoreTake( networkManager.globalMutex, portMAX_DELAY ); + + #if BLE_ENABLED + if( ( networkTypes & AWSIOT_NETWORK_TYPE_BLE ) == AWSIOT_NETWORK_TYPE_BLE ) + { + if( _bleEnable() == true ) + { + enabled |= AWSIOT_NETWORK_TYPE_BLE; + } + } + #endif + + #if WIFI_ENABLED + if( ( networkTypes & AWSIOT_NETWORK_TYPE_WIFI ) == AWSIOT_NETWORK_TYPE_WIFI ) + { + if( _wifiEnable() == true ) + { + enabled |= AWSIOT_NETWORK_TYPE_WIFI; + } + } + #endif + + #if ETH_ENABLED + if( ( networkTypes & AWSIOT_NETWORK_TYPE_ETH ) == AWSIOT_NETWORK_TYPE_ETH ) + { + if( _ethEnable() == true ) + { + enabled |= AWSIOT_NETWORK_TYPE_ETH; + } + } + #endif + + xSemaphoreGive( networkManager.globalMutex ); + + return enabled; +} + +uint32_t AwsIotNetworkManager_DisableNetwork( uint32_t networkTypes ) +{ + uint32_t disabled = AWSIOT_NETWORK_TYPE_NONE; + + /* Unused parameter when no networks enabled */ + ( void ) networkTypes; + + xSemaphoreTake( networkManager.globalMutex, portMAX_DELAY ); + + #if WIFI_ENABLED + if( ( networkTypes & AWSIOT_NETWORK_TYPE_WIFI ) == AWSIOT_NETWORK_TYPE_WIFI ) + { + if( _wifiDisable() == true ) + { + disabled |= AWSIOT_NETWORK_TYPE_WIFI; + } + } + #endif + + #if BLE_ENABLED + if( ( networkTypes & AWSIOT_NETWORK_TYPE_BLE ) == AWSIOT_NETWORK_TYPE_BLE ) + { + if( _bleDisable() == true ) + { + disabled |= AWSIOT_NETWORK_TYPE_BLE; + } + } + #endif + + #if ETH_ENABLED + if( ( networkTypes & AWSIOT_NETWORK_TYPE_ETH ) == AWSIOT_NETWORK_TYPE_ETH ) + { + if( _ethDisable() == true ) + { + disabled |= AWSIOT_NETWORK_TYPE_ETH; + } + } + #endif + + xSemaphoreGive( networkManager.globalMutex ); + + + return disabled; +} + +const IotNetworkInterface_t * AwsIotNetworkManager_GetNetworkInterface( uint32_t networkType ) +{ + const IotNetworkInterface_t * pInterface = NULL; + size_t index; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + if( networkManager.pNetworks[ index ].type == networkType ) + { + pInterface = networkManager.pNetworks[ index ].pNetworkInterface; + } + } + + return pInterface; +} + +void * AwsIotNetworkManager_GetCredentials( uint32_t networkType ) +{ + void * pCredentials = NULL; + size_t index; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + if( networkManager.pNetworks[ index ].type == networkType ) + { + pCredentials = networkManager.pNetworks[ index ].pCredentials; + } + } + + return pCredentials; +} + +void * AwsIotNetworkManager_GetConnectionParams( uint32_t networkType ) +{ + void * pConnectionParams = NULL; + size_t index; + + for( index = 0; index < networkManager.numNetworks; index++ ) + { + if( networkManager.pNetworks[ index ].type == networkType ) + { + pConnectionParams = networkManager.pNetworks[ index ].pConnectionParams; + } + } + + return pConnectionParams; +} diff --git a/bsp/aws_libraries/demos/network_manager/iot_network_manager_private.h b/bsp/aws_libraries/demos/network_manager/iot_network_manager_private.h new file mode 100644 index 0000000..99d03a6 --- /dev/null +++ b/bsp/aws_libraries/demos/network_manager/iot_network_manager_private.h @@ -0,0 +1,189 @@ +/* + * FreeRTOS V202012.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file aws_iot_network.h + * @brief Header file which defines all supported network types for Freertos. + */ +#ifndef AWS_IOT_NETWORK_H_ +#define AWS_IOT_NETWORK_H_ + +#include "types/iot_network_types.h" +#include "aws_iot_network_config.h" + +#include "platform/iot_network.h" + +#ifndef configSUPPORTED_NETWORKS + #error "Flag 'configSUPPORTED_NETWORKS' is not defined. Please define the flag in aws_iot_network_config.h with the list of all networks supported by the board" +#endif + +#ifndef configENABLED_NETWORKS + #error "Flag 'configENABLED_NETWORKS' not defined. Please define the flag in aws_iot_network_config.h with all the networks that needs to be enabled" +#endif + + +#if defined( configENABLED_NETWORKS ) && defined( configSUPPORTED_NETWORKS ) + #if ( ( configENABLED_NETWORKS | configSUPPORTED_NETWORKS ) != configSUPPORTED_NETWORKS ) + #error "Enabled networks should always be a subset of supported networks" + #endif +#endif + +/** + * @brief Compile time flag which can be used to check if BLE is enabled. + */ +#define BLE_ENABLED ( ( configENABLED_NETWORKS & AWSIOT_NETWORK_TYPE_BLE ) == AWSIOT_NETWORK_TYPE_BLE ) + +/** + * @brief Compile time flag which can be used to check if WIFI is enabled. + */ +#define WIFI_ENABLED ( ( configENABLED_NETWORKS & AWSIOT_NETWORK_TYPE_WIFI ) == AWSIOT_NETWORK_TYPE_WIFI ) + +/** + * @brief Compile time flag which can be used to check if Ethernet is enabled. + */ +#define ETH_ENABLED ( ( configENABLED_NETWORKS & AWSIOT_NETWORK_TYPE_ETH ) == AWSIOT_NETWORK_TYPE_ETH ) + +#define TCPIP_NETWORK_ENABLED ( ( configENABLED_NETWORKS & AWSIOT_NETWORK_TYPE_TCP_IP ) != 0 ) + +/** + * @brief Initializer for a subscription handle. + */ +#define IOT_NETWORK_MANAGER_SUBSCRIPTION_INITIALIZER ( NULL ) + + +/** + * @brief Unique handle for a network manager user callback subscription. + */ +typedef void * IotNetworkManagerSubscription_t; + + +/** + * @brief Callback used for passing state change events from network layer to application layer. + * + * Application can register the callback with network layer such as WIFI or BLE. + * + * @param[in] ulNetworkType Network type to be passed within the callback + * @param[in] pvContext The context passed in at the time of registering. + */ +typedef void ( * AwsIotNetworkStateChangeCb_t ) ( uint32_t ulNetworkType, + AwsIotNetworkState_t xNetworkState, + void * pvContext ); + + +/** + * @brief API to subscribe for the network state change event. + * + * Application can register multiple callbacks, single callback for multiple network types + * or separate callbacks for each network type. + * + * @param ulNetworkTpe Network type for the callback + * @param xCallback Callback for receiving the network state change event + * @param pvContext Context passed in as it is by the callback + * @param pxHandle Handle to the subscription + * @return pdTRUE or pdFALSE + */ +BaseType_t AwsIotNetworkManager_SubscribeForStateChange( uint32_t ulNetworkTypes, + AwsIotNetworkStateChangeCb_t xCallback, + void * pvContext, + IotNetworkManagerSubscription_t * pxHandle ); + + +/** + * @brief Removes a subscription for network state change + * @param xHandle Handle to the subscription + * @return pdTRUE or pdFALSE + */ +BaseType_t AwsIotNetworkManager_RemoveSubscription( IotNetworkManagerSubscription_t xHandle ); + + +/** + * @brief Returns all network types which are connected. + * @return Network Types of all connected networks. + */ +uint32_t AwsIotNetworkManager_GetConnectedNetworks( void ); + +/** + * @brief Gets all supported networks + * @return Flags indicating all configured networks + */ +uint32_t AwsIotNetworkManager_GetConfiguredNetworks( void ); + + +/** + * @brief Get the networks which are enabled currently. + * @return Flags indicating all enabled networks. + */ +uint32_t AwsIotNetworkManager_GetEnabledNetworks( void ); + +/** + * @brief Get the network interface for a given network. + * The network interface can be used to create/delete a network connection, send/receive data over the connection. + * + * @param[in] networkType The type of the network + * @return NetworkInterface stucture for the network type. + * + */ +const IotNetworkInterface_t * AwsIotNetworkManager_GetNetworkInterface( uint32_t networkType ); + +/** + * @brief Gets the credentials associated with the network. + * Credentials can then be passed in to the network interface create API to create a secure connection over the network. + * + * @param[in] networkType Type of the network + * @return Blob representing the credentials associated with a network. NULL if no credentials are provided. + */ +void * AwsIotNetworkManager_GetCredentials( uint32_t networkType ); + +/** + * @brief Gets the connection parameters associated with a network. + * Connection parameters can the be passed in to the network interface create API to create a connection over the network. + * + * @param[in] networkType Type of the network + * @return Blob representing the parameters for connection over a network. + */ +void * AwsIotNetworkManager_GetConnectionParams( uint32_t networkType ); + +/** + * API to enable network manager for different networks + * @param ulNetworkTypes Network types + * @return FLag indicating the network types enabled + */ +uint32_t AwsIotNetworkManager_EnableNetwork( uint32_t ulNetworkTypes ); + +/** + * API to disable network manager for different networks + * + * @param ulNetworkTypes Network types + * @return FLag indicating the network types disabled + */ +uint32_t AwsIotNetworkManager_DisableNetwork( uint32_t ulNetworkTypes ); + +/** + * Initializes the network manager + * @return pdTRUE or pdFALSE + */ +BaseType_t AwsIotNetworkManager_Init( void ); + +#endif /* LIB_AWS_INCLUDE_AWS_IOT_NETWORK_H_ */ diff --git a/bsp/aws_libraries/freertos_plus/standard/crypto/include/iot_crypto.h b/bsp/aws_libraries/freertos_plus/standard/crypto/include/iot_crypto.h new file mode 100644 index 0000000..0069b11 --- /dev/null +++ b/bsp/aws_libraries/freertos_plus/standard/crypto/include/iot_crypto.h @@ -0,0 +1,103 @@ +/* + * FreeRTOS Crypto V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +#ifndef __AWS_CRYPTO__H__ +#define __AWS_CRYPTO__H__ + +#include "FreeRTOS.h" + +/** + * @brief Commonly used buffer sizes for storing cryptographic hash computation + * results. + */ +#define cryptoSHA1_DIGEST_BYTES 20 +#define cryptoSHA256_DIGEST_BYTES 32 + +/** + * @brief Initializes the heap and threading functions for cryptography libraries. + */ +void CRYPTO_Init( void ); + +/** + * @brief Initializes the mbedTLS mutex functions. + * + * Provides mbedTLS access to mutex create, destroy, take and free. + * + * @see MBEDTLS_THREADING_ALT + */ +void CRYPTO_ConfigureThreading( void ); + +/** + * @brief Library-independent cryptographic algorithm identifiers. + */ +#define cryptoHASH_ALGORITHM_SHA1 1 +#define cryptoHASH_ALGORITHM_SHA256 2 +#define cryptoASYMMETRIC_ALGORITHM_RSA 1 +#define cryptoASYMMETRIC_ALGORITHM_ECDSA 2 + +/** + * @brief Initializes digital signature verification. + * + * @param[out] ppvContext Opaque context structure. + * @param[in] xAsymmetricAlgorithm Cryptographic public key cryptosystem. + * @param[in] xHashAlgorithm Cryptographic hash algorithm that was used for signing. + * + * @return pdTRUE if initialization succeeds, or pdFALSE otherwise. + */ +BaseType_t CRYPTO_SignatureVerificationStart( void ** ppvContext, + BaseType_t xAsymmetricAlgorithm, + BaseType_t xHashAlgorithm ); + +/** + * @brief Updates a cryptographic hash computation with the specified byte array. + * + * @param[in] pvContext Opaque context structure. + * @param[in] pucData Byte array that was signed. + * @param[in] xDataLength Length in bytes of data that was signed. + */ +void CRYPTO_SignatureVerificationUpdate( void * pvContext, + const uint8_t * pucData, + size_t xDataLength ); + +/** + * @brief Verifies a digital signature computation using the public key from the + * specified certificate. + * + * @param[in] pvContext Opaque context structure. + * @param[in] pucSignerCertificate Base64 and DER encoded X.509 certificate of the + * signer. + * @param[in] xSignerCertificateLength Length in bytes of the certificate. + * @param[in] pucSignature Digital signature result to verify. + * @param[in] xSignatureLength in bytes of digital signature result. + * + * @return pdTRUE if the signature is correct or pdFALSE if the signature is invalid. + */ +BaseType_t CRYPTO_SignatureVerificationFinal( void * pvContext, + char * pcSignerCertificate, + size_t xSignerCertificateLength, + uint8_t * pucSignature, + size_t xSignatureLength ); + +#endif /* ifndef __AWS_CRYPTO__H__ */ diff --git a/bsp/aws_libraries/freertos_plus/standard/crypto/src/iot_crypto.c b/bsp/aws_libraries/freertos_plus/standard/crypto/src/iot_crypto.c new file mode 100644 index 0000000..32945f6 --- /dev/null +++ b/bsp/aws_libraries/freertos_plus/standard/crypto/src/iot_crypto.c @@ -0,0 +1,393 @@ +/* + * FreeRTOS Crypto V1.1.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "iot_crypto.h" + +/* mbedTLS includes. */ + +#if !defined( MBEDTLS_CONFIG_FILE ) + #include "mbedtls/config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/platform.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha1.h" +#include "mbedtls/pk.h" +#include "mbedtls/x509_crt.h" +/* Threading mutex implementations for mbedTLS. */ +#include "mbedtls/threading.h" +#include "threading_alt.h" + +/* C runtime includes. */ +#include + + + +#define CRYPTO_PRINT( X ) configPRINTF( X ) + +/** + * @brief Internal signature verification context structure + */ +typedef struct SignatureVerificationState +{ + BaseType_t xAsymmetricAlgorithm; + BaseType_t xHashAlgorithm; + mbedtls_sha1_context xSHA1Context; + mbedtls_sha256_context xSHA256Context; +} SignatureVerificationState_t, * SignatureVerificationStatePtr_t; + +/*-----------------------------------------------------------*/ +/*------ Helper functions for FreeRTOS heap management ------*/ +/*-----------------------------------------------------------*/ + +/* If mbedTLS is using AFR managed memory, it needs access to an implementation of calloc. */ +#ifdef CONFIG_MEDTLS_USE_AFR_MEMORY + +/** + * @brief Implements libc calloc semantics using the FreeRTOS heap + */ + void * pvCalloc( size_t xNumElements, + size_t xSize ) + { + void * pvNew = pvPortMalloc( xNumElements * xSize ); + + if( NULL != pvNew ) + { + memset( pvNew, 0, xNumElements * xSize ); + } + + return pvNew; + } +#endif /* ifdef CONFIG_MEDTLS_USE_AFR_MEMORY */ + +/*-----------------------------------------------------------*/ +/*--------- mbedTLS threading functions for FreeRTOS --------*/ +/*--------------- See MBEDTLS_THREADING_ALT -----------------*/ +/*-----------------------------------------------------------*/ + +/** + * @brief Implementation of mbedtls_mutex_init for thread-safety. + * + */ +void aws_mbedtls_mutex_init( mbedtls_threading_mutex_t * mutex ) +{ + mutex->mutex = xSemaphoreCreateMutex(); + + if( mutex->mutex != NULL ) + { + mutex->is_valid = 1; + } + else + { + mutex->is_valid = 0; + CRYPTO_PRINT( ( "Failed to initialize mbedTLS mutex.\r\n" ) ); + } +} + +/** + * @brief Implementation of mbedtls_mutex_free for thread-safety. + * + */ +void aws_mbedtls_mutex_free( mbedtls_threading_mutex_t * mutex ) +{ + if( mutex->is_valid == 1 ) + { + vSemaphoreDelete( mutex->mutex ); + mutex->is_valid = 0; + } +} + +/** + * @brief Implementation of mbedtls_mutex_lock for thread-safety. + * + * @return 0 if successful, MBEDTLS_ERR_THREADING_MUTEX_ERROR if timeout, + * MBEDTLS_ERR_THREADING_BAD_INPUT_DATA if the mutex is not valid. + */ +int aws_mbedtls_mutex_lock( mbedtls_threading_mutex_t * mutex ) +{ + int ret = MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; + + if( mutex->is_valid == 1 ) + { + if( xSemaphoreTake( mutex->mutex, portMAX_DELAY ) ) + { + ret = 0; + } + else + { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + CRYPTO_PRINT( ( "Failed to obtain mbedTLS mutex.\r\n" ) ); + } + } + + return ret; +} + +/** + * @brief Implementation of mbedtls_mutex_unlock for thread-safety. + * + * @return 0 if successful, MBEDTLS_ERR_THREADING_MUTEX_ERROR if timeout, + * MBEDTLS_ERR_THREADING_BAD_INPUT_DATA if the mutex is not valid. + */ +int aws_mbedtls_mutex_unlock( mbedtls_threading_mutex_t * mutex ) +{ + int ret = MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; + + if( mutex->is_valid == 1 ) + { + if( xSemaphoreGive( mutex->mutex ) ) + { + ret = 0; + } + else + { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + CRYPTO_PRINT( ( "Failed to unlock mbedTLS mutex.\r\n" ) ); + } + } + + return ret; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Verifies a cryptographic signature based on the signer + * certificate, hash algorithm, and the data that was signed. + */ +static BaseType_t prvVerifySignature( char * pcSignerCertificate, + size_t xSignerCertificateLength, + BaseType_t xHashAlgorithm, + uint8_t * pucHash, + size_t xHashLength, + uint8_t * pucSignature, + size_t xSignatureLength ) +{ + BaseType_t xResult = pdTRUE; + mbedtls_x509_crt xCertCtx; + mbedtls_md_type_t xMbedHashAlg = MBEDTLS_MD_SHA256; + + + memset( &xCertCtx, 0, sizeof( mbedtls_x509_crt ) ); + + /* + * Map the hash algorithm + */ + if( cryptoHASH_ALGORITHM_SHA1 == xHashAlgorithm ) + { + xMbedHashAlg = MBEDTLS_MD_SHA1; + } + + /* + * Decode and create a certificate context + */ + mbedtls_x509_crt_init( &xCertCtx ); + + if( 0 != mbedtls_x509_crt_parse( + &xCertCtx, ( const unsigned char * ) pcSignerCertificate, xSignerCertificateLength ) ) + { + xResult = pdFALSE; + } + + /* + * Verify the signature using the public key from the decoded certificate + */ + if( pdTRUE == xResult ) + { + if( 0 != mbedtls_pk_verify( + &xCertCtx.pk, + xMbedHashAlg, + pucHash, + xHashLength, + pucSignature, + xSignatureLength ) ) + { + xResult = pdFALSE; + } + } + + /* + * Clean-up + */ + mbedtls_x509_crt_free( &xCertCtx ); + + return xResult; +} + +/* + * Interface routines + */ + +void CRYPTO_Init( void ) +{ + CRYPTO_ConfigureThreading(); +} + +void CRYPTO_ConfigureThreading( void ) +{ + /* Configure mbedtls to use FreeRTOS mutexes. */ + mbedtls_threading_set_alt( aws_mbedtls_mutex_init, + aws_mbedtls_mutex_free, + aws_mbedtls_mutex_lock, + aws_mbedtls_mutex_unlock ); +} + +/** + * @brief Creates signature verification context. + */ +BaseType_t CRYPTO_SignatureVerificationStart( void ** ppvContext, + BaseType_t xAsymmetricAlgorithm, + BaseType_t xHashAlgorithm ) +{ + BaseType_t xResult = pdTRUE; + SignatureVerificationState_t * pxCtx = NULL; + + /* + * Allocate the context + */ + if( NULL == ( pxCtx = ( SignatureVerificationStatePtr_t ) pvPortMalloc( + sizeof( *pxCtx ) ) ) ) /*lint !e9087 Allow casting void* to other types. */ + { + xResult = pdFALSE; + } + + if( pdTRUE == xResult ) + { + *ppvContext = pxCtx; + + /* + * Store the algorithm identifiers + */ + pxCtx->xAsymmetricAlgorithm = xAsymmetricAlgorithm; + pxCtx->xHashAlgorithm = xHashAlgorithm; + + /* + * Initialize the requested hash type + */ + if( cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm ) + { + mbedtls_sha1_init( &pxCtx->xSHA1Context ); + ( void ) mbedtls_sha1_starts_ret( &pxCtx->xSHA1Context ); + } + else + { + mbedtls_sha256_init( &pxCtx->xSHA256Context ); + ( void ) mbedtls_sha256_starts_ret( &pxCtx->xSHA256Context, 0 ); + } + } + + return xResult; +} + +/** + * @brief Adds bytes to an in-progress hash for subsequent signature + * verification. + */ +void CRYPTO_SignatureVerificationUpdate( void * pvContext, + const uint8_t * pucData, + size_t xDataLength ) +{ + SignatureVerificationState_t * pxCtx = ( SignatureVerificationStatePtr_t ) pvContext; /*lint !e9087 Allow casting void* to other types. */ + + /* + * Add the data to the hash of the requested type + */ + if( cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm ) + { + ( void ) mbedtls_sha1_update_ret( &pxCtx->xSHA1Context, pucData, xDataLength ); + } + else + { + ( void ) mbedtls_sha256_update_ret( &pxCtx->xSHA256Context, pucData, xDataLength ); + } +} + +/** + * @brief Performs signature verification on a cryptographic hash. + */ +BaseType_t CRYPTO_SignatureVerificationFinal( void * pvContext, + char * pcSignerCertificate, + size_t xSignerCertificateLength, + uint8_t * pucSignature, + size_t xSignatureLength ) +{ + BaseType_t xResult = pdFALSE; + + if( pvContext != NULL ) + { + SignatureVerificationStatePtr_t pxCtx = ( SignatureVerificationStatePtr_t ) pvContext; /*lint !e9087 Allow casting void* to other types. */ + uint8_t ucSHA1or256[ cryptoSHA256_DIGEST_BYTES ]; /* Reserve enough space for the larger of SHA1 or SHA256 results. */ + uint8_t * pucHash = NULL; + size_t xHashLength = 0; + + if( ( pcSignerCertificate != NULL ) && + ( pucSignature != NULL ) && + ( xSignerCertificateLength > 0UL ) && + ( xSignatureLength > 0UL ) ) + { + /* + * Finish the hash + */ + if( cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm ) + { + ( void ) mbedtls_sha1_finish_ret( &pxCtx->xSHA1Context, ucSHA1or256 ); + pucHash = ucSHA1or256; + xHashLength = cryptoSHA1_DIGEST_BYTES; + } + else + { + ( void ) mbedtls_sha256_finish_ret( &pxCtx->xSHA256Context, ucSHA1or256 ); + pucHash = ucSHA1or256; + xHashLength = cryptoSHA256_DIGEST_BYTES; + } + + /* + * Verify the signature + */ + xResult = prvVerifySignature( pcSignerCertificate, + xSignerCertificateLength, + pxCtx->xHashAlgorithm, + pucHash, + xHashLength, + pucSignature, + xSignatureLength ); + } + else + { + /* Allow function to be called with only the context pointer for cleanup after a failure. */ + } + + /* + * Clean-up + */ + vPortFree( pxCtx ); + } + + return xResult; +} diff --git a/bsp/aws_libraries/freertos_plus/standard/tls/include/iot_tls.h b/bsp/aws_libraries/freertos_plus/standard/tls/include/iot_tls.h new file mode 100644 index 0000000..b47edd5 --- /dev/null +++ b/bsp/aws_libraries/freertos_plus/standard/tls/include/iot_tls.h @@ -0,0 +1,178 @@ +/* + * FreeRTOS TLS V1.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +#ifndef __AWS__TLS__H__ +#define __AWS__TLS__H__ + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include iot_tls.h" +#endif + +/** + * @defgroup TlsErrors TLS Error Codes + * @brief Error codes returned by the TLS API. + * + * Note that TLS API may also propagate port-specific + * error codes, or codes from mbedTLS. + */ +/**@{ */ +#define TLS_ERROR_HANDSHAKE_FAILED ( -2001 ) /*!< Error in handshake. */ +#define TLS_ERROR_RNG ( -2002 ) /*!< Error in RNG. */ +#define TLS_ERROR_SIGN ( -2003 ) /*!< Error in sign operation. */ +#define TLS_ERROR_NO_PRIVATE_KEY ( -2004 ) /*!< Private key was not provisioned. */ +#define TLS_ERROR_NO_CERTIFICATE ( -2005 ) /*!< Client certificate not provisioned. */ + +/**@} */ + +/** + * @brief Defines callback type for receiving bytes from the network. + * + * @param[in] pvCallerContext Opaque context handle provided by caller. + * @param[out] pucReceiveBuffer Buffer to fill with received data. + * @param[in] xReceiveLength Length of previous parameter in bytes. + * + * @return The number of bytes actually read. + */ +typedef BaseType_t ( * NetworkRecv_t )( void * pvCallerContext, + unsigned char * pucReceiveBuffer, + size_t xReceiveLength ); + +/** + * @brief Defines callback type for sending bytes to the network. + * + * @param[in] pvCallerContext Opaque context handle provided by caller. + * @param[out] pucReceiveBuffer Buffer of data to send. + * @param[in] xReceiveLength Length of previous parameter in bytes. + * + * @return The number of bytes actually sent. + */ +typedef BaseType_t ( * NetworkSend_t )( void * pvCallerContext, + const unsigned char * pucData, + size_t xDataLength ); + +/** + * @brief Defines parameter structure for initializing the TLS interface. + * + * @param[in] ulSize Size of the structure in bytes. + * @param[in] pcDestination Network name of the TLS server. + * @param[in] pcServerCertificate PEM encoded server certificate to trust. + * @param[in] ulServerCertificateLength Length in bytes of the encoded server + * certificate. The length must include the null terminator. + * @param[in] pxNetworkRecv Caller-defined network receive function pointer. + * @param[in] pxNetworkSend Caller-defined network send function pointer. + * @param[in] pvCallerContext Caller-defined context handle to be used with callback + * functions. + */ +typedef struct xTLS_PARAMS +{ + uint32_t ulSize; + const char * pcDestination; + const char * pcServerCertificate; + uint32_t ulServerCertificateLength; + const char ** ppcAlpnProtocols; + uint32_t ulAlpnProtocolsCount; + + NetworkRecv_t pxNetworkRecv; + NetworkSend_t pxNetworkSend; + void * pvCallerContext; +} TLSParams_t; + +/** + * @brief Initializes the TLS context. + * + * @param[out] ppvContext Opaque context handle returned by the TLS library. + * @param[in] pxParams Connection parameters specified by caller. + * + * @return Zero on success. Error return codes have the high bit set. + */ +BaseType_t TLS_Init( void ** ppvContext, + TLSParams_t * pxParams ); + +/** + * @brief Negotiates TLS and connects to the server. + * + * @param pvContext Opaque context handle for TLS library. + * + * @return Zero on success. Error return codes have the high bit set. + */ +BaseType_t TLS_Connect( void * pvContext ); + +/** + * @brief Reads the requested number of bytes from the secure connection + * + * @param pvContext Opaque context handle for TLS library. + * @param pucReadBuffer Byte array for storing (decrypted) data read from the + * network. + * @param xReadLength Length in bytes of read buffer. + * + * @return Number of bytes read. Error return codes have the high bit set. + */ +BaseType_t TLS_Recv( void * pvContext, + unsigned char * pucReadBuffer, + size_t xReadLength ); + +/** + * @brief Writes the requested number of bytes to the secure connection. + * + * @param pvContext Opaque context handle for TLS library. + * @param pucMsg Byte array of data to be encrypted and then sent to the network. + * @param xMsgLength Length in bytes of write buffer. + * + * @return Number of bytes read. Error return codes have the high bit set. + */ +BaseType_t TLS_Send( void * pvContext, + const unsigned char * pucMsg, + size_t xMsgLength ); + +/** + * @brief Frees resources consumed by the TLS context. + * + * @param pvContext Opaque context handle for TLS library. + */ +void TLS_Cleanup( void * pvContext ); + +/** + * @brief callback to verify the expiration date of the certificate + * + * This callback will return TRUE if the date provided is in the past. + * + * @param day the expiration date day to check + * @param month the expiration date month to check + * @param year the expiration date year to check. Note: this is the full year i.e. 1932 + * + * @return non-zero if the date is in the past + */ +typedef BaseType_t (* DateIsInThePast_t)( BaseType_t day, + BaseType_t month, + BaseType_t year ); + +/** + * @brief function to set the callback for testing the expiration date of certificates + * + * @param DateIsInThePast a function that tests the expiration date against the current date + */ +void TLS_setDateIsInThePastFunction( DateIsInThePast_t dateIsInThePast ); + +#endif /* ifndef __AWS__TLS__H__ */ diff --git a/bsp/aws_libraries/freertos_plus/standard/tls/src/iot_tls.c b/bsp/aws_libraries/freertos_plus/standard/tls/src/iot_tls.c new file mode 100644 index 0000000..2c1315f --- /dev/null +++ b/bsp/aws_libraries/freertos_plus/standard/tls/src/iot_tls.c @@ -0,0 +1,1096 @@ +/* + * FreeRTOS TLS V1.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "FreeRTOSIPConfig.h" +#include "iot_tls.h" +#include "iot_crypto.h" +#include "core_pkcs11_config.h" +#include "core_pkcs11.h" +#include "task.h" +#include "aws_clientcredential_keys.h" +#include "iot_default_root_certificates.h" +#include "core_pki_utils.h" + +/* mbedTLS includes. */ +#include "mbedtls/platform.h" +#include "mbedtls/net.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/entropy.h" +#include "mbedtls/sha256.h" +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" +#include "mbedtls/debug.h" + +#ifdef MBEDTLS_DEBUG_C + #define tlsDEBUG_VERBOSE 4 +#endif + +/* Custom mbedtls utls include. */ +#include "mbedtls_error.h" + +/* C runtime includes. */ +#include +#include +#include + +/** + * @brief Represents string to be logged when mbedTLS returned error + * does not contain a high-level code. + */ +static const char * pNoHighLevelMbedTlsCodeStr = ""; + +/** + * @brief Represents string to be logged when mbedTLS returned error + * does not contain a low-level code. + */ +static const char * pNoLowLevelMbedTlsCodeStr = ""; + +/** + * @brief Utility for converting the high-level code in an mbedTLS error to string, + * if the code-contains a high-level code; otherwise, using a default string. + */ +#define mbedtlsHighLevelCodeOrDefault( mbedTlsCode ) \ + ( mbedtls_strerror_highlevel( mbedTlsCode ) != NULL ) ? \ + mbedtls_strerror_highlevel( mbedTlsCode ) : pNoHighLevelMbedTlsCodeStr + + +/** + * @brief Utility for converting the level-level code in an mbedTLS error to string, + * if the code-contains a level-level code; otherwise, using a default string. + */ +#define mbedtlsLowLevelCodeOrDefault( mbedTlsCode ) \ + ( mbedtls_strerror_lowlevel( mbedTlsCode ) != NULL ) ? \ + mbedtls_strerror_lowlevel( mbedTlsCode ) : pNoLowLevelMbedTlsCodeStr + + +/** + * @brief Internal context structure. + * + * @param[in] pcDestination Server location, can be a DNS name or IP address. + * @param[in] pcServerCertificate Server X.509 certificate in PEM format to trust. + * @param[in] ulServerCertificateLength Length in bytes of the server certificate. + * @param[in] xNetworkRecv Callback for receiving data on an open TCP socket. + * @param[in] xNetworkSend Callback for sending data on an open TCP socket. + * @param[in] pvCallerContext Opaque pointer provided by caller for above callbacks. + * @param[out] xTLSHandshakeState Indicates the state of the TLS handshake. + * @param[out] xMbedSslCtx Connection context for mbedTLS. + * @param[out] xMbedSslConfig Configuration context for mbedTLS. + * @param[out] xMbedX509CA Server certificate context for mbedTLS. + * @param[out] xMbedX509Cli Client certificate context for mbedTLS. + * @param[out] mbedPkAltCtx RSA crypto implementation context for mbedTLS. + * @param[out] pxP11FunctionList PKCS#11 function list structure. + * @param[out] xP11Session PKCS#11 session context. + * @param[out] xP11PrivateKey PKCS#11 private key context. + */ +typedef struct TLSContext +{ + const char * pcDestination; + const char * pcServerCertificate; + uint32_t ulServerCertificateLength; + const char ** ppcAlpnProtocols; + uint32_t ulAlpnProtocolsCount; + + NetworkRecv_t xNetworkRecv; + NetworkSend_t xNetworkSend; + void * pvCallerContext; + BaseType_t xTLSHandshakeState; + + /* mbedTLS. */ + mbedtls_ssl_context xMbedSslCtx; + mbedtls_ssl_config xMbedSslConfig; + mbedtls_x509_crt xMbedX509CA; + mbedtls_x509_crt xMbedX509Cli; + mbedtls_pk_context xMbedPkCtx; + mbedtls_pk_info_t xMbedPkInfo; + mbedtls_ctr_drbg_context xMbedDrbgCtx; + + /* PKCS#11. */ + CK_FUNCTION_LIST_PTR pxP11FunctionList; + CK_SESSION_HANDLE xP11Session; + CK_OBJECT_HANDLE xP11PrivateKey; + CK_KEY_TYPE xKeyType; +} TLSContext_t; + +#define TLS_HANDSHAKE_NOT_STARTED ( 0 ) /* Must be 0 */ +#define TLS_HANDSHAKE_STARTED ( 1 ) +#define TLS_HANDSHAKE_SUCCESSFUL ( 2 ) + +#define TLS_PRINT( X ) configPRINTF( X ) + +static BaseType_t prvDefault_DateIsInThePast( BaseType_t day, + BaseType_t month, + BaseType_t year ); +static DateIsInThePast_t pDateIsInThePast = prvDefault_DateIsInThePast; + +/*-----------------------------------------------------------*/ + +/* + * Helper routines. + */ + +/** + * @brief TLS internal context rundown helper routine. + * + * @param[in] pvContext Caller context. + */ +static void prvFreeContext( TLSContext_t * pxCtx ) +{ + if( NULL != pxCtx ) + { + /* Cleanup mbedTLS. */ + mbedtls_ssl_close_notify( &pxCtx->xMbedSslCtx ); /*lint !e534 The error is already taken care of inside mbedtls_ssl_close_notify*/ + mbedtls_ssl_free( &pxCtx->xMbedSslCtx ); + mbedtls_ssl_config_free( &pxCtx->xMbedSslConfig ); + mbedtls_ctr_drbg_free( &pxCtx->xMbedDrbgCtx ); + + /* Cleanup PKCS11 only if the handshake was started. */ + if( ( TLS_HANDSHAKE_NOT_STARTED != pxCtx->xTLSHandshakeState ) && + ( NULL != pxCtx->pxP11FunctionList ) && + ( NULL != pxCtx->pxP11FunctionList->C_CloseSession ) && + ( CK_INVALID_HANDLE != pxCtx->xP11Session ) ) + { + pxCtx->pxP11FunctionList->C_CloseSession( pxCtx->xP11Session ); /*lint !e534 This function always return CKR_OK. */ + } + + pxCtx->xTLSHandshakeState = TLS_HANDSHAKE_NOT_STARTED; + } +} + +static BaseType_t prvDefault_DateIsInThePast( BaseType_t day, + BaseType_t month, + BaseType_t year ) +{ + return 0; /* Assume the certificate is valid. */ +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Network send callback shim. + * + * @param[in] pvContext Caller context. + * @param[in] pucData Byte buffer to send. + * @param[in] xDataLength Length of byte buffer to send. + * + * @return Number of bytes sent, or a negative value on error. + */ +static int prvNetworkSend( void * pvContext, + const unsigned char * pucData, + size_t xDataLength ) +{ + TLSContext_t * pxCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + + return ( int ) pxCtx->xNetworkSend( pxCtx->pvCallerContext, pucData, xDataLength ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Network receive callback shim. + * + * @param[in] pvContext Caller context. + * @param[out] pucReceiveBuffer Byte buffer to receive into. + * @param[in] xReceiveLength Length of byte buffer for receive. + * + * @return Number of bytes received, or a negative value on error. + */ +static int prvNetworkRecv( void * pvContext, + unsigned char * pucReceiveBuffer, + size_t xReceiveLength ) +{ + TLSContext_t * pxCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + + return ( int ) pxCtx->xNetworkRecv( pxCtx->pvCallerContext, pucReceiveBuffer, xReceiveLength ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Callback that wraps PKCS#11 for pseudo-random number generation. + * + * @param[in] pvCtx Caller context. + * @param[in] pucRandom Byte array to fill with random data. + * @param[in] xRandomLength Length of byte array. + * + * @return Zero on success. + */ +static int prvGenerateRandomBytes( void * pvCtx, + unsigned char * pucRandom, + size_t xRandomLength ) +{ + TLSContext_t * pxCtx = ( TLSContext_t * ) pvCtx; /*lint !e9087 !e9079 Allow casting void* to other types. */ + int xResult = 0; + + xResult = mbedtls_ctr_drbg_random( &pxCtx->xMbedDrbgCtx, pucRandom, xRandomLength ); + + if( xResult != 0 ) + { + TLS_PRINT( ( "ERROR: Failed to generate random bytes %s : %s \r\n", + mbedtlsHighLevelCodeOrDefault( xResult ), + mbedtlsLowLevelCodeOrDefault( xResult ) ) ); + xResult = TLS_ERROR_RNG; + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Callback that enforces a worst-case expiration check on TLS server + * certificates. + * + * @param[in] pvCtx Caller context. + * @param[in] pxCertificate Certificate to check. + * @param[in] lPathCount Location of this certificate in the chain. + * @param[in] pulFlags Verification status flags. + * + * @return Zero on success. + */ +static int prvCheckCertificate( void * pvContext, + mbedtls_x509_crt * pxCertificate, + int lPathCount, + uint32_t * pulFlags ) +{ + /* Unreferenced parameters. */ + ( void ) ( pvContext ); + ( void ) ( lPathCount ); + + BaseType_t day = pxCertificate->valid_to.day; + BaseType_t month = pxCertificate->valid_to.mon; + BaseType_t year = pxCertificate->valid_to.year; + + if( pDateIsInThePast( day, month, year ) != 0 ) + { + *pulFlags |= MBEDTLS_X509_BADCERT_EXPIRED; + } + + return 0; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Sign a cryptographic hash with the private key. + * + * @param[in] pvContext Crypto context. + * @param[in] xMdAlg Unused. + * @param[in] pucHash Length in bytes of hash to be signed. + * @param[in] uiHashLen Byte array of hash to be signed. + * @param[out] pucSig RSA signature bytes. + * @param[in] pxSigLen Length in bytes of signature buffer. + * @param[in] piRng Unused. + * @param[in] pvRng Unused. + * + * @return Zero on success. + */ +static int prvPrivateKeySigningCallback( void * pvContext, + mbedtls_md_type_t xMdAlg, + const unsigned char * pucHash, + size_t xHashLen, + unsigned char * pucSig, + size_t * pxSigLen, + int ( * piRng )( void *, + unsigned char *, + size_t ), /*lint !e955 This parameter is unused. */ + void * pvRng ) +{ + CK_RV xResult = CKR_OK; + int lFinalResult = 0; + TLSContext_t * pxTLSContext = ( TLSContext_t * ) pvContext; + CK_MECHANISM xMech = { 0 }; + CK_BYTE xToBeSigned[ 256 ]; + CK_ULONG xToBeSignedLen = sizeof( xToBeSigned ); + + /* Unreferenced parameters. */ + ( void ) ( piRng ); + ( void ) ( pvRng ); + ( void ) ( xMdAlg ); + + /* Sanity check buffer length. */ + if( xHashLen > sizeof( xToBeSigned ) ) + { + xResult = CKR_ARGUMENTS_BAD; + } + + /* Format the hash data to be signed. */ + if( CKK_RSA == pxTLSContext->xKeyType ) + { + xMech.mechanism = CKM_RSA_PKCS; + + /* mbedTLS expects hashed data without padding, but PKCS #11 C_Sign function performs a hash + * & sign if hash algorithm is specified. This helper function applies padding + * indicating data was hashed with SHA-256 while still allowing pre-hashed data to + * be provided. */ + xResult = vAppendSHA256AlgorithmIdentifierSequence( ( uint8_t * ) pucHash, xToBeSigned ); + xToBeSignedLen = pkcs11RSA_SIGNATURE_INPUT_LENGTH; + } + else if( CKK_EC == pxTLSContext->xKeyType ) + { + xMech.mechanism = CKM_ECDSA; + memcpy( xToBeSigned, pucHash, xHashLen ); + xToBeSignedLen = xHashLen; + } + else + { + xResult = CKR_ARGUMENTS_BAD; + } + + if( CKR_OK == xResult ) + { + /* Use the PKCS#11 module to sign. */ + xResult = pxTLSContext->pxP11FunctionList->C_SignInit( pxTLSContext->xP11Session, + &xMech, + pxTLSContext->xP11PrivateKey ); + } + + if( CKR_OK == xResult ) + { + *pxSigLen = sizeof( xToBeSigned ); + xResult = pxTLSContext->pxP11FunctionList->C_Sign( ( CK_SESSION_HANDLE ) pxTLSContext->xP11Session, + xToBeSigned, + xToBeSignedLen, + pucSig, + ( CK_ULONG_PTR ) pxSigLen ); + } + + if( ( xResult == CKR_OK ) && ( CKK_EC == pxTLSContext->xKeyType ) ) + { + /* PKCS #11 for P256 returns a 64-byte signature with 32 bytes for R and 32 bytes for S. + * This must be converted to an ASN.1 encoded array. */ + if( *pxSigLen != pkcs11ECDSA_P256_SIGNATURE_LENGTH ) + { + xResult = CKR_FUNCTION_FAILED; + } + + if( xResult == CKR_OK ) + { + PKI_pkcs11SignatureTombedTLSSignature( pucSig, pxSigLen ); + } + } + + if( xResult != CKR_OK ) + { + TLS_PRINT( ( "ERROR: Failure in signing callback: %d \r\n", xResult ) ); + lFinalResult = TLS_ERROR_SIGN; + } + + return lFinalResult; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Helper for reading the specified certificate object, if present, + * out of storage, into RAM, and then into an mbedTLS certificate context + * object. + * + * @param[in] pxTlsContext Caller TLS context. + * @param[in] pcLabelName PKCS #11 certificate object label. + * @param[in] xClass PKCS #11 certificate object class. + * @param[out] pxCertificateContext Certificate context. + * + * @return Zero on success. + */ +static int prvReadCertificateIntoContext( TLSContext_t * pxTlsContext, + char * pcLabelName, + CK_OBJECT_CLASS xClass, + mbedtls_x509_crt * pxCertificateContext ) +{ + BaseType_t xResult = CKR_OK; + CK_ATTRIBUTE xTemplate = { 0 }; + CK_OBJECT_HANDLE xCertObj = 0; + + /* Get the handle of the certificate. */ + xResult = xFindObjectWithLabelAndClass( pxTlsContext->xP11Session, + pcLabelName, + strlen( pcLabelName ), + xClass, + &xCertObj ); + + if( ( CKR_OK == xResult ) && ( xCertObj == CK_INVALID_HANDLE ) ) + { + xResult = CKR_OBJECT_HANDLE_INVALID; + } + + /* Query the certificate size. */ + if( 0 == xResult ) + { + xTemplate.type = CKA_VALUE; + xTemplate.ulValueLen = 0; + xTemplate.pValue = NULL; + xResult = ( BaseType_t ) pxTlsContext->pxP11FunctionList->C_GetAttributeValue( pxTlsContext->xP11Session, + xCertObj, + &xTemplate, + 1 ); + } + + /* Create a buffer for the certificate. */ + if( 0 == xResult ) + { + xTemplate.pValue = pvPortMalloc( xTemplate.ulValueLen ); /*lint !e9079 Allow casting void* to other types. */ + + if( NULL == xTemplate.pValue ) + { + xResult = ( BaseType_t ) CKR_HOST_MEMORY; + } + } + + /* Export the certificate. */ + if( 0 == xResult ) + { + xResult = ( BaseType_t ) pxTlsContext->pxP11FunctionList->C_GetAttributeValue( pxTlsContext->xP11Session, + xCertObj, + &xTemplate, + 1 ); + } + + /* Decode the certificate. */ + if( 0 == xResult ) + { + xResult = mbedtls_x509_crt_parse( pxCertificateContext, + ( const unsigned char * ) xTemplate.pValue, + xTemplate.ulValueLen ); + } + + /* Free memory. */ + if( NULL != xTemplate.pValue ) + { + vPortFree( xTemplate.pValue ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Helper for setting up potentially hardware-based cryptographic context + * for the client TLS certificate and private key. + * + * @param Caller context. + * + * @return Zero on success. + */ +static int prvInitializeClientCredential( TLSContext_t * pxCtx ) +{ + BaseType_t xResult = CKR_OK; + CK_ATTRIBUTE xTemplate[ 2 ]; + mbedtls_pk_type_t xKeyAlgo = ( mbedtls_pk_type_t ) ~0; + char * pcJitrCertificate = keyJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM; + + /* Initialize the mbed contexts. */ + mbedtls_x509_crt_init( &pxCtx->xMbedX509Cli ); + + if( pxCtx->xP11Session == CK_INVALID_HANDLE ) + { + xResult = CKR_SESSION_HANDLE_INVALID; + TLS_PRINT( ( "Error: PKCS #11 session was not initialized.\r\n" ) ); + } + + /* Put the module in authenticated mode. */ + if( CKR_OK == xResult ) + { + pxCtx->xTLSHandshakeState = TLS_HANDSHAKE_STARTED; + xResult = ( BaseType_t ) pxCtx->pxP11FunctionList->C_Login( pxCtx->xP11Session, + CKU_USER, + ( CK_UTF8CHAR_PTR ) configPKCS11_DEFAULT_USER_PIN, + sizeof( configPKCS11_DEFAULT_USER_PIN ) - 1 ); + } + + if( CKR_OK == xResult ) + { + /* Get the handle of the device private key. */ + xResult = xFindObjectWithLabelAndClass( pxCtx->xP11Session, + pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS, + sizeof( pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) - 1, + CKO_PRIVATE_KEY, + &pxCtx->xP11PrivateKey ); + } + + if( ( CKR_OK == xResult ) && ( pxCtx->xP11PrivateKey == CK_INVALID_HANDLE ) ) + { + xResult = TLS_ERROR_NO_PRIVATE_KEY; + TLS_PRINT( ( "ERROR: Private key not found. " ) ); + } + + /* Query the device private key type. */ + if( xResult == CKR_OK ) + { + xTemplate[ 0 ].type = CKA_KEY_TYPE; + xTemplate[ 0 ].pValue = &pxCtx->xKeyType; + xTemplate[ 0 ].ulValueLen = sizeof( CK_KEY_TYPE ); + xResult = pxCtx->pxP11FunctionList->C_GetAttributeValue( pxCtx->xP11Session, + pxCtx->xP11PrivateKey, + xTemplate, + 1 ); + } + + /* Map the PKCS #11 key type to an mbedTLS algorithm. */ + if( xResult == CKR_OK ) + { + switch( pxCtx->xKeyType ) + { + case CKK_RSA: + xKeyAlgo = MBEDTLS_PK_RSA; + break; + + case CKK_EC: + xKeyAlgo = MBEDTLS_PK_ECKEY; + break; + + default: + xResult = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + } + + /* Map the mbedTLS algorithm to its internal metadata. */ + if( xResult == CKR_OK ) + { + memcpy( &pxCtx->xMbedPkInfo, mbedtls_pk_info_from_type( xKeyAlgo ), sizeof( mbedtls_pk_info_t ) ); + + pxCtx->xMbedPkInfo.sign_func = prvPrivateKeySigningCallback; + pxCtx->xMbedPkCtx.pk_info = &pxCtx->xMbedPkInfo; + pxCtx->xMbedPkCtx.pk_ctx = pxCtx; + } + + /* Get the handle of the device client certificate. */ + if( xResult == CKR_OK ) + { + xResult = prvReadCertificateIntoContext( pxCtx, + pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS, + CKO_CERTIFICATE, + &pxCtx->xMbedX509Cli ); + } + + /* Add a Just-in-Time Registration (JITR) device issuer certificate, if + * present, to the TLS context handle. */ + if( xResult == CKR_OK ) + { + /* Prioritize a statically defined certificate over one in storage. */ + if( ( NULL != pcJitrCertificate ) && + ( 0 != strcmp( "", pcJitrCertificate ) ) ) + { + xResult = mbedtls_x509_crt_parse( &pxCtx->xMbedX509Cli, + ( const unsigned char * ) pcJitrCertificate, + 1 + strlen( pcJitrCertificate ) ); + } + else + { + /* Check for a device JITR certificate in storage. */ + xResult = prvReadCertificateIntoContext( pxCtx, + pkcs11configLABEL_JITP_CERTIFICATE, + CKO_CERTIFICATE, + &pxCtx->xMbedX509Cli ); + + /* It is optional to have a JITR certificate in storage. */ + if( CKR_OBJECT_HANDLE_INVALID == xResult ) + { + xResult = CKR_OK; + } + } + } + + /* Attach the client certificate(s) and private key to the TLS configuration. */ + if( 0 == xResult ) + { + xResult = mbedtls_ssl_conf_own_cert( &pxCtx->xMbedSslConfig, + &pxCtx->xMbedX509Cli, + &pxCtx->xMbedPkCtx ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Helper to seed the entropy module used by the DRBG. Periodically this + * this function will be called to get more random data from the TRNG. + * + * @param[in] tlsContext The TLS context. + * @param[out] outputBuffer The output buffer to return the generated random data. + * @param[in] outputBufferLength Length of the output buffer. + * + * @return Zero on success, otherwise a negative error code telling the cause of the error. + */ +static int prvEntropyCallback( void * tlsContext, + unsigned char * outputBuffer, + size_t outputBufferLength ) +{ + int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + CK_RV xResult = CKR_OK; + TLSContext_t * pxCtx = ( TLSContext_t * ) tlsContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + + if( pxCtx->xP11Session != CK_INVALID_HANDLE ) + { + xResult = C_GenerateRandom( pxCtx->xP11Session, + outputBuffer, + outputBufferLength ); + } + else + { + xResult = CKR_SESSION_HANDLE_INVALID; + TLS_PRINT( ( "Error: PKCS #11 session was not initialized.\r\n" ) ); + } + + if( xResult == CKR_OK ) + { + ret = 0; + } + else + { + TLS_PRINT( ( "Error: PKCS #11 C_GenerateRandom failed with error code:" \ + "%d\r\n", xResult ) ); + } + + return ret; +} + +/* + * Interface routines. + */ + +BaseType_t TLS_Init( void ** ppvContext, + TLSParams_t * pxParams ) +{ + BaseType_t xResult = CKR_OK; + int mbedTLSResult = 0; + TLSContext_t * pxCtx = NULL; + CK_C_GetFunctionList xCkGetFunctionList = NULL; + + /* Allocate an internal context. */ + pxCtx = ( TLSContext_t * ) pvPortMalloc( sizeof( TLSContext_t ) ); /*lint !e9087 !e9079 Allow casting void* to other types. */ + + if( NULL != pxCtx ) + { + memset( pxCtx, 0, sizeof( TLSContext_t ) ); + *ppvContext = pxCtx; + + /* Initialize the context. */ + pxCtx->pcDestination = pxParams->pcDestination; + pxCtx->pcServerCertificate = pxParams->pcServerCertificate; + pxCtx->ulServerCertificateLength = pxParams->ulServerCertificateLength; + pxCtx->ppcAlpnProtocols = pxParams->ppcAlpnProtocols; + pxCtx->ulAlpnProtocolsCount = pxParams->ulAlpnProtocolsCount; + pxCtx->xNetworkRecv = pxParams->pxNetworkRecv; + pxCtx->xNetworkSend = pxParams->pxNetworkSend; + pxCtx->pvCallerContext = pxParams->pvCallerContext; + + /* Get the function pointer list for the PKCS#11 module. */ + xCkGetFunctionList = C_GetFunctionList; + xResult = ( BaseType_t ) xCkGetFunctionList( &pxCtx->pxP11FunctionList ); + + /* Ensure that the PKCS #11 module is initialized and create a session. */ + if( xResult == CKR_OK ) + { + xResult = xInitializePkcs11Session( &pxCtx->xP11Session ); + + /* It is ok if the module was previously initialized. */ + if( xResult == CKR_CRYPTOKI_ALREADY_INITIALIZED ) + { + xResult = CKR_OK; + } + } + + if( xResult == CKR_OK ) + { + mbedtls_ctr_drbg_init( &pxCtx->xMbedDrbgCtx ); + mbedTLSResult = mbedtls_ctr_drbg_seed( &pxCtx->xMbedDrbgCtx, + prvEntropyCallback, + pxCtx, + NULL, + 0 ); + + if( 0 != mbedTLSResult ) + { + TLS_PRINT( ( "ERROR: Failed to setup DRBG seed %s : %s \r\n", + mbedtlsHighLevelCodeOrDefault( mbedTLSResult ), + mbedtlsLowLevelCodeOrDefault( mbedTLSResult ) ) ); + xResult = CKR_FUNCTION_FAILED; + } + } + } + else + { + xResult = ( BaseType_t ) CKR_HOST_MEMORY; + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +#ifdef MBEDTLS_DEBUG_C + static void prvTlsDebugPrint( void * ctx, + int lLevel, + const char * pcFile, + int lLine, + const char * pcStr ) + { + /* Unused parameters. */ + ( void ) ctx; + ( void ) pcFile; + ( void ) lLine; + + /* Send the debug string to the portable logger. */ + vLoggingPrintf( "mbedTLS: |%d| %s", lLevel, pcStr ); + } +#endif /* ifdef MBEDTLS_DEBUG_C */ + +/*-----------------------------------------------------------*/ + +BaseType_t TLS_Connect( void * pvContext ) +{ + BaseType_t xResult = 0; + CK_RV xPKCSResult = CKR_OK; + TLSContext_t * pxCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + + /* Initialize mbedTLS structures. */ + mbedtls_ssl_init( &pxCtx->xMbedSslCtx ); + mbedtls_ssl_config_init( &pxCtx->xMbedSslConfig ); + mbedtls_x509_crt_init( &pxCtx->xMbedX509CA ); + + /* Decode the root certificate: either the default or the override. */ + if( NULL != pxCtx->pcServerCertificate ) + { + xResult = mbedtls_x509_crt_parse( &pxCtx->xMbedX509CA, + ( const unsigned char * ) pxCtx->pcServerCertificate, + pxCtx->ulServerCertificateLength ); + + if( 0 != xResult ) + { + TLS_PRINT( ( "ERROR: Failed to parse custom server certificates %s : %s \r\n", + mbedtlsHighLevelCodeOrDefault( xResult ), + mbedtlsLowLevelCodeOrDefault( xResult ) ) ); + } + } + else + { + xResult = mbedtls_x509_crt_parse( &pxCtx->xMbedX509CA, + ( const unsigned char * ) tlsVERISIGN_ROOT_CERTIFICATE_PEM, + tlsVERISIGN_ROOT_CERTIFICATE_LENGTH ); + + if( 0 == xResult ) + { + xResult = mbedtls_x509_crt_parse( &pxCtx->xMbedX509CA, + ( const unsigned char * ) tlsATS1_ROOT_CERTIFICATE_PEM, + tlsATS1_ROOT_CERTIFICATE_LENGTH ); + + if( 0 == xResult ) + { + xResult = mbedtls_x509_crt_parse( &pxCtx->xMbedX509CA, + ( const unsigned char * ) tlsATS3_ROOT_CERTIFICATE_PEM, + tlsATS3_ROOT_CERTIFICATE_LENGTH ); + + if( 0 == xResult ) + { + xResult = mbedtls_x509_crt_parse( &pxCtx->xMbedX509CA, + ( const unsigned char * ) tlsSTARFIELD_ROOT_CERTIFICATE_PEM, + tlsSTARFIELD_ROOT_CERTIFICATE_LENGTH ); + } + } + } + + if( 0 != xResult ) + { + /* Default root certificates should be in aws_default_root_certificate.h */ + TLS_PRINT( ( "ERROR: Failed to parse default server certificates %s : %s \r\n", + mbedtlsHighLevelCodeOrDefault( xResult ), + mbedtlsLowLevelCodeOrDefault( xResult ) ) ); + } + } + + /* Start with protocol defaults. */ + if( 0 == xResult ) + { + xResult = mbedtls_ssl_config_defaults( &pxCtx->xMbedSslConfig, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ); + + if( 0 != xResult ) + { + TLS_PRINT( ( "ERROR: Failed to set ssl config defaults %s : %s \r\n", + mbedtlsHighLevelCodeOrDefault( xResult ), + mbedtlsLowLevelCodeOrDefault( xResult ) ) ); + } + } + + if( 0 == xResult ) + { + /* Use a callback for additional server certificate validation. */ + mbedtls_ssl_conf_verify( &pxCtx->xMbedSslConfig, + &prvCheckCertificate, + pxCtx ); + + /* Server certificate validation is mandatory. */ + mbedtls_ssl_conf_authmode( &pxCtx->xMbedSslConfig, MBEDTLS_SSL_VERIFY_REQUIRED ); + + /* Set the RNG callback. */ + mbedtls_ssl_conf_rng( &pxCtx->xMbedSslConfig, &prvGenerateRandomBytes, pxCtx ); /*lint !e546 Nothing wrong here. */ + + /* Set issuer certificate. */ + mbedtls_ssl_conf_ca_chain( &pxCtx->xMbedSslConfig, &pxCtx->xMbedX509CA, NULL ); + + /* Configure the SSL context to contain device credentials (eg device cert + * and private key) obtained from the PKCS #11 layer. The result of + * loading device key and certificate is placed in a separate variable + * (xPKCSResult instead of xResult). The reason is that we want to + * attempt TLS handshake, even if the device key and certificate + * are not loaded. This allows the TLS layer to still connect to servers + * that do not require mutual authentication. If the server does + * require mutual authentication, the handshake will fail. */ + xPKCSResult = prvInitializeClientCredential( pxCtx ); + } + + if( ( 0 == xResult ) && ( NULL != pxCtx->ppcAlpnProtocols ) ) + { + /* Include an application protocol list in the TLS ClientHello + * message. */ + xResult = mbedtls_ssl_conf_alpn_protocols( + &pxCtx->xMbedSslConfig, + pxCtx->ppcAlpnProtocols ); + } + + #ifdef MBEDTLS_DEBUG_C + + /* If mbedTLS is being compiled with debug support, assume that the + * runtime configuration should use verbose output. */ + mbedtls_ssl_conf_dbg( &pxCtx->xMbedSslConfig, prvTlsDebugPrint, NULL ); + mbedtls_debug_set_threshold( tlsDEBUG_VERBOSE ); + #endif + + if( 0 == xResult ) + { + /* Set the resulting protocol configuration. */ + xResult = mbedtls_ssl_setup( &pxCtx->xMbedSslCtx, &pxCtx->xMbedSslConfig ); + } + + #ifdef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + if( 0 == xResult ) + { + /* Enable the max fragment extension. 4096 bytes is currently the largest fragment size permitted. + * See RFC 8449 https://tools.ietf.org/html/rfc8449 for more information. + * + * Smaller values can be found in "mbedtls/include/ssl.h". + */ + xResult = mbedtls_ssl_conf_max_frag_len( &pxCtx->xMbedSslConfig, MBEDTLS_SSL_MAX_FRAG_LEN_4096 ); + } + #endif + + /* Set the hostname, if requested. */ + if( ( 0 == xResult ) && ( NULL != pxCtx->pcDestination ) ) + { + xResult = mbedtls_ssl_set_hostname( &pxCtx->xMbedSslCtx, pxCtx->pcDestination ); + } + + /* Set the socket callbacks. */ + if( 0 == xResult ) + { + mbedtls_ssl_set_bio( &pxCtx->xMbedSslCtx, + pxCtx, + prvNetworkSend, + prvNetworkRecv, + NULL ); + + /* Negotiate. */ + while( 0 != ( xResult = mbedtls_ssl_handshake( &pxCtx->xMbedSslCtx ) ) ) + { + if( ( MBEDTLS_ERR_SSL_WANT_READ != xResult ) && + ( MBEDTLS_ERR_SSL_WANT_WRITE != xResult ) ) + { + /* There was an unexpected error. Per mbedTLS API documentation, + * ensure that upstream clean-up code doesn't accidentally use + * a context that failed the handshake. */ + prvFreeContext( pxCtx ); + + if( xPKCSResult != CKR_OK ) + { + TLS_PRINT( ( "ERROR: The handshake failed and it is likely " + "due to a failure in PKCS #11. Consider enabling " + "error logging in PKCS #11 or checking if your device " + "is properly provisioned with client credentials. " + "PKCS #11 error=0x(%0X). TLS handshake error=%s : %s \r\n", + xPKCSResult, + mbedtlsHighLevelCodeOrDefault( xResult ), + mbedtlsLowLevelCodeOrDefault( xResult ) ) ); + } + else + { + TLS_PRINT( ( "ERROR: TLS handshake failed trying to connect. %s : %s \r\n", + mbedtlsHighLevelCodeOrDefault( xResult ), + mbedtlsLowLevelCodeOrDefault( xResult ) ) ); + } + + break; + } + } + } + + /* Keep track of successful completion of the handshake. */ + if( 0 == xResult ) + { + pxCtx->xTLSHandshakeState = TLS_HANDSHAKE_SUCCESSFUL; + } + else if( xResult > 0 ) + { + TLS_PRINT( ( "ERROR: TLS_Connect failed with error code %d \r\n", xResult ) ); + /* Convert PKCS #11 failures to a negative error code. */ + xResult = TLS_ERROR_HANDSHAKE_FAILED; + } + + /* Free up allocated memory. */ + mbedtls_x509_crt_free( &pxCtx->xMbedX509CA ); + mbedtls_x509_crt_free( &pxCtx->xMbedX509Cli ); + + return xResult; +} + +/*-----------------------------------------------------------*/ + +BaseType_t TLS_Recv( void * pvContext, + unsigned char * pucReadBuffer, + size_t xReadLength ) +{ + BaseType_t xResult = 0; + TLSContext_t * pxCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + size_t xRead = 0; + + if( ( NULL != pxCtx ) && ( TLS_HANDSHAKE_SUCCESSFUL == pxCtx->xTLSHandshakeState ) ) + { + /* This routine will return however many bytes are returned from from mbedtls_ssl_read + * immediately unless MBEDTLS_ERR_SSL_WANT_READ is returned, in which case we try again. */ + do + { + xResult = mbedtls_ssl_read( &pxCtx->xMbedSslCtx, + pucReadBuffer + xRead, + xReadLength - xRead ); + + if( xResult > 0 ) + { + /* Got data, so update the tally and keep looping. */ + xRead += ( size_t ) xResult; + } + + /* If xResult == 0, then no data was received (and there is no error). + * The secure sockets API supports non-blocking read, so stop the loop, + * but don't flag an error. */ + } while( ( xResult == MBEDTLS_ERR_SSL_WANT_READ ) ); + } + else + { + xResult = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if( xResult >= 0 ) + { + xResult = ( BaseType_t ) xRead; + } + else + { + /* xResult < 0 is a hard error, so invalidate the context and stop. */ + prvFreeContext( pxCtx ); + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +BaseType_t TLS_Send( void * pvContext, + const unsigned char * pucMsg, + size_t xMsgLength ) +{ + BaseType_t xResult = 0; + TLSContext_t * pxCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + size_t xWritten = 0; + + if( ( NULL != pxCtx ) && ( TLS_HANDSHAKE_SUCCESSFUL == pxCtx->xTLSHandshakeState ) ) + { + while( xWritten < xMsgLength ) + { + xResult = mbedtls_ssl_write( &pxCtx->xMbedSslCtx, + pucMsg + xWritten, + xMsgLength - xWritten ); + + if( 0 < xResult ) + { + /* Sent data, so update the tally and keep looping. */ + xWritten += ( size_t ) xResult; + } + else if( ( 0 == xResult ) || ( -pdFREERTOS_ERRNO_ENOSPC == xResult ) ) + { + /* No data sent. The secure sockets + * API supports non-blocking send, so stop the loop but don't + * flag an error. */ + xResult = 0; + break; + } + else if( MBEDTLS_ERR_SSL_WANT_WRITE != xResult ) + { + /* Hard error: invalidate the context and stop. */ + prvFreeContext( pxCtx ); + break; + } + } + } + else + { + xResult = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if( 0 <= xResult ) + { + xResult = ( BaseType_t ) xWritten; + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +void TLS_Cleanup( void * pvContext ) +{ + TLSContext_t * pxCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */ + + if( NULL != pxCtx ) + { + prvFreeContext( pxCtx ); + + /* Free memory. */ + vPortFree( pxCtx ); + } +} + +/*-----------------------------------------------------------*/ + +void TLS_setDateIsInThePastFunction( DateIsInThePast_t DateIsInThePast ) +{ + pDateIsInThePast = DateIsInThePast; +} diff --git a/bsp/aws_libraries/logging/include/iot_logging_task.h b/bsp/aws_libraries/logging/include/iot_logging_task.h new file mode 100644 index 0000000..be8e05d --- /dev/null +++ b/bsp/aws_libraries/logging/include/iot_logging_task.h @@ -0,0 +1,134 @@ +/* + * FreeRTOS Common V1.1.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_logging_task.h + * @brief Logging task interface. + */ + +#ifndef AWS_LOGGING_TASK_H +#define AWS_LOGGING_TASK_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include iot_logging_task.h" +#endif + +/** + * @brief Initialization function for logging task. + * + * Called once to create the logging task and queue. Must be called before any + * calls to vLoggingPrintf(). + */ +BaseType_t xLoggingTaskInitialize( uint16_t usStackSize, + UBaseType_t uxPriority, + UBaseType_t uxQueueLength ); + +/** + * @brief Interface to print via the logging interface. + * + * Uses the same semantics as printf(). How the print is performed depends on + * which files are being built. Some vLoggingPrintf() implementations will + * output directly, others will use a logging task to allow log message to be + * output in the background should the output device be too slow for output to + * be performed inline. + * + * @param[in] pcFormat The format string of the log message. + * @param[in] ... The variadic list of parameters for the format + * specifiers in the @p pcFormat. + */ +void vLoggingPrintf( const char * pcFormat, + ... ); + +/** + * @brief Same as vLoggingPrintf but additionally takes parameters + * of source file location of log to add as metadata in message. + * + * @param[in] pcFile The file name or file path containing the log + * message. If a file path is passed, only the filename is added to + * the log message. + * @param[in] fileLineNo The line number in the @p pcFile containing + * the message being logged. + * @param[in] pcFormat The format string of the log message. + * @param[in] ... The variadic list of parameters for the format + * specifiers in the @p pcFormat. + */ +void vLoggingPrintfWithFileAndLine( const char * pcFile, + size_t fileLineNo, + const char * pcFormat, + ... ); + +/** + * @brief Interface for logging message at Error level. + * + * This function adds a "[ERROR]" prefix to the + * log message to label it as an error. + * + * @param[in] pcFormat The format string of the log message. + * @param[in] ... The variadic list of parameters for the format + * specifiers in the @p pcFormat. + */ +void vLoggingPrintfError( const char * pcFormat, + ... ); + +/** + * @brief Interface for logging message at Warn level. + * + * This function adds a "[WARN]" prefix to the + * log message to label it as a warning. + * + * @param[in] pcFormat The format string of the log message. + * @param[in] ... The variadic list of parameters for the format + * specifiers in the @p pcFormat. + */ +void vLoggingPrintfWarn( const char * pcFormat, + ... ); + +/** + * @brief Interface for logging message at Info level. + * + * This function adds a "[INFO]" prefix to the + * log message to label it as an informational message. + * + * @param[in] pcFormat The format string of the log message. + * @param[in] ... The variadic list of parameters for the format + * specifiers in the @p pcFormat. + */ +void vLoggingPrintfInfo( const char * pcFormat, + ... ); + +/** + * @brief Interface for logging message at Debug level. + * + * This function adds a "[DEBUG]" prefix to the + * log message to label it as a debug level message. + * + * @param[in] pcFormat The format string of the log message. + * @param[in] ... The variadic list of parameters for the format + * specifiers in the @p pcFormat. + */ +void vLoggingPrintfDebug( const char * pcFormat, + ... ); + +#endif /* AWS_LOGGING_TASK_H */ diff --git a/bsp/aws_libraries/logging/include/logging_levels.h b/bsp/aws_libraries/logging/include/logging_levels.h new file mode 100644 index 0000000..f3f4f64 --- /dev/null +++ b/bsp/aws_libraries/logging/include/logging_levels.h @@ -0,0 +1,109 @@ +/* + * FreeRTOS Common V1.1.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file logging_levels.h + * @brief Defines the logging level macros. + */ + +#ifndef LOGGING_LEVELS_H_ +#define LOGGING_LEVELS_H_ + +/** + * @constantspage{logging,logging library} + * + * @section logging_constants_levels Log levels + * @brief Log levels for the libraries in this SDK. + * + * Each library should specify a log level by setting @ref LIBRARY_LOG_LEVEL. + * All log messages with a level at or below the specified level will be printed + * for that library. + * + * Currently, there are 4 log levels. In the order of lowest to highest, they are: + * - #LOG_NONE
+ * @copybrief LOG_NONE + * - #LOG_ERROR
+ * @copybrief LOG_ERROR + * - #LOG_WARN
+ * @copybrief LOG_WARN + * - #LOG_INFO
+ * @copybrief LOG_INFO + * - #LOG_DEBUG
+ * @copybrief LOG_DEBUG + */ + +/** + * @brief No log messages. + * + * When @ref LIBRARY_LOG_LEVEL is #LOG_NONE, logging is disabled and no + * logging messages are printed. + */ +#define LOG_NONE 0 + +/** + * @brief Represents erroneous application state or event. + * + * These messages describe the situations when a library encounters an error from + * which it cannot recover. + * + * These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either + * of #LOG_ERROR, #LOG_WARN, #LOG_INFO or #LOG_DEBUG. + */ +#define LOG_ERROR 1 + +/** + * @brief Message about an abnormal event. + * + * These messages describe the situations when a library encounters + * abnormal event that may be indicative of an error. Libraries continue + * execution after logging a warning. + * + * These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either + * of #LOG_WARN, #LOG_INFO or #LOG_DEBUG. + */ +#define LOG_WARN 2 + +/** + * @brief A helpful, informational message. + * + * These messages describe normal execution of a library. They provide + * the progress of the program at a coarse-grained level. + * + * These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either + * of #LOG_INFO or #LOG_DEBUG. + */ +#define LOG_INFO 3 + +/** + * @brief Detailed and excessive debug information. + * + * Debug log messages are used to provide the + * progress of the program at a fine-grained level. These are mostly used + * for debugging and may contain excessive information such as internal + * variables, buffers, or other specific information. + * + * These messages are only printed when @ref LIBRARY_LOG_LEVEL is defined as + * #LOG_DEBUG. + */ +#define LOG_DEBUG 4 + +#endif /* ifndef LOGGING_LEVELS_H_ */ diff --git a/bsp/aws_libraries/logging/include/logging_stack.h b/bsp/aws_libraries/logging/include/logging_stack.h new file mode 100644 index 0000000..7235600 --- /dev/null +++ b/bsp/aws_libraries/logging/include/logging_stack.h @@ -0,0 +1,121 @@ +/* + * FreeRTOS Common V1.1.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file logging_stack.h + * @brief Reference implementation of Logging stack as a header-only library. + */ + +#ifndef LOGGING_STACK_H_ +#define LOGGING_STACK_H_ + +/* Include header for logging level macros. */ +#include "logging_levels.h" + +/* FreeRTOS Include. */ +#include "FreeRTOS.h" +#include "iot_logging_task.h" + +/* Standard Include. */ +#include + +/** + * @brief This config enables extra verbosity in log messages with metadata information + * about the source library and location of the log message. + * This requires that the toolchain support C99 (for variadic macros) and the GNU + * extension for comma elision in variadic macros (with ##__VA_ARGS__). + * If this flag is enabled, you can change the metadata information from the logging_stack.h + * file. + * + * @note By default, this configuration is disabled by + */ +#ifndef LOGGING_ENABLE_METADATA_WITH_C99_AND_GNU_EXTENSION + #define LOGGING_ENABLE_METADATA_WITH_C99_AND_GNU_EXTENSION 0 +#endif + +#if LOGGING_ENABLE_METADATA_WITH_C99_AND_GNU_EXTENSION == 1 + + #define SdkLogError( message ) SdkLogErrorC99 message + #define SdkLogErrorC99( format, ... ) vLoggingPrintfWithFileAndLine( __FILE__, __LINE__, "[ERROR] [%s] " format "\r\n", LIBRARY_LOG_NAME, ## __VA_ARGS__ ) + #define SdkLogWarn( message ) SdkLogWarnC99 message + #define SdkLogWarnC99( format, ... ) vLoggingPrintfWithFileAndLine( __FILE__, __LINE__, "[WARN] [%s] " format "\r\n", LIBRARY_LOG_NAME, ## __VA_ARGS__ ) + #define SdkLogInfo( message ) SdkLogInfoC99 message + #define SdkLogInfoC99( format, ... ) vLoggingPrintfWithFileAndLine( __FILE__, __LINE__, "[INFO] [%s] " format "\r\n", LIBRARY_LOG_NAME, ## __VA_ARGS__ ) + #define SdkLogDebug( message ) SdkLogDebugC99 message + #define SdkLogDebugC99( format, ... ) vLoggingPrintfWithFileAndLine( __FILE__, __LINE__, "[DEBUG] [%s] " format "\r\n", LIBRARY_LOG_NAME, ## __VA_ARGS__ ) +#else /* if LOGGING_ENABLE_METADATA_WITH_C99_AND_GNU_EXTENSION == 1 */ + #define SdkLogError( message ) vLoggingPrintfError message + #define SdkLogWarn( message ) vLoggingPrintfWarn message + #define SdkLogInfo( message ) vLoggingPrintfInfo message + #define SdkLogDebug( message ) vLoggingPrintfDebug message +#endif /* if defined( LOGGING_METADATA_WITH_C99_SUPPORT ) && ( LOGGING_METADATA_WITH_C99_SUPPORT == 1 ) */ + +/* Check that LIBRARY_LOG_LEVEL is defined and has a valid value. */ +#if !defined( LIBRARY_LOG_LEVEL ) || \ + ( ( LIBRARY_LOG_LEVEL != LOG_NONE ) && \ + ( LIBRARY_LOG_LEVEL != LOG_ERROR ) && \ + ( LIBRARY_LOG_LEVEL != LOG_WARN ) && \ + ( LIBRARY_LOG_LEVEL != LOG_INFO ) && \ + ( LIBRARY_LOG_LEVEL != LOG_DEBUG ) ) + #error "Please define LIBRARY_LOG_LEVEL as either LOG_NONE, LOG_ERROR, LOG_WARN, LOG_INFO, or LOG_DEBUG." +#elif !defined( LIBRARY_LOG_NAME ) + #error "Please define LIBRARY_LOG_NAME for the library." +#else + #if LIBRARY_LOG_LEVEL == LOG_DEBUG + /* All log level messages will logged. */ + #define LogError( message ) SdkLogError( message ) + #define LogWarn( message ) SdkLogWarn( message ) + #define LogInfo( message ) SdkLogInfo( message ) + #define LogDebug( message ) SdkLogDebug( message ) + + #elif LIBRARY_LOG_LEVEL == LOG_INFO + /* Only INFO, WARNING and ERROR messages will be logged. */ + #define LogError( message ) SdkLogError( message ) + #define LogWarn( message ) SdkLogWarn( message ) + #define LogInfo( message ) SdkLogInfo( message ) + #define LogDebug( message ) + + #elif LIBRARY_LOG_LEVEL == LOG_WARN + /* Only WARNING and ERROR messages will be logged.*/ + #define LogError( message ) SdkLogError( message ) + #define LogWarn( message ) SdkLogWarn( message ) + #define LogInfo( message ) + #define LogDebug( message ) + + #elif LIBRARY_LOG_LEVEL == LOG_ERROR + /* Only ERROR messages will be logged. */ + #define LogError( message ) SdkLogError( message ) + #define LogWarn( message ) + #define LogInfo( message ) + #define LogDebug( message ) + + #else /* if LIBRARY_LOG_LEVEL == LOG_ERROR */ + + #define LogError( message ) + #define LogWarn( message ) + #define LogInfo( message ) + #define LogDebug( message ) + + #endif /* if LIBRARY_LOG_LEVEL == LOG_ERROR */ +#endif /* if !defined( LIBRARY_LOG_LEVEL ) || ( ( LIBRARY_LOG_LEVEL != LOG_NONE ) && ( LIBRARY_LOG_LEVEL != LOG_ERROR ) && ( LIBRARY_LOG_LEVEL != LOG_WARN ) && ( LIBRARY_LOG_LEVEL != LOG_INFO ) && ( LIBRARY_LOG_LEVEL != LOG_DEBUG ) ) */ + +#endif /* ifndef LOGGING_STACK_H_ */ diff --git a/bsp/aws_libraries/logging/iot_logging.c b/bsp/aws_libraries/logging/iot_logging.c new file mode 100644 index 0000000..139ea8e --- /dev/null +++ b/bsp/aws_libraries/logging/iot_logging.c @@ -0,0 +1,454 @@ +/* + * FreeRTOS Common V1.1.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file iot_logging.c + * @brief Implementation of logging functions from iot_logging.h + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include +#include +#include + +/* Platform clock include. */ +#include "platform/iot_clock.h" + +/* Logging includes. */ +#include "private/iot_logging.h" + +/*-----------------------------------------------------------*/ + +/* This implementation assumes the following values for the log level constants. + * Ensure that the values have not been modified. */ +#if IOT_LOG_NONE != 0 + #error "IOT_LOG_NONE must be 0." +#endif +#if IOT_LOG_ERROR != 1 + #error "IOT_LOG_ERROR must be 1." +#endif +#if IOT_LOG_WARN != 2 + #error "IOT_LOG_WARN must be 2." +#endif +#if IOT_LOG_INFO != 3 + #error "IOT_LOG_INFO must be 3." +#endif +#if IOT_LOG_DEBUG != 4 + #error "IOT_LOG_DEBUG must be 4." +#endif + +/** + * @def IotLogging_Puts( message ) + * @brief Function the logging library uses to print a line. + * + * This function can be set by using a define. By default, the standard library + * [puts](http://pubs.opengroup.org/onlinepubs/9699919799/functions/puts.html) + * function is used. + */ +#ifndef IotLogging_Puts + #define IotLogging_Puts puts +#endif + +/* + * Provide default values for undefined memory allocation functions based on + * the usage of dynamic memory allocation. + */ +#if IOT_STATIC_MEMORY_ONLY == 1 + /* Static memory allocation header. */ + #include "private/iot_static_memory.h" + +/** + * @brief Allocate a new logging buffer. This function must have the same + * signature as [malloc](http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html). + */ + #ifndef IotLogging_Malloc + #define IotLogging_Malloc Iot_MallocMessageBuffer + #endif + +/** + * @brief Free a logging buffer. This function must have the same signature + * as [free](http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html). + */ + #ifndef IotLogging_Free + #define IotLogging_Free Iot_FreeMessageBuffer + #endif + +/** + * @brief Get the size of a logging buffer. Statically-allocated buffers + * should all have the same size. + */ + #ifndef IotLogging_StaticBufferSize + #define IotLogging_StaticBufferSize Iot_MessageBufferSize + #endif +#else /* if IOT_STATIC_MEMORY_ONLY == 1 */ + #ifndef IotLogging_Malloc + #include + #define IotLogging_Malloc malloc + #endif + + #ifndef IotLogging_Free + #include + #define IotLogging_Free free + #endif +#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */ + +/** + * @brief A guess of the maximum length of a timestring. + * + * There's no way for this logging library to know the length of a timestring + * before it's generated. Therefore, the logging library will assume a maximum + * length of any timestring it may get. This value should be generous enough + * to accommodate the vast majority of timestrings. + * + * @see IotClock_GetTimestring + */ +#define MAX_TIMESTRING_LENGTH ( 64 ) + +/** + * @brief The longest string in #_pLogLevelStrings (below), plus 3 to accommodate + * `[]` and a null-terminator. + */ +#define MAX_LOG_LEVEL_LENGTH ( 8 ) + +/** + * @brief How many bytes @ref logging_function_genericprintbuffer should output on + * each line. + */ +#define BYTES_PER_LINE ( 16 ) + +/*-----------------------------------------------------------*/ + +/** + * @brief Lookup table for log levels. + * + * Converts one of the @ref logging_constants_levels to a string. + */ +static const char * const _pLogLevelStrings[ 5 ] = +{ + "", /* IOT_LOG_NONE */ + "ERROR", /* IOT_LOG_ERROR */ + "WARN ", /* IOT_LOG_WARN */ + "INFO ", /* IOT_LOG_INFO */ + "DEBUG" /* IOT_LOG_DEBUG */ +}; + +/*-----------------------------------------------------------*/ + +#if !defined( IOT_STATIC_MEMORY_ONLY ) || ( IOT_STATIC_MEMORY_ONLY == 0 ) + static bool _reallocLoggingBuffer( void ** pOldBuffer, + size_t newSize, + size_t oldSize ) + { + bool status = false; + + /* Allocate a new, larger buffer. */ + void * pNewBuffer = IotLogging_Malloc( newSize ); + + /* Ensure that memory allocation succeeded. */ + if( pNewBuffer != NULL ) + { + /* Copy the data from the old buffer to the new buffer. */ + ( void ) memcpy( pNewBuffer, *pOldBuffer, oldSize ); + + /* Free the old buffer and update the pointer. */ + IotLogging_Free( *pOldBuffer ); + *pOldBuffer = pNewBuffer; + + status = true; + } + + return status; + } +#endif /* if !defined( IOT_STATIC_MEMORY_ONLY ) || ( IOT_STATIC_MEMORY_ONLY == 0 ) */ + +/*-----------------------------------------------------------*/ + +void IotLog_Generic( int libraryLogSetting, + const char * const pLibraryName, + int messageLevel, + const IotLogConfig_t * const pLogConfig, + const char * const pFormat, + ... ) +{ + int requiredMessageSize = 0; + size_t bufferSize = 0, + bufferPosition = 0, timestringLength = 0; + char * pLoggingBuffer = NULL; + va_list args; + + /* If the library's log level setting is lower than the message level, + * return without doing anything. */ + if( ( messageLevel == 0 ) || ( messageLevel > libraryLogSetting ) ) + { + return; + } + + if( ( pLogConfig == NULL ) || ( pLogConfig->hideLogLevel == false ) ) + { + /* Add length of log level if requested. */ + bufferSize += MAX_LOG_LEVEL_LENGTH; + } + + /* Estimate the amount of buffer needed for this log message. */ + if( ( pLogConfig == NULL ) || ( pLogConfig->hideLibraryName == false ) ) + { + /* Add size of library name if requested. Add 2 to accommodate "[]". */ + bufferSize += strlen( pLibraryName ) + 2; + } + + if( ( pLogConfig == NULL ) || ( pLogConfig->hideTimestring == false ) ) + { + /* Add length of timestring if requested. */ + bufferSize += MAX_TIMESTRING_LENGTH; + } + + /* Add 64 as an initial (arbitrary) guess for the length of the message. */ + bufferSize += 64; + + /* In static memory mode, check that the log message will fit in the a + * static buffer. */ + #if IOT_STATIC_MEMORY_ONLY == 1 + if( bufferSize >= IotLogging_StaticBufferSize() ) + { + /* If the static buffers are likely too small to fit the log message, + * return. */ + return; + } + + /* Otherwise, update the buffer size to the size of a static buffer. */ + bufferSize = IotLogging_StaticBufferSize(); + #endif + + /* Allocate memory for the logging buffer. */ + pLoggingBuffer = ( char * ) IotLogging_Malloc( bufferSize ); + + if( pLoggingBuffer == NULL ) + { + return; + } + + /* Print the message log level if requested. */ + if( ( pLogConfig == NULL ) || ( pLogConfig->hideLogLevel == false ) ) + { + /* Ensure that message level is valid. */ + if( ( messageLevel >= IOT_LOG_NONE ) && ( messageLevel <= IOT_LOG_DEBUG ) ) + { + /* Add the log level string to the logging buffer. */ + requiredMessageSize = snprintf( pLoggingBuffer + bufferPosition, + bufferSize - bufferPosition, + "[%s]", + _pLogLevelStrings[ messageLevel ] ); + + /* Check for encoding errors. */ + if( requiredMessageSize <= 0 ) + { + IotLogging_Free( pLoggingBuffer ); + + return; + } + + /* Update the buffer position. */ + bufferPosition += ( size_t ) requiredMessageSize; + } + } + + /* Print the library name if requested. */ + if( ( pLogConfig == NULL ) || ( pLogConfig->hideLibraryName == false ) ) + { + /* Add the library name to the logging buffer. */ + requiredMessageSize = snprintf( pLoggingBuffer + bufferPosition, + bufferSize - bufferPosition, + "[%s]", + pLibraryName ); + + /* Check for encoding errors. */ + if( requiredMessageSize <= 0 ) + { + IotLogging_Free( pLoggingBuffer ); + + return; + } + + /* Update the buffer position. */ + bufferPosition += ( size_t ) requiredMessageSize; + } + + /* Print the timestring if requested. */ + if( ( pLogConfig == NULL ) || ( pLogConfig->hideTimestring == false ) ) + { + /* Add the opening '[' enclosing the timestring. */ + pLoggingBuffer[ bufferPosition ] = '['; + bufferPosition++; + + /* Generate the timestring and add it to the buffer. */ + if( IotClock_GetTimestring( pLoggingBuffer + bufferPosition, + bufferSize - bufferPosition, + ×tringLength ) == true ) + { + /* If the timestring was successfully generated, add the closing "]". */ + bufferPosition += timestringLength; + pLoggingBuffer[ bufferPosition ] = ']'; + bufferPosition++; + } + else + { + /* Sufficient memory for a timestring should have been allocated. A timestring + * probably failed to generate due to a clock read error; remove the opening '[' + * from the logging buffer. */ + bufferPosition--; + pLoggingBuffer[ bufferPosition ] = '\0'; + } + } + + /* Add a padding space between the last closing ']' and the message, unless + * the logging buffer is empty. */ + if( bufferPosition > 0 ) + { + pLoggingBuffer[ bufferPosition ] = ' '; + bufferPosition++; + } + + va_start( args, pFormat ); + + /* Add the log message to the logging buffer. */ + requiredMessageSize = vsnprintf( pLoggingBuffer + bufferPosition, + bufferSize - bufferPosition, + pFormat, + args ); + + va_end( args ); + + /* If the logging buffer was too small to fit the log message, reallocate + * a larger logging buffer. */ + if( ( size_t ) requiredMessageSize >= bufferSize - bufferPosition ) + { + #if IOT_STATIC_MEMORY_ONLY == 1 + + /* There's no point trying to allocate a larger static buffer. Return + * immediately. */ + IotLogging_Free( pLoggingBuffer ); + + return; + #else + if( _reallocLoggingBuffer( ( void ** ) &pLoggingBuffer, + ( size_t ) requiredMessageSize + bufferPosition + 1, + bufferSize ) == false ) + { + /* If buffer reallocation failed, return. */ + IotLogging_Free( pLoggingBuffer ); + + return; + } + + /* Reallocation successful, update buffer size. */ + bufferSize = ( size_t ) requiredMessageSize + bufferPosition + 1; + + /* Add the log message to the buffer. Now that the buffer has been + * reallocated, this should succeed. */ + va_start( args, pFormat ); + requiredMessageSize = vsnprintf( pLoggingBuffer + bufferPosition, + bufferSize - bufferPosition, + pFormat, + args ); + va_end( args ); + #endif /* if IOT_STATIC_MEMORY_ONLY == 1 */ + } + + /* Check for encoding errors. */ + if( requiredMessageSize <= 0 ) + { + IotLogging_Free( pLoggingBuffer ); + + return; + } + + /* Print the logging buffer to stdout. */ + IotLogging_Puts( pLoggingBuffer ); + + /* Free the logging buffer. */ + IotLogging_Free( pLoggingBuffer ); +} + +/*-----------------------------------------------------------*/ + +void IotLog_GenericPrintBuffer( const char * const pLibraryName, + const char * const pHeader, + const uint8_t * const pBuffer, + size_t bufferSize ) +{ + size_t i = 0, offset = 0; + + /* Allocate memory to hold each line of the log message. Since each byte + * of pBuffer is printed in 4 characters (2 digits, a space, and a null- + * terminator), the size of each line is 4 * BYTES_PER_LINE. */ + char * pMessageBuffer = IotLogging_Malloc( 4 * BYTES_PER_LINE ); + + /* Exit if no memory is available. */ + if( pMessageBuffer == NULL ) + { + return; + } + + /* Print pHeader before printing pBuffer. */ + if( pHeader != NULL ) + { + IotLog_Generic( IOT_LOG_DEBUG, + pLibraryName, + IOT_LOG_DEBUG, + NULL, + pHeader ); + } + + /* Print each byte in pBuffer. */ + for( i = 0; i < bufferSize; i++ ) + { + /* Print a line if BYTES_PER_LINE is reached. But don't print a line + * at the beginning (when i=0). */ + if( ( i % BYTES_PER_LINE == 0 ) && ( i != 0 ) ) + { + IotLogging_Puts( pMessageBuffer ); + + /* Reset offset so that pMessageBuffer is filled from the beginning. */ + offset = 0; + } + + /* Print a single byte into pMessageBuffer. */ + ( void ) snprintf( pMessageBuffer + offset, 4, "%02x ", pBuffer[ i ] ); + + /* Move the offset where the next character is printed. */ + offset += 3; + } + + /* Print the final line of bytes. This line isn't printed by the for-loop above. */ + IotLogging_Puts( pMessageBuffer ); + + /* Free memory used by this function. */ + IotLogging_Free( pMessageBuffer ); +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/aws_libraries/logging/iot_logging_task_dynamic_buffers.c b/bsp/aws_libraries/logging/iot_logging_task_dynamic_buffers.c new file mode 100644 index 0000000..c482936 --- /dev/null +++ b/bsp/aws_libraries/logging/iot_logging_task_dynamic_buffers.c @@ -0,0 +1,484 @@ +/* + * FreeRTOS Common V1.1.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Logging includes. */ +#include "iot_logging_task.h" +#include "logging_levels.h" + +/* Standard includes. */ +#include +#include +#include + +/* Sanity check all the definitions required by this file are set. */ +#ifndef configPRINT_STRING + #error configPRINT_STRING( x ) must be defined in FreeRTOSConfig.h to use this logging file. Set configPRINT_STRING( x ) to a function that outputs a string, where X is the string. For example, #define configPRINT_STRING( x ) MyUARTWriteString( X ) +#endif + +#ifndef configLOGGING_MAX_MESSAGE_LENGTH + #error configLOGGING_MAX_MESSAGE_LENGTH must be defined in FreeRTOSConfig.h to use this logging file. configLOGGING_MAX_MESSAGE_LENGTH sets the size of the buffer into which formatted text is written, so also sets the maximum log message length. +#endif + +#ifndef configLOGGING_INCLUDE_TIME_AND_TASK_NAME + #error configLOGGING_INCLUDE_TIME_AND_TASK_NAME must be defined in FreeRTOSConfig.h to use this logging file. Set configLOGGING_INCLUDE_TIME_AND_TASK_NAME to 1 to prepend a time stamp, message number and the name of the calling task to each logged message. Otherwise set to 0. +#endif + +/* A block time of 0 just means don't block. */ +#define loggingDONT_BLOCK 0 + +/* + * Wrapper functions for vsnprintf and snprintf to return the actual number of + * characters written. + * + * From the documentation, the retrun value of vsnprintf/snprintf is: + * 1. In case of success i.e. when the complete string is successfully written + * to the buffer, the return value is the number of characters written to the + * buffer not counting the terminating null character. + * 2. In case when the buffer is not large enough to hold the complete string, + * the return value is the number of characters that would have been written + * if the buffer was large enough. + * 3. In case of encoding error, a negative number is returned. + * + * These wrapper functions instead return the actual number of characters + * written in all cases: + * 1. In case of success i.e. when the complete string is successfully written + * to the buffer, these wrappers return the same value as from + * vsnprintf/snprintf. + * 2. In case when the buffer is not large enough to hold the complete string, + * these wrapper functions return the number of actual characters written + * (i.e. n - 1) as opposed to the number of characters that would have been + * written if the buffer was large enough. + * 3. In case of encoding error, these wrapper functions return 0 to indicate + * that nothing was written as opposed to negative value from + * vsnprintf/snprintf. + */ +static int vsnprintf_safe( char * s, + size_t n, + const char * format, + va_list arg ); +static int snprintf_safe( char * s, + size_t n, + const char * format, + ... ); + +/*-----------------------------------------------------------*/ + +/* + * The task that actually performs the print output. Using a separate task + * enables the use of slow output, such as as a UART, without the task that is + * outputting the log message having to wait for the message to be completely + * written. Using a separate task also serializes access to the output port. + * + * The structure of this task is very simple; it blocks on a queue to wait for + * a pointer to a string, sending any received strings to a macro that performs + * the actual output. The macro is port specific, so implemented outside of + * this file. This version uses dynamic memory, so the buffer that contained + * the log message is freed after it has been output. + */ +static void prvLoggingTask( void * pvParameters ); + +/*-----------------------------------------------------------*/ + +/* + * The queue used to pass pointers to log messages from the task that created + * the message to the task that will performs the output. + */ +static QueueHandle_t xQueue = NULL; + +/*-----------------------------------------------------------*/ + +static int vsnprintf_safe( char * s, + size_t n, + const char * format, + va_list arg ) +{ + int ret; + + ret = vsnprintf( s, n, format, arg ); + + /* Check if the string was truncated and if so, update the return value + * to reflect the number of characters actually written. */ + if( ret >= n ) + { + /* Do not include the terminating NULL character to keep the behaviour + * same as the standard. */ + ret = n - 1; + } + else if( ret < 0 ) + { + /* Encoding error - Return 0 to indicate that nothing was written to the + * buffer. */ + ret = 0; + } + else + { + /* Complete string was written to the buffer. */ + } + + return ret; +} + +/*-----------------------------------------------------------*/ + +static int snprintf_safe( char * s, + size_t n, + const char * format, + ... ) +{ + int ret; + va_list args; + + va_start( args, format ); + ret = vsnprintf_safe( s, n, format, args ); + va_end( args ); + + return ret; +} + +/*-----------------------------------------------------------*/ + +BaseType_t xLoggingTaskInitialize( uint16_t usStackSize, + UBaseType_t uxPriority, + UBaseType_t uxQueueLength ) +{ + BaseType_t xReturn = pdFAIL; + + /* Ensure the logging task has not been created already. */ + if( xQueue == NULL ) + { + /* Create the queue used to pass pointers to strings to the logging task. */ + xQueue = xQueueCreate( uxQueueLength, sizeof( char ** ) ); + + if( xQueue != NULL ) + { + if( xTaskCreate( prvLoggingTask, "Logging", usStackSize, NULL, uxPriority, NULL ) == pdPASS ) + { + xReturn = pdPASS; + } + else + { + /* Could not create the task, so delete the queue again. */ + vQueueDelete( xQueue ); + } + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvLoggingTask( void * pvParameters ) +{ + /* Disable unused parameter warning. */ + ( void ) pvParameters; + + char * pcReceivedString = NULL; + + for( ; ; ) + { + /* Block to wait for the next string to print. */ + if( xQueueReceive( xQueue, &pcReceivedString, portMAX_DELAY ) == pdPASS ) + { + configPRINT_STRING( pcReceivedString ); + + vPortFree( ( void * ) pcReceivedString ); + } + } +} + +/*-----------------------------------------------------------*/ + +static void prvLoggingPrintfCommon( uint8_t usLoggingLevel, + const char * pcFile, + size_t fileLineNo, + const char * pcFormat, + va_list args ) +{ + size_t xLength = 0; + char * pcPrintString = NULL; + + configASSERT( usLoggingLevel <= LOG_DEBUG ); + configASSERT( pcFormat != NULL ); + configASSERT( configLOGGING_MAX_MESSAGE_LENGTH > 0 ); + + /* The queue is created by xLoggingTaskInitialize(). Check + * xLoggingTaskInitialize() has been called. */ + configASSERT( xQueue ); + + /* Allocate a buffer to hold the log message. */ + pcPrintString = pvPortMalloc( configLOGGING_MAX_MESSAGE_LENGTH ); + + if( pcPrintString != NULL ) + { + const char * pcLevelString = NULL; + size_t ulFormatLen = 0UL; + + /* Add metadata of task name and tick time for a new log message. */ + if( strcmp( pcFormat, "\n" ) != 0 ) + { + /* Add metadata of task name and tick count if config is enabled. */ + #if ( configLOGGING_INCLUDE_TIME_AND_TASK_NAME == 1 ) + { + const char * pcTaskName; + const char * pcNoTask = "None"; + static BaseType_t xMessageNumber = 0; + + /* Add a time stamp and the name of the calling task to the + * start of the log. */ + if( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED ) + { + pcTaskName = pcTaskGetName( NULL ); + } + else + { + pcTaskName = pcNoTask; + } + + xLength += snprintf_safe( pcPrintString, configLOGGING_MAX_MESSAGE_LENGTH, "%lu %lu [%s] ", + ( unsigned long ) xMessageNumber++, + ( unsigned long ) xTaskGetTickCount(), + pcTaskName ); + } + #endif /* if ( configLOGGING_INCLUDE_TIME_AND_TASK_NAME == 1 ) */ + } + + /* Choose the string for the log level metadata for the log message. */ + switch( usLoggingLevel ) + { + case LOG_ERROR: + pcLevelString = "ERROR"; + break; + + case LOG_WARN: + pcLevelString = "WARN"; + break; + + case LOG_INFO: + pcLevelString = "INFO"; + break; + + case LOG_DEBUG: + pcLevelString = "DEBUG"; + } + + /* Add the chosen log level information as prefix for the message. */ + if( ( pcLevelString != NULL ) && ( xLength < configLOGGING_MAX_MESSAGE_LENGTH ) ) + { + xLength += snprintf_safe( pcPrintString + xLength, configLOGGING_MAX_MESSAGE_LENGTH - xLength, "[%s] ", pcLevelString ); + } + + /* If provided, add the source file and line number metadata in the message. */ + if( ( pcFile != NULL ) && ( xLength < configLOGGING_MAX_MESSAGE_LENGTH ) ) + { + /* If a file path is provided, extract only the file name from the string + * by looking for '/' or '\' directory seperator. */ + const char * pcFileName = NULL; + + /* Check if file path contains "\" as the directory separator. */ + if( strrchr( pcFile, '\\' ) != NULL ) + { + pcFileName = strrchr( pcFile, '\\' ) + 1; + } + /* Check if file path contains "/" as the directory separator. */ + else if( strrchr( pcFile, '/' ) != NULL ) + { + pcFileName = strrchr( pcFile, '/' ) + 1; + } + else + { + /* File path contains only file name. */ + pcFileName = pcFile; + } + + xLength += snprintf_safe( pcPrintString + xLength, configLOGGING_MAX_MESSAGE_LENGTH - xLength, "[%s:%d] ", pcFileName, fileLineNo ); + configASSERT( xLength > 0 ); + } + + if( xLength < configLOGGING_MAX_MESSAGE_LENGTH ) + { + xLength += vsnprintf_safe( pcPrintString + xLength, configLOGGING_MAX_MESSAGE_LENGTH - xLength, pcFormat, args ); + } + + /* Add newline characters if the message does not end with them.*/ + ulFormatLen = strlen( pcFormat ); + + if( ( ulFormatLen >= 2 ) && + ( strncmp( pcFormat + ulFormatLen, "\r\n", 2 ) != 0 ) && + ( xLength < configLOGGING_MAX_MESSAGE_LENGTH ) ) + { + xLength += snprintf_safe( pcPrintString + xLength, configLOGGING_MAX_MESSAGE_LENGTH - xLength, "%s", "\r\n" ); + } + + /* The standard says that snprintf writes the terminating NULL + * character. Just re-write it in case some buggy implementation does + * not. */ + configASSERT( xLength < configLOGGING_MAX_MESSAGE_LENGTH ); + pcPrintString[ xLength ] = '\0'; + + /* Only send the buffer to the logging task if it is + * not empty. */ + if( xLength > 0 ) + { + /* Send the string to the logging task for IO. */ + if( xQueueSend( xQueue, &pcPrintString, loggingDONT_BLOCK ) != pdPASS ) + { + /* The buffer was not sent so must be freed again. */ + vPortFree( ( void * ) pcPrintString ); + } + } + else + { + /* The buffer was not sent, so it must be + * freed. */ + vPortFree( ( void * ) pcPrintString ); + } + } +} + +/*-----------------------------------------------------------*/ + +void vLoggingPrintfError( const char * pcFormat, + ... ) +{ + va_list args; + + va_start( args, pcFormat ); + prvLoggingPrintfCommon( LOG_ERROR, NULL, 0, pcFormat, args ); + + va_end( args ); +} + +/*-----------------------------------------------------------*/ + +void vLoggingPrintfWarn( const char * pcFormat, + ... ) +{ + va_list args; + + va_start( args, pcFormat ); + prvLoggingPrintfCommon( LOG_WARN, NULL, 0, pcFormat, args ); + + va_end( args ); +} + +/*-----------------------------------------------------------*/ + +void vLoggingPrintfInfo( const char * pcFormat, + ... ) +{ + va_list args; + + va_start( args, pcFormat ); + prvLoggingPrintfCommon( LOG_INFO, NULL, 0, pcFormat, args ); + + va_end( args ); +} + +/*-----------------------------------------------------------*/ + +void vLoggingPrintfDebug( const char * pcFormat, + ... ) +{ + va_list args; + + va_start( args, pcFormat ); + prvLoggingPrintfCommon( LOG_DEBUG, NULL, 0, pcFormat, args ); + + va_end( args ); +} + +/*-----------------------------------------------------------*/ + +void vLoggingPrintfWithFileAndLine( const char * pcFile, + size_t fileLineNo, + const char * pcFormat, + ... ) +{ + configASSERT( pcFile != NULL ); + + va_list args; + + va_start( args, pcFormat ); + prvLoggingPrintfCommon( LOG_NONE, pcFile, fileLineNo, pcFormat, args ); + + va_end( args ); +} + +/*-----------------------------------------------------------*/ + +/*! + * \brief Formats a string to be printed and sends it + * to the print queue. + * + * Appends the message number, time (in ticks), and task + * that called vLoggingPrintf to the beginning of each + * print statement. + * + */ +void vLoggingPrintf( const char * pcFormat, + ... ) +{ + va_list args; + + va_start( args, pcFormat ); + prvLoggingPrintfCommon( LOG_NONE, NULL, 0, pcFormat, args ); + + va_end( args ); +} + +/*-----------------------------------------------------------*/ + +void vLoggingPrint( const char * pcMessage ) +{ + char * pcPrintString = NULL; + size_t xLength = 0; + + /* The queue is created by xLoggingTaskInitialize(). Check + * xLoggingTaskInitialize() has been called. */ + configASSERT( xQueue ); + + xLength = strlen( pcMessage ) + 1; + pcPrintString = pvPortMalloc( xLength ); + + if( pcPrintString != NULL ) + { + strncpy( pcPrintString, pcMessage, xLength ); + + /* Send the string to the logging task for IO. */ + if( xQueueSend( xQueue, &pcPrintString, loggingDONT_BLOCK ) != pdPASS ) + { + /* The buffer was not sent so must be freed again. */ + vPortFree( ( void * ) pcPrintString ); + } + } +} + +/*-----------------------------------------------------------*/ diff --git a/bsp/freertos-platform/NetworkInterface.c b/bsp/freertos-platform/NetworkInterface.c deleted file mode 100644 index ff4736c..0000000 --- a/bsp/freertos-platform/NetworkInterface.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stdio.h" -#include - -#include "FreeRTOS.h" -#include "task.h" -#include "FreeRTOS_IP.h" -#include "FreeRTOS_Sockets.h" -#include "NetworkBufferManagement.h" -#include "NetworkInterface.h" -#include "FreeRTOS_IP_Private.h" -#include "semphr.h" - -#include "cmsis.h" -#include "cmsis_driver_config.h" -#include "lan91c111.h" - -#define ETH_DEV SMSC9220_ETH_DEV -#define CRC_LENGTH_BYTES 4U - -static TaskHandle_t xReceiveTask = NULL; -static SemaphoreHandle_t xRXSemaphore; -static SemaphoreHandle_t xTXSemaphore; - -static void smsc9220_Receive_task( void *pvParameters ); - -/** - * So called interrupt from lan91 ethernet -*/ -void my_lan91_callback(lan91_event_t event, void *userData) -{ - BaseType_t taskWoken = pdFALSE; - - //NVIC_ClearPendingIRQ(ETHERNET_IRQn); - NVIC_DisableIRQ(ETHERNET_IRQn); - - vTaskNotifyGiveFromISR(xReceiveTask, &taskWoken); - portYIELD_FROM_ISR(taskWoken); -} - -BaseType_t xNetworkInterfaceInitialise( void ) -{ - //enum smsc9220_error_t ret = SMSC9220_ERROR_NONE; - uint8_t MACaddr[ipMAC_ADDRESS_LENGTH_BYTES] = {0}; - - FreeRTOS_debug_printf(("\r\nInit SMSC 9220 Ethernet driver...\r\n")); - - /* Execution must not be taken away during Ethernet controller init */ - taskENTER_CRITICAL(); - vTaskSuspendAll(); - //ret = smsc9220_init(Ð_DEV, &busy_wait_ms); - LAN91_init(); - xTaskResumeAll(); - taskEXIT_CRITICAL(); - - /* Register ethernet interrupt handler */ - LAN91_SetCallback(my_lan91_callback, NULL); -// if (ret != SMSC9220_ERROR_NONE) { -// printf("\r\nError in SMSC 9220 Ethernet init.\r\n"); -// return pdFALSE; -// } else { -// printf(" done!\r\n"); -// } - - //smsc9220_read_mac_address(Ð_DEV, MACaddr); - read_MACaddr(MACaddr); - printf("%x %x %x %x %x %x", MACaddr[0], MACaddr[1], MACaddr[2], MACaddr[3], MACaddr[4], MACaddr[5]); - FreeRTOS_UpdateMACAddress((const uint8_t *)MACaddr); - - xRXSemaphore = xSemaphoreCreateMutex(); - xTXSemaphore = xSemaphoreCreateMutex(); - - // create receive task - xTaskCreate(smsc9220_Receive_task, "smsc9220 receive", 1024, NULL, configMAX_PRIORITIES-2, NULL); - - //smsc9220_enable_interrupt(Ð_DEV, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - //NVIC_EnableIRQ(ETHERNET_IRQn); - - return pdTRUE; -} - -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, - BaseType_t xReleaseAfterSend ) -{ - bool ret; - xSemaphoreTake(xTXSemaphore, portMAX_DELAY); - //smsc9220_send_by_chunks(Ð_DEV, (uint32_t)pxDescriptor->xDataLength, true, - // (char*)pxDescriptor->pucEthernetBuffer, - // (uint32_t)pxDescriptor->xDataLength); - //printf("Sending frame\r\n"); - vTaskDelay(10); - //pxDescriptor->xDataLength /= 4; - ret = LAN91_send_frame( (uint32_t *)pxDescriptor->pucEthernetBuffer, (uint32_t *) &(pxDescriptor->xDataLength)); - - if(!ret) { - FreeRTOS_debug_printf(("Error in sending frame!!!\r\n")); - } - - xSemaphoreGive(xTXSemaphore); - - /* Call the standard trace macro to log the send event. */ - iptraceNETWORK_INTERFACE_TRANSMIT(); - - if (xReleaseAfterSend == pdTRUE) { - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); - } - - return pdTRUE; -} - -// FIXME would be nicer to use something like this in device cfg: -// #define SMSC9220_Ethernet_Interrupt_Handler ETHERNET_IRQHandler -// and than here SMSC9220_Ethernet_Interrupt_Handler(void) - -/*void ETHERNET_Handler(void) -{ - BaseType_t taskWoken = pdFALSE; - if (smsc9220_get_interrupt(Ð_DEV, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL)) { - - smsc9220_disable_interrupt(Ð_DEV, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - smsc9220_clear_interrupt(Ð_DEV, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - NVIC_ClearPendingIRQ(ETHERNET_IRQn); - //NVIC_DisableIRQ(ETHERNET_IRQn); // does this needed?? - - vTaskNotifyGiveFromISR(xReceiveTask, &taskWoken); - // if (taskWoken != pdTRUE) { - // printf("Error waking RX task from ISR"); - // } - } else { - // not expected interrupt - } - portYIELD_FROM_ISR(taskWoken); -}*/ - -//static uint8_t static_buffer_for_test[1000]; - -static void smsc9220_Receive_task( void *pvParameters ) -{ - FreeRTOS_debug_printf(("smsc9220 ethernet receive task created\r\n")); - NetworkBufferDescriptor_t *pxBufferDescriptor; - /* Used to indicate that xSendEventStructToIPTask() is being called because - of an Ethernet receive event. */ - IPStackEvent_t xRxEvent; - - xReceiveTask = xTaskGetCurrentTaskHandle(); - - //smsc9220_enable_interrupt(Ð_DEV, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - //NVIC_EnableIRQ(ETHERNET_IRQn); - - FreeRTOS_debug_printf(("Receive thred started!!!\r\n")); - - while (1) { - /* Sleep thread until notified from Ethernet ISR */ - NVIC_EnableIRQ(ETHERNET_IRQn); - //NVIC_ClearPendingIRQ(ETHERNET_IRQn); - LAN91_SetInterruptMasks(MSK_RCV); - //smsc9220_enable_interrupt(Ð_DEV, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - ulTaskNotifyTake(pdFALSE, portMAX_DELAY); - - /* Peak transfer size */ - //message_length = smsc9220_peek_next_packet_size(Ð_DEV); - // if (message_length == 0) { - // /* There are no packets to read */ - // continue; - //} else { - // /* The Ethernet controller cannot remove CRC from the end of the - // * incoming packet, thus it should be taken into account when - // * calculating the actual message length.*/ - // message_length -= CRC_LENGTH_BYTES; - //} - - /* Allocate a network buffer descriptor that points to a buffer - large enough to hold the received frame. As this is the simple - rather than efficient example the received data will just be copied - into this buffer. */ - pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( LAN91_ETH_MTU_SIZE, 0 ); - - if( pxBufferDescriptor != NULL ) - { - xSemaphoreTake(xRXSemaphore, portMAX_DELAY); - //received_bytes = smsc9220_receive_by_chunks(Ð_DEV, pxBufferDescriptor->pucEthernetBuffer, message_length); - //pxBufferDescriptor->xDataLength = received_bytes; - - if (!LAN91_receive_frame((uint32_t*)pxBufferDescriptor->pucEthernetBuffer, &pxBufferDescriptor->xDataLength)) { - FreeRTOS_debug_printf(("Receive error!\r\n")); - } - - /* See if the data contained in the received Ethernet frame needs - to be processed. NOTE! It is preferable to do this in - the interrupt service routine itself, which would remove the need - to unblock this task for packets that don't need processing. */ - if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) - == eProcessBuffer ) - { - /* The event about to be sent to the TCP/IP is an Rx event. */ - xRxEvent.eEventType = eNetworkRxEvent; - - /* pvData is used to point to the network buffer descriptor that - now references the received data. */ - xRxEvent.pvData = ( void * ) pxBufferDescriptor; - - /* Send the data to the TCP/IP stack. */ - if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) - { - /* The buffer could not be sent to the IP task so the buffer - must be released. */ - vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor ); - - /* Make a call to the standard trace macro to log the - occurrence. */ - iptraceETHERNET_RX_EVENT_LOST(); - } - else - { - /* The message was successfully sent to the TCP/IP stack. - Call the standard trace macro to log the occurrence. */ - iptraceNETWORK_INTERFACE_RECEIVE(); - } - } - else - { - /* The Ethernet frame can be dropped, but the Ethernet buffer - must be released. */ - vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor ); - } - xSemaphoreGive(xRXSemaphore); - } - else - { - /* The event was lost because a network buffer was not available. - Call the standard trace macro to log the occurrence. */ - iptraceETHERNET_RX_EVENT_LOST(); - } - - } -} diff --git a/bsp/freertos-platform/application_helpers.c b/bsp/freertos-platform/application_helpers.c index 08cf4b5..94338ae 100644 --- a/bsp/freertos-platform/application_helpers.c +++ b/bsp/freertos-platform/application_helpers.c @@ -16,7 +16,7 @@ #include "stdio.h" #include -#include "serial.h" +#include "bsp_serial.h" #include "print_log.h" #include "FreeRTOS.h" @@ -29,14 +29,6 @@ #include "psa/crypto.h" -/* includes for IoT Cloud */ -#include "iot_mqtt.h" -#include "iot_secure_sockets.h" -#include "iot_network_freertos.h" -#include "iot_logging_task.h" -#include "aws_dev_mode_key_provisioning.h" - - /* ----------------------------------------------------------------------------- * Helper functions * ----------------------------------------------------------------------------- @@ -48,14 +40,6 @@ void vAssertCalled( const char * pcFile, unsigned long ulLine ) while(1); } -// void vLoggingPrint( const char * pcMessage ) -// { -// // this needs to be reworked to take infinite arguments and pass along them to printf -// if (xSemaphoreTake(uartSemaphore, portMAX_DELAY) == pdTRUE) { -// printf("%s", pcMessage); -// xSemaphoreGive(uartSemaphore); -// } -// } /** * This function is only used in the PKCS#11 test case. In the PKCS#11 test, diff --git a/bsp/source/serial.c b/bsp/freertos-platform/bsp_serial.c similarity index 52% rename from bsp/source/serial.c rename to bsp/freertos-platform/bsp_serial.c index c73e0f1..6853137 100644 --- a/bsp/source/serial.c +++ b/bsp/freertos-platform/bsp_serial.c @@ -16,39 +16,33 @@ #include #include -#include "device_cfg.h" -#include "Driver_USART.h" -#include "serial.h" -extern ARM_DRIVER_USART Driver_USART0; +#include "bsp_serial.h" +#include "serial_api.h" -void serial_init(void) -{ - Driver_USART0.Initialize(NULL); - Driver_USART0.Control(ARM_USART_MODE_ASYNCHRONOUS, DEFAULT_UART_BAUDRATE); -} +static serial_t my_uart; -void serial_print(char *str) +void bsp_serial_init(void) { - (void)Driver_USART0.Send(str, strlen(str)); + serial_init(&my_uart, CONSOLE_TX, CONSOLE_RX); + serial_baud(&my_uart, 115200); } -/* Struct FILE is implemented in stdio.h. Used to redirect printf to UART0 */ -// FILE __stdout; -/* Redirects armclang printf to UART */ -int fputc(int ch, FILE *f) +void bsp_serial_print(char *str) { - if (Driver_USART0.Send(&ch, 1) == ARM_DRIVER_OK) { - return ch; + while (*str != '\0') { + serial_putc(&my_uart, *str++); } - return EOF; } /* Redirects gcc printf to UART0 */ int _write(int fd, char *str, int len) { - if (Driver_USART0.Send(str, len) == ARM_DRIVER_OK) { - return len; + int cnt = len; + while(cnt > 0) { + serial_putc(&my_uart, *str++); + --cnt; } - return 0; + + return len - cnt; } diff --git a/kws/include/serial.h b/bsp/freertos-platform/bsp_serial.h similarity index 94% rename from kws/include/serial.h rename to bsp/freertos-platform/bsp_serial.h index 3dd3890..5c1a968 100644 --- a/kws/include/serial.h +++ b/bsp/freertos-platform/bsp_serial.h @@ -35,12 +35,12 @@ typedef void(* serial_cmd_cb_t)(serial_cmd_t); /** * \brief Initializes default UART device */ -void serial_init(void); +void bsp_serial_init(void); /** * \brief Prints a string through the default UART device */ -void serial_print(char *str); +void bsp_serial_print(char *str); #ifdef __cplusplus } diff --git a/bsp/freertos-platform/lan91c111.c b/bsp/freertos-platform/lan91c111.c deleted file mode 100644 index 3a0d334..0000000 --- a/bsp/freertos-platform/lan91c111.c +++ /dev/null @@ -1,372 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2021 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include "lan91c111.h" -#include -#include - -static lan91_handle_t lan91c111_handle; - -/** @brief Write a data value to PHY register. */ -static void write_PHY(uint32_t PhyReg, int Value); - -/** @brief Read a PHY register. */ -static uint16_t read_PHY(uint32_t PhyReg); - -void LAN91_init(void) -{ - - uint32_t tcr, stat; - - LAN91_ClearInterruptMasks(); - LAN91_Reset(); - - /* Clear control registers. */ - LAN91_SelectBank(0); - LREG(uint16_t, B0_RCR) = 0; - LREG(uint16_t, B0_TCR) = 0; - - /* Write Configuration Registers */ - LAN91_SelectBank(1); - LREG(uint16_t, B1_CR) = CR_EPH_POW_EN | CR_DEFAULT; - - /* Reset the PHY*/ - write_PHY(0, 0x8000); - - /* clear phy 18 status */ - read_PHY(18); - - /* Use 100MBit link speed by default. */ - LAN91_SelectBank(0); - LREG(uint16_t, B0_RPCR) = RPCR_SPEED | LEDA_10M_100M | LEDB_TX_RX; - - /* Read Status Register */ - stat = read_PHY(18); - - /* Set the Control Register */ - LAN91_SelectBank(1); - LREG(uint16_t, B1_CTR) = CTR_LE_ENABLE | CTR_CR_ENABLE | CTR_TE_ENABLE | CTR_AUTO_REL | CTR_DEFAULT; - - /* Setup Transmit Control Register. */ - tcr = TCR_TXENA | TCR_PAD_EN; - if (stat & 0x0040) { - tcr |= TCR_FDUPLX; - } - LREG(uint16_t, B0_TCR) = (uint16_t)tcr; - - /* Reset MMU */ - LAN91_SelectBank(2); - LREG(uint16_t, B2_MMUCR) = MMU_RESET; - while (LREG(uint16_t, B2_MMUCR) & MMUCR_BUSY); - - /* Configure the Interrupts, allow RX_OVRN and RCV intr. */ - LAN91_SetInterruptMasks(MSK_RCV); - - /* Set all buffers or data in handler for data transmit/receive process. */ - LAN91_SetHandler(); -} - -void read_MACaddr(uint8_t *addr) -{ - int i; - - LAN91_SelectBank(1); - - i = LREG(uint16_t, B1_IAR0); - addr[0] = (uint8_t)i; - addr[1] = (uint8_t)(i >> 8); - - i = LREG(uint16_t, B1_IAR2); - addr[2] = (uint8_t)i; - addr[3] = (uint8_t)(i >> 8); - - i = LREG(uint16_t, B1_IAR4); - addr[4] = (uint8_t)i; - addr[5] = (uint8_t)(i >> 8); -} - -void LAN91_SetCallback(lan91_callback_t callback, void *userData) -{ - /* Set callback and userData. */ - lan91c111_handle.callback = callback; - lan91c111_handle.userData = userData; -} - - -bool LAN91_send_frame(uint32_t *buff, uint32_t *size) -{ - /* Send frame to Lan91C111 ethernet controller */ - uint16_t *dp; - uint8_t packnr; - int i; - - LAN91_SelectBank(2); - - /* MMU allocate memory for transmitting*/ - LREG(uint16_t, B2_MMUCR) = MMU_ALLOC_TX; - - /* Check if Interrupt Status Register been set for MMU Allocate Ready */ - if (!(LREG(uint16_t, B2_IST) & IST_ALLOC_INT)) { - /* Failed, Reset MMU */ - LREG(uint16_t, B2_MMUCR) = MMU_RESET; - while (LREG(uint16_t, B2_MMUCR) & MMUCR_BUSY); - return false; - } - - /* set TX package number from allocated package number - and also set pointer register as Auto Increase, write and transmit set */ - packnr = LREG(uint8_t, B2_ARR); - LREG(uint8_t, B2_PNR) = packnr; - LREG(uint16_t, B2_PTR) = PTR_AUTO_INCR; - - /* Reserve space for Status Word */ - LREG(uint16_t, B2_DATA0) = 0x0000; - /* Total = Raw Data Size + STATUS WORD + BYTE COUNT + CONTROL BYTE + LAST BYTE */ - LREG(uint16_t, B2_DATA0) = (uint16_t) * size + 6; - - /* Copy frame data to Ethernet controller */ - dp = (uint16_t *)buff; - for (i = *size; i > 1; i -= 2) { - LREG(uint16_t, B2_DATA0) = *dp++; - } - - /* If data is odd , Add a control word and odd byte. */ - if (i) { - LREG(uint16_t, B2_DATA0) = (RFC_CRC | RFC_ODD) | (*dp & 0xFF); - } else { - /* Add control word. */ - LREG(uint16_t, B2_DATA0) = RFC_CRC; - } - - LAN91_SelectBank(0); - /* Enable transmitter. */ - LREG(uint16_t, B0_TCR) = TCR_TXENA | TCR_PAD_EN; - - /* Enqueue the packet. */ - LAN91_SelectBank(2); - LREG(uint16_t, B2_MMUCR) = MMU_ENQ_TX; - - return true; -} - - - -bool LAN91_receive_frame(uint32_t *buff, uint32_t *size) -{ - uint32_t State, RxLen; - uint32_t val, *dp; - - /* No receive packets queued in Rx FIFO queue */ - LAN91_SelectBank(2); - State = LREG(uint16_t, B2_FIFO); - if (State & FIFO_REMPTY) { - return false; - } - - - /* Pointer Register set to RCV + Auto Increase + Read access - So that Data Register is use RX FIFO*/ - LREG(uint16_t, B2_PTR) = PTR_RCV | PTR_AUTO_INCR | PTR_READ; - - /* Read status word and packet length */ - val = LREG(uint32_t, B2_DATA); - State = val & 0xFFFF; - /* Raw Data Size = Total - STATUS WORD - BYTE COUNT - CONTROL BYTE - LAST BYTE */ - RxLen = (val >> 16) - 6; - - /* Check State word if Odd number of bytes in a frame. */ - if (State & RFS_ODDFRM) { - RxLen++; - } - - /* Packet too big, ignore it and free MMU and continue */ - if (RxLen > LAN91_ETH_MTU_SIZE) { - LREG(uint16_t, B2_MMUCR) = MMU_REMV_REL_RX; - return false; - } - - if (buff != NULL) { - /* Make sure that block is dword aligned */ - RxLen = (RxLen + 3) >> 2; - *size = RxLen << 2; - dp = buff; - for (; RxLen; RxLen--) { - *dp++ = LREG(uint32_t, B2_DATA); - } - } - - /* MMU free packet. Remove and Relase from TOP of RX */ - LREG(uint16_t, B2_MMUCR) = MMU_REMV_REL_RX; - - return true; -} - - - -void ETHERNET_Handler(void) -{ - //printf("Frame received\r\n"); - LAN91_SelectBank(2); - if ((LREG(uint8_t, B2_IST) & IST_RCV) != 0) { - LREG(uint8_t, B2_MSK) = 0; - /* Callback function. */ - if (lan91c111_handle.callback) { - lan91c111_handle.callback(LAN91_RxEvent, lan91c111_handle.userData); - } - } -} - - -lan91_phy_status_t LAN91_GetLinkStatus(void) -{ - if (read_PHY(0x2u) & 0x4u) { - return STATE_LINK_UP; - } else { - return STATE_LINK_DOWN; - } -} - -static void output_MDO(int bit_value) -{ - uint32_t val = MGMT_MDOE; - - if (bit_value) { - val |= MGMT_MDO; - } - LREG(uint16_t, B3_MGMT) = (uint16_t)val; - LREG(uint16_t, B3_MGMT) = (uint16_t)(val | MGMT_MCLK); - LREG(uint16_t, B3_MGMT) = (uint16_t)val; -} - - - -static int input_MDI(void) -{ - int val = 0; - - LREG(uint16_t, B3_MGMT) = 0; - LREG(uint16_t, B3_MGMT) = MGMT_MCLK; - if (LREG(uint16_t, B3_MGMT) & MGMT_MDI) { - val = 1; - } - LREG(uint16_t, B3_MGMT) = 0; - return (val); -} - -static void write_PHY(uint32_t PhyReg, int Value) -{ - int i; - - LAN91_SelectBank(3); - LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; i++) { - LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO; - LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO | MGMT_MCLK; - } - LREG(uint16_t, B3_MGMT) = MGMT_MDOE; - - /* start code (01) */ - output_MDO(0); - output_MDO(1); - - /* write command (01) */ - output_MDO(0); - output_MDO(1); - - /* write PHY address - which is five 0s for 91C111 */ - for (i = 0; i < 5; i++) { - output_MDO(0); - } - - /* write the PHY register to write (highest bit first) */ - for (i = 0; i < 5; i++) { - output_MDO((PhyReg >> 4) & 0x01); - PhyReg <<= 1; - } - - /* turnaround MDO */ - output_MDO(1); - output_MDO(0); - - /* write the data value (highest bit first) */ - for (i = 0; i < 16; i++) { - output_MDO((Value >> 15) & 0x01); - Value <<= 1; - } - - /* turnaround MDO is tristated */ - LREG(uint16_t, B3_MGMT) = 0; - LREG(uint16_t, B3_MGMT) = MGMT_MCLK; - LREG(uint16_t, B3_MGMT) = 0; -} - - -static uint16_t read_PHY(uint32_t PhyReg) -{ - int i, val; - - LAN91_SelectBank(3); - LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; i++) { - LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO; - LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO | MGMT_MCLK; - } - LREG(uint16_t, B3_MGMT) = MGMT_MDOE; - - /* start code (01) */ - output_MDO(0); - output_MDO(1); - - /* read command (10) */ - output_MDO(1); - output_MDO(0); - - /* write PHY address - which is five 0s for 91C111 */ - for (i = 0; i < 5; i++) { - output_MDO(0); - } - - /* write the PHY register to read (highest bit first) */ - for (i = 0; i < 5; i++) { - output_MDO((PhyReg >> 4) & 0x01); - PhyReg <<= 1; - } - - /* turnaround MDO is tristated */ - LREG(uint16_t, B3_MGMT) = 0; - LREG(uint16_t, B3_MGMT) = MGMT_MCLK; - LREG(uint16_t, B3_MGMT) = 0; - - /* read the data value */ - val = 0; - for (i = 0; i < 16; i++) { - val <<= 1; - val |= input_MDI(); - } - - /* turnaround MDO is tristated */ - LREG(uint16_t, B3_MGMT) = 0; - LREG(uint16_t, B3_MGMT) = MGMT_MCLK; - LREG(uint16_t, B3_MGMT) = 0; - - return (val); -} diff --git a/bsp/freertos-platform/lan91c111.h b/bsp/freertos-platform/lan91c111.h deleted file mode 100644 index df74e2a..0000000 --- a/bsp/freertos-platform/lan91c111.h +++ /dev/null @@ -1,398 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2021 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __LAN91C111_H -#define __LAN91C111_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include -//#include "PeripheralNames.h" - -/* LAN91C111 base address used IO mode. */ -#define ADROFS 0x41400000 - -/* LAN91C111 Ethernet buffer alignment. */ -#define LAN91_BUFF_ALIGNMENT 16U - -#define LAN91_ETH_MTU_SIZE 1500 - -/* Absolute access to LAN91C111 registers macro */ -#define LREG(object, reg) (*((object volatile *) (ADROFS+reg))) - -/******************************************************************************* - * Register Definations - ******************************************************************************/ - -/* Bank Select defines */ -#define BSR 0x0E /* Bank Select register common to all banks */ -#define BSR_MASK 0x03 /* Mask constant part of bank register */ -#define BSR_UPPER 0x3300 /* Constant value for upper byte of BSR */ - -/* Bank 0 Registers */ -#define B0_TCR 0x00 /* Transmit Control Register rd/wr */ -#define B0_EPHSR 0x02 /* EPH Status Register rd */ -#define B0_RCR 0x04 /* Receive Control Register rd/wr */ -#define B0_ECR 0x06 /* Counter Register rd */ -#define B0_MIR 0x08 /* Memory Information Register rd */ -#define B0_RPCR 0x0A /* Receive/Phy Control Register rd/wr */ -#define B0_RES 0x0C /* Reserved */ - -/* Bank 1 Registers */ -#define B1_CR 0x00 /* Configuration Register rd/wr */ -#define B1_BAR 0x02 /* Base Address Register rd/wr */ -#define B1_IAR 0x04 /* Individual Address Registers rd/wr */ -#define B1_IAR0 0x04 /* Individual Address Bytes 0-1 rd/wr */ -#define B1_IAR2 0x06 /* Individual Address Bytes 2-3 rd/wr */ -#define B1_IAR4 0x08 /* Individual Address Bytes 4-5 rd/wr */ -#define B1_GPR 0x0A /* General Purpose Register rd/wr */ -#define B1_CTR 0x0C /* Control Register rd/wr */ - -/* Bank 2 Registers */ -#define B2_MMUCR 0x00 /* MMU Command Register rd/wr */ -#define B2_PNR 0x02 /* Packet Number Register (8 bit) rd/wr */ -#define B2_ARR 0x03 /* Allocation Result Register (8 bit) rd */ -#define B2_FIFO 0x04 /* FIFO Ports Register rd */ -#define B2_TX_FIFO 0x04 /* Tx FIFO Packet Number (8 bit) rd */ -#define B2_RX_FIFO 0x05 /* Rx FIFO Packet Number (8 bit) rd */ -#define B2_PTR 0x06 /* Pointer Register rd/wr */ -#define B2_DATA 0x08 /* Data Register (8/16/32 bit) rd/wr */ -#define B2_DATA0 0x08 /* Data Register Word 0 rd/wr */ -#define B2_DATA1 0x0A /* Data Register Word 1 rd/wr */ -#define B2_IST 0x0C /* Interrupt Status Register (8 bit) rd */ -#define B2_ACK 0x0C /* Interrupt Ack Register (8 bit) wr */ -#define B2_MSK 0x0D /* Interrupt Mask Register (8 bit) rd/wr */ - -/* Bank 3 Registers */ -#define B3_MT 0x00 /* Multicast Hash Table rd/wr */ -#define B3_MT0 0x00 /* Multicast Hash Table 0-1 rd/wr */ -#define B3_MT2 0x02 /* Multicast Hash Table 2-3 rd/wr */ -#define B3_MT4 0x04 /* Multicast Hash Table 4-5 rd/wr */ -#define B3_MT6 0x06 /* Multicast Hash Table 6-7 rd/wr */ -#define B3_MGMT 0x08 /* Management Interface PHY rd/wr */ -#define B3_REV 0x0A /* Revision Register (Chip Id/Revision)rd/wr */ -#define B3_ERCV 0x0C /* Early Receive Register rd/wr */ - - -/*-----TCR control bits-----*/ -#define TCR_SWFDUP 0x8000 /* Switched Full Duplex Mode */ -#define TCR_EPH_LOOP 0x2000 /* Internal Loopback at the EPH block */ -#define TCR_STP_SQET 0x1000 /* Stop transmit on SQET error */ -#define TCR_FDUPLX 0x0800 /* Full duplex mode (receive own frames) */ -#define TCR_MON_CSN 0x0400 /* Monitor carrier while transmitting */ -#define TCR_NOCRC 0x0100 /* Don't append CRC to tx frames */ -#define TCR_PAD_EN 0x0080 /* Pad short frames with 0 if len < 64 bytes */ -#define TCR_FORCOL 0x0004 /* Force collision */ -#define TCR_LOOP 0x0002 /* PHY Local loopback */ -#define TCR_TXENA 0x0001 /* Enable transmitter */ - -/*-----EPHSR status bits-----*/ -#define EPHSR_TXUNRN 0x8000 /* Transmit Under Run */ -#define EPHSR_LINK_OK 0x4000 /* General purpose input driven by nLNK pin */ -#define EPHSR_CTR_ROL 0x1000 /* Counter Roll Over */ -#define EPHSR_EXC_DEF 0x0800 /* Excessive Deferral */ -#define EPHSR_LOST_CARR 0x0400 /* Lost Carrier Sense */ -#define EPHSR_LATCOL 0x0200 /* Late Collision Detected */ -#define EPHSR_TX_DEFR 0x0080 /* Transmit Deferred */ -#define EPHSR_LTX_BRD 0x0040 /* Last Tx Frame was a broadcast */ -#define EPHSR_SQET 0x0020 /* Signal Quality Error Test */ -#define EPHSR_16COL 0x0010 /* 16 collisions reached */ -#define EPHSR_LTX_MULT 0x0008 /* Last transmit frame was a multicast */ -#define EPHSR_MULCOL 0x0004 /* Multiple collision detected for last tx */ -#define EPHSR_SNGLCOL 0x0002 /* Single collision detected for last tx */ -#define EPHSR_TX_SUC 0x0001 /* Last transmit was successful */ - -/*-----RCR control bits-----*/ -#define RCR_SOFT_RST 0x8000 /* Software-Activated Reset */ -#define RCR_FILT_CAR 0x4000 /* Filter Carrier */ -#define RCR_ABORT_ENB 0x2000 /* Enable Abort of Rx when collision */ -#define RCR_STRIP_CRC 0x0200 /* Strip CRC of received frames */ -#define RCR_RXEN 0x0100 /* Enable Receiver */ -#define RCR_ALMUL 0x0004 /* Accept all multicast (no filtering) */ -#define RCR_PRMS 0x0002 /* Promiscuous mode */ -#define RCR_RX_ABORT 0x0001 /* Receive frame aborted (too long) */ - -/*-----RPCR control bits-----*/ -#define RPCR_SPEED 0x2000 /* Speed select input (10/100 MBps) */ -#define RPCR_DPLX 0x1000 /* Duplex Select (Full/Half Duplex) */ -#define RPCR_ANEG 0x0800 /* Auto-Negotiation mode select */ -#define RPCR_LEDA_MASK 0x00E0 /* LEDA signal mode select */ -#define RPCR_LEDB_MASK 0x001C /* LEDB signal mode select */ - -/*-----LEDA ON modes-----*/ -#define LEDA_10M_100M 0x0000 /* 10 MB or 100 MB link detected */ -#define LEDA_10M 0x0040 /* 10 MB link detected */ -#define LEDA_FDUPLX 0x0060 /* Full Duplex Mode enabled */ -#define LEDA_TX_RX 0x0080 /* Transmit or Receive packet occurred */ -#define LEDA_100M 0x00A0 /* 100 MB link detected */ -#define LEDA_RX 0x00C0 /* Receive packet occurred */ -#define LEDA_TX 0x00E0 /* Transmit packet occurred */ - -/*-----LEDA ON modes-----*/ -#define LEDB_10M_100M 0x0000 /* 10 MB or 100 MB link detected */ -#define LEDB_10M 0x0008 /* 10 MB link detected */ -#define LEDB_FDUPLX 0x000C /* Full Duplex Mode enabled */ -#define LEDB_TX_RX 0x0010 /* Transmit or Receive packet occurred */ -#define LEDB_100M 0x0014 /* 100 MB link detected */ -#define LEDB_RX 0x0018 /* Receive packet occurred */ -#define LEDB_TX 0x001C /* Transmit packet occurred */ - -/*-----CR control bits-----*/ -#define CR_EPH_POW_EN 0x8000 /* EPH Power Enable (0= power down PHY) */ -#define CR_NO_WAIT 0x1000 /* No wait states */ -#define CR_GPCNTRL 0x0400 /* General purpose Output drives nCNTRL pin */ -#define CR_EXT_PHY 0x0200 /* External PHY enabled (0= internal PHY) */ -#define CR_DEFAULT 0x20B1 /* Default bits set to 1 for write */ - -/*-----CTR control bits-----*/ -#define CTR_RCV_BAD 0x4000 /* Bad CRC packet received */ -#define CTR_AUTO_REL 0x0800 /* Auto-release Tx memory */ -#define CTR_LE_ENABLE 0x0080 /* Link error enable (mux into EPH int) */ -#define CTR_CR_ENABLE 0x0040 /* Counter rollover enable (mux into EPH int)*/ -#define CTR_TE_ENABLE 0x0020 /* Transmit error enable (mux into EPH int) */ -#define CTR_EEPROM_SEL 0x0004 /* EEPROM select */ -#define CTR_RELOAD 0x0002 /* Reload from EEPROM */ -#define CTR_STORE 0x0001 /* Store to EEPROM */ -#define CTR_DEFAULT 0x1210 /* Default bits set to 1 for write */ - -/*-----MMUCR control bits-----*/ -#define MMUCR_CMD_MASK 0x00E0 /* MMU Command mask */ -#define MMUCR_BUSY 0x0001 /* MMU processing a release command */ - -/*-----MMUCR Commands------*/ -#define MMU_NOOP 0x0000 /* No operation */ -#define MMU_ALLOC_TX 0x0020 /* Allocate memory for Tx */ -#define MMU_RESET 0x0040 /* Reset MMU to initial state */ -#define MMU_REMV_RX 0x0060 /* Remove frame from top of Rx FIFO */ -#define MMU_REMV_REL_RX 0x0080 /* Remove and Release top of Rx FIFO */ -#define MMU_REL_PKT 0x00A0 /* Release specific packet */ -#define MMU_ENQ_TX 0x00C0 /* Enqueue packet number into Tx FIFO */ -#define MMU_RESET_TX 0x00E0 /* Reset Tx FIFO */ - -/*-----FIFO status bits-----*/ -#define FIFO_REMPTY 0x8000 /* No receive packets queued in Rx FIFO */ -#define FIFO_TEMPTY 0x0080 /* No transmit packets in completion queue */ - -/*-----PTR control bits-----*/ -#define PTR_RCV 0x8000 /* Address refers to Rx area (0= Tx area) */ -#define PTR_AUTO_INCR 0x4000 /* Auto increment on access */ -#define PTR_READ 0x2000 /* Read access (0= write access) */ -#define PTR_ETEN 0x1000 /* Enable early transmit underrun detection */ -#define PTR_NOT_EMPTY 0x0800 /* Data FIFO not empty yet (read only bit) */ -#define PTR_MASK 0x03FF /* Mask pointer value */ - -/*-----IST status bits-----*/ -#define IST_MDINT 0x80 /* PHY MI Register 18 change status interrupt*/ -#define IST_ERCV_INT 0x40 /* Early Receive interrupt */ -#define IST_EPH_INT 0x20 /* EPH Type interrupt */ -#define IST_RX_OVRN 0x10 /* Receive Overrun interrupt */ -#define IST_ALLOC_INT 0x08 /* Tx ram Allocation interrupt */ -#define IST_TX_EMPTY 0x04 /* Tx FIFO empty interrupt */ -#define IST_TX_INT 0x02 /* Tx Complete interrupt */ -#define IST_RCV 0x01 /* Rx Complete intererupt */ - -/*-----ACK control bits-----*/ -#define ACK_MDINT 0x80 /* PHY MI Register 18 change int. ack */ -#define ACK_ERCV_INT 0x40 /* Early Receive int. ack */ -#define ACK_RX_OVRN 0x10 /* Receive Overrun int. ack */ -#define ACK_TX_EMPTY 0x04 /* Tx FIFO empty int. ack */ -#define ACK_TX_INT 0x02 /* Tx Complete int. ack */ - -/*-----MSK control bits-----*/ -#define MSK_MDINT 0x80 /* PHY MI Register 18 change int. mask */ -#define MSK_ERCV_INT 0x40 /* Early Receive int. mask */ -#define MSK_EPH_INT 0x20 /* EPH Type int. mask */ -#define MSK_RX_OVRN 0x10 /* Receive Overrun int. mask */ -#define MSK_ALLOC_INT 0x08 /* Tx ram Allocation int. mask */ -#define MSK_TX_EMPTY 0x04 /* Tx FIFO empty int. mask */ -#define MSK_TX_INT 0x02 /* Tx Complete int. mask */ -#define MSK_RCV 0x01 /* Rx Complete int. mask */ - -/*-----MGMT control bits-----*/ -#define MGMT_MSK_CRS100 0x0040 /* Disables CRS100 detection in Tx Half Dupl.*/ -#define MGMT_MDOE 0x0008 /* MII - 1= MDO pin output, 0= MDO tristated */ -#define MGMT_MCLK 0x0004 /* MII - Value drives MDCLK pin */ -#define MGMT_MDI 0x0002 /* MII - Value of MDI pin when read */ -#define MGMT_MDO 0x0001 /* MII - Value drives MDO pin */ -#define MGMT_DEFAULT 0x3330 /* Default bits set to 1 for write */ - -/*----- Receive Frame Status -----*/ -#define RFS_ALGNERR 0x8000 /* Frame alignment error */ -#define RFS_BROADCAST 0x4000 /* Received broadcast frame */ -#define RFS_BADCRC 0x2000 /* Bad CRC error */ -#define RFS_ODDFRM 0x1000 /* Frame with Odd number of bytes received */ -#define RFS_TOOLNG 0x0800 /* Too long frame received (max. 1518 bytes) */ -#define RFS_TOOSHORT 0x0400 /* Too short frame received (min. 64 bytes) */ -#define RFS_MULTCAST 0x0001 /* Multicast frame received */ -#define RFS_HASH_MASK 0x007E /* Hash value index for multicast registers */ - -/*----- Receive Frame Control -----*/ -#define RFC_ODD 0x2000 /* Odd number of bytes in frame */ -#define RFC_CRC 0x1000 /* Append CRC (valid when TCR_NOCRC = 1) */ - -#endif - - -/******************************************************************************* - * Data Stractures - ******************************************************************************/ - -/*! @brief List of interrupts supported by the peripheral. This - * enumeration uses one-bot encoding to allow a logical OR of multiple - * members. Members usually map to interrupt enable bits in one or more - * peripheral registers. - */ -typedef enum _lan91_phy_status { - STATE_UNKNOWN = (-1), /* PHY MI Register 18 change status interrupt*/ - STATE_LINK_DOWN = (0), /* EPH Type interrupt */ - STATE_LINK_UP = (1) /* Receive Overrun interrupt */ -} lan91_phy_status_t; - -/*! @brief Defines the common interrupt event for callback use. */ -typedef enum _lan91_event { - LAN91_RxEvent, /*!< Receive event. */ - LAN91_TxEvent, /*!< Transmit event. */ - LAN91_ErrEvent /*!< Error event: BABR/BABT/EBERR/LC/RL/UN/PLR . */ -} lan91_event_t; - - -/* ------------------------------- Call back ---------------------------------*/ -/* Forward declaration of the handle typedef. */ -typedef struct _lan91_handle lan91_handle_t; - - -/*! @brief ENET callback function. */ -typedef void (*lan91_callback_t)(lan91_event_t event, void *userData); - - -/*! @brief Defines the ENET handler structure. */ -struct _lan91_handle { - lan91_callback_t callback; /*!< Callback function. */ - void *userData; /*!< Callback function parameter.*/ -}; - - -/******************************************************************************* - * functions - ******************************************************************************/ - -/** @brief Initialize the Lan91C111 ethernet controller. */ -void LAN91_init(void); - -/** @brief Read MAC address stored to external EEPROM. */ -void read_MACaddr(uint8_t *addr); - -/** - * @brief Sets the callback function. - * @param callback The callback function. - * @param userData The callback function parameter. - */ -void LAN91_SetCallback(lan91_callback_t callback, void *userData); - -/** @brief Send frame from given data buffer to Lan91C111 ethernet controller. */ -bool LAN91_send_frame(uint32_t *buff, uint32_t *size); - -/** @brief Receive frame from Lan91C111 ethernet controller to a given data buffer. */ -bool LAN91_receive_frame(uint32_t *buff, uint32_t *size); - -/** @brief Ethernet interrupt handler. */ -void ETHERNET_Handler(void); - -/** @brief Check Ethernet controller link status. */ -lan91_phy_status_t LAN91_GetLinkStatus(void); - - -/******************************************************************************* - * inline functions - ******************************************************************************/ - -/** @brief Select Bank Register of LAN91C111 controller. */ -static inline void LAN91_SelectBank(uint8_t bank) -{ - uint16_t current_bank = (LREG(uint16_t, BSR) & BSR_MASK); - if ((bank & BSR_MASK) != current_bank) { - LREG(uint16_t, BSR) = (bank & BSR_MASK); - } - -} - -/** @brief Resets the LAN91C111 controller. */ -static inline void LAN91_Reset(void) -{ - LAN91_SelectBank(0); - LREG(uint16_t, B0_RCR) = RCR_SOFT_RST; -} - -/** @brief Gets the LAN91C111 interrupt status flag. */ -static inline uint8_t LAN91_GetInterruptStatus(void) -{ - LAN91_SelectBank(2); - return LREG(uint8_t, B2_IST); -} - -/** @brief Get FIFO status if RxFIFO is empty. - * @return ture for RxFIFO is empty, false for RxFIFO it not empty. */ -static inline bool LAN91_RxFIFOEmpty(void) -{ - LAN91_SelectBank(2); - return ((LREG(uint8_t, B2_IST) & IST_RCV) == 0); - //return (( LREG (uint16_t, B2_FIFO) & FIFO_REMPTY ) == 1); -} - -/** @brief Get FIFO status if TxFIFO is empty. - * @return ture for TxFIFO is empty, false for TxFIFO it not empty. */ -static inline bool LAN91_TxFIFOEmpty(void) -{ - LAN91_SelectBank(2); - return ((LREG(uint8_t, B2_IST) & IST_TX_INT) == 0); -} - -/** @brief Clears the Ethernet interrupt status flag. */ -static inline void LAN91_ClearInterruptMasks(void) -{ - /* Mask off all interrupts */ - LAN91_SelectBank(2); - LREG(uint8_t, B2_MSK) = 0; -} - -static inline void LAN91_SetInterruptMasks(const uint8_t mask) -{ - /* Mask off all interrupts */ - LAN91_SelectBank(2); - LREG(uint8_t, B2_MSK) = mask; -} - -static inline uint8_t LAN91_GetInterruptMasks(void) -{ - /* Mask off all interrupts */ - LAN91_SelectBank(2); - return (LREG(uint8_t, B2_MSK)); -} - -/** @brief Enable Ethernet interrupt handler. */ -static inline void LAN91_SetHandler(void) -{ - //NVIC_EnableIRQ(ETHERNET_IRQn); -} - -#if defined(__cplusplus) -} -#endif diff --git a/bsp/freertos-platform/lwip_emac_netif.c b/bsp/freertos-platform/lwip_emac_netif.c new file mode 100644 index 0000000..69ef39a --- /dev/null +++ b/bsp/freertos-platform/lwip_emac_netif.c @@ -0,0 +1,264 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "lwip/opt.h" + +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/tcpip.h" +#include "lwip/ethip6.h" +#include "lwip/etharp.h" +#include "netif/ppp/pppoe.h" + +#include "lwip_memory_manager.h" +#include "lwip_stack.h" + +#define US_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000000U ) ) + +typedef struct pbuf pbuf_t; + +extern mdh_emac_t *cs300_emac_get_default_instance(void); + +#if LWIP_IGMP + +#include "lwip/igmp.h" +/** + * IPv4 address filtering setup. + * + * \param[in] netif the lwip network interface structure + * \param[in] group IPv4 group to modify + * \param[in] action + * \return ERR_OK or error code + */ +static err_t emac_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action) +{ + netif_context_t *netif_context_t = netif->state; + + switch (action) { + case NETIF_DEL_MAC_FILTER: + case NETIF_ADD_MAC_FILTER: { + uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; + uint8_t addr[6]; + addr[0] = LL_IP4_MULTICAST_ADDR_0; + addr[1] = LL_IP4_MULTICAST_ADDR_1; + addr[2] = LL_IP4_MULTICAST_ADDR_2; + addr[3] = group23 >> 16; + addr[4] = group23 >> 8; + addr[5] = group23; + + mdh_emac_status_t ret; + if (action == NETIF_ADD_MAC_FILTER) { + ret = mdh_emac_add_to_multicast_group(netif_context_t->emac, addr); + } else { + ret = mdh_emac_remove_from_multicast_group(netif_context_t->emac, addr); + } + + return (ret == MDH_EMAC_STATUS_NO_ERROR) ? ERR_OK : ERR_IF; + } + default: + return ERR_ARG; + } +} + +#endif + +#if LWIP_IPV6_MLD + +#include "lwip/mld6.h" +/** + * IPv6 address filtering setup. + * + * \param[in] netif the lwip network interface structure + * \param[in] group IPv6 group to modify + * \param[in] action + * \return ERR_OK or error code + */ +static err_t emac_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action) +{ + netif_context_t *netif_context_t = netif->state; + + switch (action) { + case NETIF_DEL_MAC_FILTER: + case NETIF_ADD_MAC_FILTER: { + uint32_t group32 = ntohl(group->addr[3]); + uint8_t addr[6]; + addr[0] = LL_IP6_MULTICAST_ADDR_0; + addr[1] = LL_IP6_MULTICAST_ADDR_1; + addr[2] = group32 >> 24; + addr[3] = group32 >> 16; + addr[4] = group32 >> 8; + addr[5] = group32; + + mdh_emac_status_t ret; + if (action == NETIF_ADD_MAC_FILTER) { + ret = mdh_emac_add_to_multicast_group(netif_context_t->emac, addr); + } else { + ret = mdh_emac_remove_from_multicast_group(netif_context_t->emac, addr); + } + + return (ret == MDH_EMAC_STATUS_NO_ERROR) ? ERR_OK : ERR_IF; + } + default: + return ERR_ARG; + } +} + +#endif + +/* this is called from ISR to let us know that input is ready*/ +static void ethernetif_input(mdh_emac_t *self, void *ctx, mdh_emac_receive_t status) +{ + if (status == MDH_EMAC_RECEIVE_DONE) { + netif_context_t *context = (netif_context_t *)(ctx); + signal_receive(context); + } +} + +static err_t ethernetif_output(struct netif *netif, struct pbuf *p) +{ + netif_context_t *context = netif->state; + mdh_network_stack_buffer_t *buf = (mdh_network_stack_buffer_t *)p; + + if (p->next) { + /* if it's not a single chunk, allocate a new buf to hold the whole payload */ + mdh_network_stack_memory_manager_t *memory_manager = lwip_mm_get_instance(); + + buf = mdh_network_stack_memory_manager_alloc_from_heap( + memory_manager, + mdh_network_stack_memory_manager_get_payload_len(memory_manager, buf), + mdh_emac_get_align(context->emac) + ); + + if (!buf) { + return ERR_IF; + } + + mdh_network_stack_memory_manager_copy(memory_manager, (mdh_network_stack_buffer_t *)p, buf); + } else { + /* Increase reference counter since lwip stores handle to pbuf and frees it after output */ + pbuf_ref(p); + } + + mdh_emac_status_t ret = mdh_emac_transmit(context->emac, buf); + + return (ret == MDH_EMAC_STATUS_NO_ERROR) ? ERR_OK : ERR_IF; +} + +static void ethernetif_sent(mdh_emac_t *self, void *ctx, mdh_emac_transfer_t status, const mdh_network_stack_buffer_t *buffer) +{ + if (status == MDH_EMAC_TRANSFER_ERROR) { + //@TODO react? + } + + mdh_network_stack_memory_manager_free(lwip_mm_get_instance(), buffer); +} + +static void emac_state_change(mdh_emac_t *self, void *ctx, mdh_emac_event_t event) +{ + /* this does not work because the handler fails to give us the context */ + netif_context_t *context = (netif_context_t *)(ctx); + if (event == MDH_EMAC_EVENT_LINK_STATUS_CHANGE) { + /* @TODO missing event types so we infer state based on netif state instead, + * if we were down this means we just went up */ + if (netif_is_link_up(&context->lwip_netif)) { + tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, &context->lwip_netif, 1); + } else { + tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, &context->lwip_netif, 1); + } + } +} + +void ethernetif_process_input(netif_context_t *context) +{ + struct pbuf *buf = mdh_network_stack_memory_manager_alloc_from_heap( + lwip_mm_get_instance(), + mdh_emac_get_mtu(context->emac), + mdh_emac_get_align(context->emac) + ); + + if (!buf) { + LWIP_DEBUGF(NETIF_DEBUG, ("Emac LWIP: pbuf allocation failed in ethernetif_process_input\n")); + return; + } + + mdh_emac_receive(context->emac, buf); + + /* pass all packets to ethernet_input, which decides what packets it supports */ + if (context->lwip_netif.input(buf, &context->lwip_netif) != ERR_OK) { + mdh_network_stack_memory_manager_free(lwip_mm_get_instance(), buf); + } +} + +err_t ethernetif_init(struct netif *netif) +{ + int err = ERR_OK; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + netif_context_t *context = netif->state; + mdh_emac_t *emac = cs300_emac_get_default_instance(); + context->emac = emac; + + /* Interface capabilities */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET; + + mdh_network_stack_memory_manager_t *memory_manager = lwip_mm_get_instance(); + + static const mdh_emac_callbacks_t cbks = { + .rx = ethernetif_input, .tx = ethernetif_sent, .event = emac_state_change + }; + + if (MDH_EMAC_STATUS_NO_ERROR != mdh_emac_power_up(context->emac, &cbks, memory_manager, context)) { + err = ERR_IF; + } + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->name[0] = 'e'; + netif->name[1] = 'n'; + + netif->mtu = mdh_emac_get_mtu(emac); + /* We have a default MAC address, so do don't force them to supply one */ + netif->hwaddr_len = mdh_emac_get_mac_addr_size(emac); + /* They may or may not update hwaddr with their address */ + mdh_emac_get_mac_addr(emac, netif->hwaddr); + /* Then we write back either what they gave us, or our default */ + mdh_emac_set_mac_addr(emac, netif->hwaddr); + +#if LWIP_IPV4 + netif->output = etharp_output; +#if LWIP_IGMP + netif->igmp_mac_filter = emac_igmp_mac_filter; + netif->flags |= NETIF_FLAG_IGMP; +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#if LWIP_IPV6_MLD + netif->mld_mac_filter = emac_mld_mac_filter; + netif->flags |= NETIF_FLAG_MLD6; +#else +// Would need to enable all multicasts here - no API in fsl_enet to do that +#error "IPv6 multicasts won't be received if LWIP_IPV6_MLD is disabled, breaking the system" +#endif +#endif + + netif->linkoutput = ethernetif_output; + + return err; +} + +/* Temporarily override definitions from MCU driver HAL as they don't work in NS + mode */ +void $Sub$$us_ticker_init(void) +{ +} + +void $Sub$$us_ticker_util_wait(uint32_t us) +{ + vTaskDelay(US_TO_TICKS(us)); +} \ No newline at end of file diff --git a/bsp/freertos-platform/lwip_emac_netif.h b/bsp/freertos-platform/lwip_emac_netif.h new file mode 100644 index 0000000..0b1e501 --- /dev/null +++ b/bsp/freertos-platform/lwip_emac_netif.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LWIP_EMAC_NETIF_H_ +#define LWIP_EMAC_NETIF_H_ + +#include +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "FreeRTOS.h" +#include "semphr.h" +#include "ethernet.h" +#include "emac_api.h" + +typedef enum connection_status_t { + CONNECTION_STATUS_DISCONNECTED, + CONNECTION_STATUS_CONNECTING, + CONNECTION_STATUS_GLOBAL_UP, + CONNECTION_STATUS_LOCAL_UP +} connection_status_t; + +typedef enum address_status_t { + ADDRESS_STATUS_HAS_ANY_ADDR = 1, + ADDRESS_STATUS_HAS_PREF_ADDR = 2, + ADDRESS_STATUS_HAS_BOTH_ADDR = 4 +} address_status_t; + +typedef struct netif_context_t { + mdh_emac_t *emac; + struct netif lwip_netif; + QueueHandle_t receive_semaphore; + connection_status_t connected; + bool dhcp_has_to_be_set; + bool dhcp_started; + uint8_t has_addr_state; +} netif_context_t; + +err_t ethernetif_init(struct netif *netif); +void ethernetif_process_input(netif_context_t *netif); + +#endif // LWIP_EMAC_NETIF_H_ \ No newline at end of file diff --git a/bsp/freertos-platform/lwip_memory_manager.c b/bsp/freertos-platform/lwip_memory_manager.c new file mode 100644 index 0000000..6199f88 --- /dev/null +++ b/bsp/freertos-platform/lwip_memory_manager.c @@ -0,0 +1,204 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "pbuf.h" +#include "lwipopts.h" +#include "hal/emac_api.h" +#include "lwip_memory_manager.h" + +static mdh_network_stack_buffer_t * +lwip_mm_alloc_from_heap(mdh_network_stack_memory_manager_t *const self, size_t size, size_t align); +static mdh_network_stack_buffer_t * +lwip_mm_alloc_from_static_pool(mdh_network_stack_memory_manager_t *const self, size_t size, size_t align); +static size_t lwip_mm_get_static_pool_alloc_unit(mdh_network_stack_memory_manager_t *const self, size_t align); +static void lwip_mm_free(mdh_network_stack_memory_manager_t *const self, const mdh_network_stack_buffer_t *buf); +static void lwip_mm_copy(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const source, + const mdh_network_stack_buffer_t *destination); +static size_t lwip_mm_copy_to_buf(mdh_network_stack_memory_manager_t *const self, + const void *const ptr, + size_t size, + const mdh_network_stack_buffer_t *buf); +static size_t lwip_mm_copy_from_buf(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const buf, + void *const ptr, + size_t size); +static void *lwip_mm_get_payload(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const buf); +static size_t lwip_mm_get_payload_len(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const buf); +static void lwip_mm_set_payload_len(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *buf, + size_t size); + +typedef struct pbuf pbuf_t; + +typedef struct lwip_mm_instance { + mdh_network_stack_memory_manager_t memory_manager; +} lwip_mm_instance; + +static const mdh_network_stack_memory_manager_vtable_t memory_manager_vtable = { + .alloc_from_heap = lwip_mm_alloc_from_heap, + .alloc_from_static_pool = lwip_mm_alloc_from_static_pool, + .get_static_pool_alloc_unit = lwip_mm_get_static_pool_alloc_unit, + .free = lwip_mm_free, + .copy = lwip_mm_copy, + .copy_to_buf = lwip_mm_copy_to_buf, + .copy_from_buf = lwip_mm_copy_from_buf, + .get_payload = lwip_mm_get_payload, + .get_payload_len = lwip_mm_get_payload_len, + .set_payload_len = lwip_mm_set_payload_len, +}; + +static lwip_mm_instance instance = {.memory_manager.vtable = &memory_manager_vtable}; + +static uint32_t count_total_align(uint32_t size, uint32_t align) +{ + uint32_t buffers = size / (LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - align); + if (size % (LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - align) != 0) { + buffers++; + } + return buffers * align; +} + +static void set_total_len(pbuf_t *pbuf) +{ + if (!pbuf->next) { + pbuf->tot_len = pbuf->len; + return; + } + + uint32_t total_len; + pbuf_t *pbuf_tailing; + + while (pbuf) { + total_len = pbuf->len; + + pbuf_tailing = pbuf->next; + while (pbuf_tailing) { + total_len += pbuf_tailing->len; + pbuf_tailing = pbuf_tailing->next; + } + + pbuf->tot_len = total_len; + pbuf = pbuf->next; + } +} + +static void align_memory(pbuf_t *pbuf, uint32_t align) +{ + if (!align) { + return; + } + + pbuf_t *pbuf_start = pbuf; + + while (pbuf) { + uint32_t remainder = (uint32_t)(pbuf->payload) % align; + if (remainder) { + uint32_t offset = align - remainder; + if (offset >= align) { + offset = align; + } + pbuf->payload = (char *)(pbuf->payload) + offset; + } + pbuf->len -= align; + pbuf = pbuf->next; + } + + // Correct total lengths + set_total_len(pbuf_start); +} + +mdh_network_stack_buffer_t * +lwip_mm_alloc_from_heap(mdh_network_stack_memory_manager_t *const self, size_t size, size_t align) +{ + pbuf_t *pbuf = pbuf_alloc(PBUF_RAW, size + align, PBUF_RAM); + if (pbuf == NULL) { + return NULL; + } + + align_memory(pbuf, align); + + return (mdh_network_stack_buffer_t *)(pbuf); +} + +mdh_network_stack_buffer_t * +lwip_mm_alloc_from_static_pool(mdh_network_stack_memory_manager_t *const self, size_t size, size_t align) +{ + uint32_t total_align = count_total_align(size, align); + + pbuf_t *pbuf = pbuf_alloc(PBUF_RAW, size + total_align, PBUF_POOL); + if (pbuf == NULL) { + return NULL; + } + + align_memory(pbuf, align); + + return (mdh_network_stack_buffer_t *)(pbuf); +} + +size_t lwip_mm_get_static_pool_alloc_unit(mdh_network_stack_memory_manager_t *const self, size_t align) +{ + uint32_t alloc_unit = LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - align; + return alloc_unit; +} + +void lwip_mm_free(mdh_network_stack_memory_manager_t *const self, const mdh_network_stack_buffer_t *buf) +{ + pbuf_free((pbuf_t *)(buf)); +} + +void lwip_mm_copy(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const source, + const mdh_network_stack_buffer_t *destination) +{ + pbuf_copy((pbuf_t *)(destination), (const pbuf_t *)(source)); +} + +size_t lwip_mm_copy_to_buf(mdh_network_stack_memory_manager_t *const self, + const void *const ptr, + size_t size, + const mdh_network_stack_buffer_t *buf) +{ + if (pbuf_take((pbuf_t *)(buf), ptr, size) == ERR_OK) { + return size; + } + return 0; +} + +size_t lwip_mm_copy_from_buf(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const buf, + void *const ptr, + size_t size) +{ + return pbuf_copy_partial((const pbuf_t *)(buf), ptr, size, 0); +} + +void *lwip_mm_get_payload(mdh_network_stack_memory_manager_t *const self, const mdh_network_stack_buffer_t *const buf) +{ + return ((const pbuf_t *)(buf))->payload; +} + +size_t lwip_mm_get_payload_len(mdh_network_stack_memory_manager_t *const self, + const mdh_network_stack_buffer_t *const buf) +{ + return ((const pbuf_t *)(buf))->len; +} + +void lwip_mm_set_payload_len(mdh_network_stack_memory_manager_t *const self, const mdh_network_stack_buffer_t *buf, + size_t size) +{ + pbuf_t *pbuf = (pbuf_t *)(buf); + pbuf->len = size; + set_total_len(pbuf); +}; + +mdh_network_stack_memory_manager_t *lwip_mm_get_instance(void) +{ + return &(instance.memory_manager); +} \ No newline at end of file diff --git a/bsp/freertos-platform/lwip_memory_manager.h b/bsp/freertos-platform/lwip_memory_manager.h new file mode 100644 index 0000000..44bc87f --- /dev/null +++ b/bsp/freertos-platform/lwip_memory_manager.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LWIP_MEMORY_MANAGER_H_ +#define LWIP_MEMORY_MANAGER_H_ + +#include "network_stack_memory_manager.h" + +mdh_network_stack_memory_manager_t *lwip_mm_get_instance(void); + +#endif // LWIP_MEMORY_MANAGER_H_ diff --git a/bsp/freertos-platform/lwip_stack.c b/bsp/freertos-platform/lwip_stack.c new file mode 100644 index 0000000..1cc5b71 --- /dev/null +++ b/bsp/freertos-platform/lwip_stack.c @@ -0,0 +1,286 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "FreeRTOS.h" +#include "lwipopts.h" +#include "semphr.h" +#include "lwip/err.h" +#include "lwip/dhcp.h" +#include "lwip/tcpip.h" +#include "lwip/netif.h" +#include "lwip_emac_netif.h" +#include "lwip_memory_manager.h" +#include "lwip_stack.h" +#include "FreeRTOS_IP.h" + +/* secure sockets requires errno to communicate error codes */ +int errno = 0; + +static err_t set_dhcp(struct netif *netif) +{ + netif_context_t *context = (netif_context_t *)(netif->state); + +#if LWIP_DHCP + if (context->dhcp_has_to_be_set) { + err_t err = dhcp_start(netif); + if (err) { + context->connected = CONNECTION_STATUS_DISCONNECTED; + return ERR_IF; + } + + context->dhcp_has_to_be_set = false; + context->dhcp_started = true; + } +#endif + + return ERR_OK; +} + +static const ip_addr_t *get_ipv4_addr(const struct netif *netif) +{ +#if LWIP_IPV4 + if (!netif_is_up(netif)) { + return NULL; + } + + if (!ip4_addr_isany(netif_ip4_addr(netif))) { + return netif_ip_addr4(netif); + } +#endif + return NULL; +} + +static const ip_addr_t *get_ipv6_addr(const struct netif *netif) +{ +#if LWIP_IPV6 + if (!netif_is_up(netif)) { + return NULL; + } + + for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + + for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + return netif_ip_addr6(netif, i); + } + } +#endif + return NULL; +} + +static const ip_addr_t *get_ip_addr(bool any_addr, const struct netif *netif) +{ + const ip_addr_t *pref_ip_addr = 0; + const ip_addr_t *npref_ip_addr = 0; + +#if LWIP_IPV4 && LWIP_IPV6 +#if IP_VERSION_PREF == PREF_IPV4 + pref_ip_addr = get_ipv4_addr(netif); + npref_ip_addr = get_ipv6_addr(netif); +#else + pref_ip_addr = get_ipv6_addr(netif); + npref_ip_addr = get_ipv4_addr(netif); +#endif +#elif LWIP_IPV6 + pref_ip_addr = get_ipv6_addr(netif); +#elif LWIP_IPV4 + pref_ip_addr = get_ipv4_addr(netif); +#endif + + if (pref_ip_addr) { + return pref_ip_addr; + } else if (npref_ip_addr && any_addr) { + return npref_ip_addr; + } + + return NULL; +} + +static void netif_link_irq(struct netif *netif) +{ + netif_context_t *context = (netif_context_t *)(netif->state); + + if (netif_is_link_up(netif) && context->connected == CONNECTION_STATUS_CONNECTING) { + netif_set_up(netif); + } else { + if (netif_is_up(netif)) { + context->connected = CONNECTION_STATUS_CONNECTING; + } + netif_set_down(netif); + } +} + +extern void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ); + +static void netif_status_irq(struct netif *netif) +{ + netif_context_t *context = (netif_context_t *)(netif->state); + + if (netif_is_up(netif) && netif_is_link_up(netif)) { + if (context->dhcp_has_to_be_set) { + set_dhcp(netif); + } else { + if (!(context->has_addr_state & ADDRESS_STATUS_HAS_ANY_ADDR) && get_ip_addr(true, netif)) { + context->has_addr_state |= ADDRESS_STATUS_HAS_ANY_ADDR; + } +#if PREF_ADDR_TIMEOUT + if (!(context->has_addr_state & ADDRESS_STATUS_HAS_PREF_ADDR) && get_ip_addr(false, netif)) { + context->has_addr_state |= ADDRESS_STATUS_HAS_PREF_ADDR; + } +#endif +#if BOTH_ADDR_TIMEOUT + if (!(context->has_addr_state & ADDRESS_STATUS_HAS_BOTH_ADDR) && get_ipv4_addr(netif) && get_ipv6_addr(netif)) { + context->has_addr_state |= ADDRESS_STATUS_HAS_BOTH_ADDR; + } +#endif + if (context->has_addr_state & ADDRESS_STATUS_HAS_ANY_ADDR) { + context->connected = CONNECTION_STATUS_GLOBAL_UP; +#if LWIP_IPV6 + if (ip_addr_islinklocal(get_ipv6_addr(netif))) { + context->connected = CONNECTION_STATUS_LOCAL_UP; + } +#endif + vApplicationIPNetworkEventHook(eNetworkUp); + } + } + } else if (!netif_is_up(netif) && netif_is_link_up(netif)) { + context->connected = CONNECTION_STATUS_DISCONNECTED; + + vApplicationIPNetworkEventHook(eNetworkDown); + } +} + +static err_t ethernet_interface_bringup(netif_context_t *context) +{ + if (context->connected == CONNECTION_STATUS_GLOBAL_UP) { + return ERR_ISCONN; + } else if (context->connected == CONNECTION_STATUS_CONNECTING) { + return ERR_INPROGRESS; + } + + context->connected = CONNECTION_STATUS_CONNECTING; + context->dhcp_has_to_be_set = true; + + return ERR_OK; +} + +static err_t ethernet_interface_bringdown(netif_context_t *context) +{ + // Check if we've connected + if (context->connected == CONNECTION_STATUS_DISCONNECTED) { + return ERR_CONN; + } + +#if LWIP_DHCP + // Disconnect from the network + if (context->dhcp_started) { + dhcp_release(&context->lwip_netif); + dhcp_stop(&context->lwip_netif); + context->dhcp_started = false; + context->dhcp_has_to_be_set = false; + } +#endif + + netif_set_down(&context->lwip_netif); + +#if LWIP_IPV6 + mbed_lwip_clear_ipv6_addresses(&context->lwip_netif); +#endif +#if LWIP_IPV4 + ip_addr_set_zero(&(context->lwip_netif.ip_addr)); + ip_addr_set_zero(&(context->lwip_netif.netmask)); + ip_addr_set_zero(&(context->lwip_netif.gw)); +#endif + + context->connected = CONNECTION_STATUS_DISCONNECTED; + + return ERR_OK; +} + +static err_t ethernet_interface_init(netif_context_t *context) +{ + struct netif *n = netif_add(&context->lwip_netif, +#if LWIP_IPV4 + 0, + 0, + 0, +#endif + context /* state */, + ðernetif_init, + tcpip_input); + + if (!n) { + return ERR_IF; + } + + netif_set_link_callback(&context->lwip_netif, &netif_link_irq); + netif_set_status_callback(&context->lwip_netif, &netif_status_irq); + + netif_set_default(&context->lwip_netif); + + return ERR_OK; +} + +static void tcpip_init_done(void *arg) +{ + SemaphoreHandle_t xSemaphore = *((SemaphoreHandle_t *)arg); + xSemaphoreGive(xSemaphore); +} + +static err_t lwip_network_init(netif_context_t *context) +{ + // it's safe to create them on the stack since they are only used until we exit this function + StaticSemaphore_t semaphore_buffer; + SemaphoreHandle_t semaphore; + + semaphore = xSemaphoreCreateBinaryStatic(&semaphore_buffer); + + /* Initialise LwIP, providing the callback function and callback semaphore */ + tcpip_init(tcpip_init_done, &semaphore); + + xSemaphoreTake(semaphore, portMAX_DELAY); + + return ERR_OK; +} + +void signal_receive(netif_context_t *context) +{ + xQueueGiveFromISR(context->receive_semaphore, NULL); +} + +void net_task(void *pvParameters) +{ + printf("Net task started\r\n"); + + netif_context_t context = { 0 }; + + context.receive_semaphore = xQueueCreate(1, 0); + + lwip_network_init(&context); + ethernet_interface_init(&context); + ethernet_interface_bringup(&context); + + /* @TODO: emac is missing this event so we need to trigger it ourselves*/ + tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, &context.lwip_netif, 1); + + /* Initialise the RTOS's TCP/IP stack. The tasks that use the network are created in the + * vApplicationIPNetworkEventHook() The hook function is called when the network connects. */ + + while (1) + { + /* tick lwip */ + sys_check_timeouts(); + + /* handle input */ + if (xQueueSemaphoreTake(context.receive_semaphore, 0)) { + ethernetif_process_input(&context); + } + } +} diff --git a/bsp/freertos-platform/lwip_stack.h b/bsp/freertos-platform/lwip_stack.h new file mode 100644 index 0000000..a6dc4cd --- /dev/null +++ b/bsp/freertos-platform/lwip_stack.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LWIP_STACK_H_ +#define LWIP_STACK_H_ + +#include "lwip_emac_netif.h" + +/* Cause the stack to read the input buffer */ +void signal_receive(netif_context_t *context); + +/* free rtos task to initialise and run the LWIP stack */ +void net_task(void *pvParameters); + +#endif // LWIP_STACK_H_ diff --git a/bsp/freertos-platform/lwipopts.h b/bsp/freertos-platform/lwipopts.h new file mode 100644 index 0000000..75a2ca4 --- /dev/null +++ b/bsp/freertos-platform/lwipopts.h @@ -0,0 +1,11 @@ +/* Copyright (c) 2021 Arm Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "lwipopts_freertos.h" + +#define LWIP_NETIF_LINK_CALLBACK 1 +#define MEM_ALIGNMENT 4U + +#undef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 1U) diff --git a/bsp/interface/include/psa/README.md b/bsp/interface/include/psa/README.md deleted file mode 100644 index d47b9a6..0000000 --- a/bsp/interface/include/psa/README.md +++ /dev/null @@ -1 +0,0 @@ -These files are copied from interface/include/psa due to inclusion filename clash diff --git a/bsp/interface/include/psa/client.h b/bsp/interface/include/psa/client.h deleted file mode 100644 index 7aee1e5..0000000 --- a/bsp/interface/include/psa/client.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __PSA_CLIENT_H__ -#define __PSA_CLIENT_H__ - -#include -#include - -#include "psa/error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef IOVEC_LEN -#define IOVEC_LEN(arr) ((uint32_t)(sizeof(arr)/sizeof(arr[0]))) -#endif - -/*********************** PSA Client Macros and Types *************************/ - -/** - * The version of the PSA Framework API that is being used to build the calling - * firmware. Only part of features of FF-M v1.1 have been implemented. FF-M v1.1 - * is compatible with v1.0. - */ -#define PSA_FRAMEWORK_VERSION (0x0101u) - -/** - * Return value from psa_version() if the requested RoT Service is not present - * in the system. - */ -#define PSA_VERSION_NONE (0u) - -/** - * The zero-value null handle can be assigned to variables used in clients and - * RoT Services, indicating that there is no current connection or message. - */ -#define PSA_NULL_HANDLE ((psa_handle_t)0) - -/** - * Tests whether a handle value returned by psa_connect() is valid. - */ -#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0) - -/** - * Converts the handle value returned from a failed call psa_connect() into - * an error code. - */ -#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle)) - -/** - * Maximum number of input and output vectors for a request to psa_call(). - */ -#define PSA_MAX_IOVEC (4u) - -/** - * An IPC message type that indicates a generic client request. - */ -#define PSA_IPC_CALL (0) - -typedef int32_t psa_handle_t; - -/** - * A read-only input memory region provided to an RoT Service. - */ -typedef struct psa_invec { - const void *base; /*!< the start address of the memory buffer */ - size_t len; /*!< the size in bytes */ -} psa_invec; - -/** - * A writable output memory region provided to an RoT Service. - */ -typedef struct psa_outvec { - void *base; /*!< the start address of the memory buffer */ - size_t len; /*!< the size in bytes */ -} psa_outvec; - -/*************************** PSA Client API **********************************/ - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return version The version of the PSA Framework implementation - * that is providing the runtime services to the - * caller. The major and minor version are encoded - * as follows: - * \arg version[15:8] -- major version number. - * \arg version[7:0] -- minor version number. - */ -uint32_t psa_framework_version(void); - -/** - * \brief Retrieve the version of an RoT Service or indicate that it is not - * present on this system. - * - * \param[in] sid ID of the RoT Service to query. - * - * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the - * caller is not permitted to access the service. - * \retval > 0 The version of the implemented RoT Service. - */ -uint32_t psa_version(uint32_t sid); - -/** - * \brief Connect to an RoT Service by its SID. - * - * \param[in] sid ID of the RoT Service to connect to. - * \param[in] version Requested version of the RoT Service. - * - * \retval > 0 A handle for the connection. - * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the - * connection. - * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the - * connection at the moment. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg The RoT Service ID is not present. - * \arg The RoT Service version is not supported. - * \arg The caller is not allowed to access the RoT - * service. - */ -psa_handle_t psa_connect(uint32_t sid, uint32_t version); - -/** - * \brief Call an RoT Service on an established connection. - * - * \note FF-M 1.0 proposes 6 parameters for psa_call but the secure gateway ABI - * support at most 4 parameters. TF-M chooses to encode 'in_len', - * 'out_len', and 'type' into a 32-bit integer to improve efficiency. - * Compared with struct-based encoding, this method saves extra memory - * check and memory copy operation. The disadvantage is that the 'type' - * range has to be reduced into a 16-bit integer. So with this encoding, - * the valid range for 'type' is 0-32767. - * - * \param[in] handle A handle to an established connection. - * \param[in] type The request type. - * Must be zero( \ref PSA_IPC_CALL) or positive. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in] in_len Number of input \ref psa_invec structures. - * \param[in,out] out_vec Array of output \ref psa_outvec structures. - * \param[in] out_len Number of output \ref psa_outvec structures. - * - * \retval >=0 RoT Service-specific status value. - * \retval <0 RoT Service-specific error code. - * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the - * RoT Service. The call is a PROGRAMMER ERROR if - * one or more of the following are true: - * \arg An invalid handle was passed. - * \arg The connection is already handling a request. - * \arg type < 0. - * \arg An invalid memory reference was provided. - * \arg in_len + out_len > PSA_MAX_IOVEC. - * \arg The message is unrecognized by the RoT - * Service or incorrectly formatted. - */ -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); - -/** - * \brief Close a connection to an RoT Service. - * - * \param[in] handle A handle to an established connection, or the - * null handle. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg An invalid handle was provided that is not - * the null handle. - * \arg The connection is currently handling a - * request. - */ -void psa_close(psa_handle_t handle); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_CLIENT_H__ */ diff --git a/bsp/interface/include/psa/crypto_client_struct.h b/bsp/interface/include/psa/crypto_client_struct.h deleted file mode 100644 index bf95c98..0000000 --- a/bsp/interface/include/psa/crypto_client_struct.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2020-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_client_struct.h - * - * \brief PSA cryptography client key attribute definitions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of some data structures with - * PSA crypto client specific definitions. This is for implementations - * with isolation between the Client applications and the Crypto - * Server module, it is expected that the front-end and the back-end - * would have different versions of the data structure. - */ -#ifndef PSA_CRYPTO_CLIENT_STRUCT_H -#define PSA_CRYPTO_CLIENT_STRUCT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the client view of the `key_attributes` structure. Only - * fields which need to be set by the PSA crypto client are present. - * The PSA crypto service will maintain a different version of the - * data structure internally. */ -struct psa_client_key_attributes_s -{ - uint16_t type; - uint16_t bits; - uint32_t lifetime; - psa_key_id_t id; - uint32_t usage; - uint32_t alg; -}; - -#define PSA_CLIENT_KEY_ATTRIBUTES_INIT {0, 0, 0, 0, 0, 0} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_CLIENT_STRUCT_H */ diff --git a/bsp/interface/include/psa/crypto_compat.h b/bsp/interface/include/psa/crypto_compat.h deleted file mode 100644 index 17dcee2..0000000 --- a/bsp/interface/include/psa/crypto_compat.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_compat.h - * - * \brief PSA cryptography module: Backward compatibility aliases - * - * This header declares alternative names for macro and functions. - * New application code should not use these names. - * These names may be removed in a future version of Mbed Crypto. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - */ - -#ifndef PSA_CRYPTO_COMPAT_H -#define PSA_CRYPTO_COMPAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * To support both openless APIs and psa_open_key() temporarily, define - * psa_key_handle_t to be equal to psa_key_id_t. Do not mark the - * type and its utility macros and functions deprecated yet. This will be done - * in a subsequent phase. - */ -typedef psa_key_id_t psa_key_handle_t; - -/** Check whether an handle is null. - * - * \param handle Handle - * - * \return Non-zero if the handle is null, zero otherwise. - */ -static inline int psa_key_handle_is_null(psa_key_handle_t handle) -{ - return(handle == 0); -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/* - * Mechanism for declaring deprecated values - */ -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) -#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_PSA_DEPRECATED -#endif - -typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; -typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; -typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; -typedef MBEDTLS_PSA_DEPRECATED psa_ecc_family_t mbedtls_deprecated_psa_ecc_family_t; -typedef MBEDTLS_PSA_DEPRECATED psa_dh_family_t mbedtls_deprecated_psa_dh_family_t; -typedef MBEDTLS_PSA_DEPRECATED psa_ecc_family_t psa_ecc_curve_t; -typedef MBEDTLS_PSA_DEPRECATED psa_dh_family_t psa_dh_group_t; -typedef MBEDTLS_PSA_DEPRECATED psa_algorithm_t mbedtls_deprecated_psa_algorithm_t; - -#define PSA_KEY_TYPE_GET_CURVE PSA_KEY_TYPE_ECC_GET_FAMILY -#define PSA_KEY_TYPE_GET_GROUP PSA_KEY_TYPE_DH_GET_FAMILY - -#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ - ( (mbedtls_deprecated_##type) ( value ) ) - -/* - * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) - */ -#define PSA_ERROR_UNKNOWN_ERROR \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) -#define PSA_ERROR_OCCUPIED_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) -#define PSA_ERROR_EMPTY_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) -#define PSA_ERROR_INSUFFICIENT_CAPACITY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) -#define PSA_ERROR_TAMPERING_DETECTED \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) - -/* - * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_KEY_USAGE_SIGN \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) -#define PSA_KEY_USAGE_VERIFY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) - -/* - * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) -#define PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) ) -#define PSA_BLOCK_CIPHER_BLOCK_SIZE( type ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) ) -#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE ) -#define PSA_HASH_SIZE( alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_HASH_LENGTH( alg ) ) -#define PSA_MAC_FINAL_SIZE( key_type, key_bits, alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_MAC_LENGTH( key_type, key_bits, alg ) ) -#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE ) -/* - * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) - */ -MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_sign( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ); - -MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_verify( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ); - - -/* - * Size-specific elliptic curve families. - */ -#define PSA_ECC_CURVE_SECP160K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) -#define PSA_ECC_CURVE_SECP192K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) -#define PSA_ECC_CURVE_SECP224K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) -#define PSA_ECC_CURVE_SECP256K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) -#define PSA_ECC_CURVE_SECP160R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP192R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP224R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP256R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP384R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP521R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP160R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R2 ) -#define PSA_ECC_CURVE_SECT163K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT233K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT239K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT283K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT409K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT571K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT163R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT193R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT233R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT283R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT409R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT571R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT163R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2 ) -#define PSA_ECC_CURVE_SECT193R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2 ) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_CURVE25519 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY ) -#define PSA_ECC_CURVE_CURVE448 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY ) - -/* - * Curves that changed name due to PSA specification. - */ -#define PSA_ECC_CURVE_SECP_K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) -#define PSA_ECC_CURVE_SECP_R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) -#define PSA_ECC_CURVE_SECP_R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R2 ) -#define PSA_ECC_CURVE_SECT_K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) -#define PSA_ECC_CURVE_SECT_R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) -#define PSA_ECC_CURVE_SECT_R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2 ) -#define PSA_ECC_CURVE_BRAINPOOL_P_R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_MONTGOMERY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY ) - -/* - * Finite-field Diffie-Hellman families. - */ -#define PSA_DH_GROUP_FFDHE2048 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) -#define PSA_DH_GROUP_FFDHE3072 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) -#define PSA_DH_GROUP_FFDHE4096 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) -#define PSA_DH_GROUP_FFDHE6144 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) -#define PSA_DH_GROUP_FFDHE8192 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) - -/* - * Diffie-Hellman families that changed name due to PSA specification. - */ -#define PSA_DH_GROUP_RFC7919 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) -#define PSA_DH_GROUP_CUSTOM \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_CUSTOM ) - -/* - * Deprecated PSA Crypto stream cipher algorithms (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ALG_ARC4 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_algorithm_t, PSA_ALG_STREAM_CIPHER) -#define PSA_ALG_CHACHA20 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_algorithm_t, PSA_ALG_STREAM_CIPHER) - -/* - * Renamed AEAD tag length macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH( aead_alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( psa_algorithm_t, PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( aead_alg ) ) -#define PSA_ALG_AEAD_WITH_TAG_LENGTH( aead_alg, tag_length ) \ - MBEDTLS_DEPRECATED_CONSTANT( psa_algorithm_t, PSA_ALG_AEAD_WITH_SHORTENED_TAG( aead_alg, tag_length ) ) - - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -/** Open a handle to an existing persistent key. - * - * Open a handle to a persistent key. A key is persistent if it was created - * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key - * always has a nonzero key identifier, set with psa_set_key_id() when - * creating the key. Implementations may provide additional pre-provisioned - * keys that can be opened with psa_open_key(). Such keys have an application - * key identifier in the vendor range, as documented in the description of - * #psa_key_id_t. - * - * The application must eventually close the handle with psa_close_key() or - * psa_destroy_key() to release associated resources. If the application dies - * without calling one of these functions, the implementation should perform - * the equivalent of a call to psa_close_key(). - * - * Some implementations permit an application to open the same key multiple - * times. If this is successful, each call to psa_open_key() will return a - * different key handle. - * - * \note This API is not part of the PSA Cryptography API Release 1.0.0 - * specification. It was defined in the 1.0 Beta 3 version of the - * specification but was removed in the 1.0.0 released version. This API is - * kept for the time being to not break applications relying on it. It is not - * deprecated yet but will be in the near future. - * - * \note Applications that rely on opening a key multiple times will not be - * portable to implementations that only permit a single key handle to be - * opened. See also :ref:\`key-handles\`. - * - * - * \param id The persistent identifier of the key. - * \param[out] key On success, a handle to the key. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the key. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * The implementation does not have sufficient resources to open the - * key. This can be due to reaching an implementation limit on the - * number of open keys, the number of open key handles, or available - * memory. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * There is no persistent key with key identifier \p id. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is not a valid persistent key identifier. - * \retval #PSA_ERROR_NOT_PERMITTED - * The specified key exists, but the application does not have the - * permission to access it. Note that this specification does not - * define any way to create such a key, but it may be possible - * through implementation-specific means. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_DATA_INVALID - * \retval #PSA_ERROR_DATA_CORRUPT - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_open_key(psa_key_id_t id, - psa_key_id_t *key); - -/** Close a key handle. - * - * If the handle designates a volatile key, this will destroy the key material - * and free all associated resources, just like psa_destroy_key(). - * - * If this is the last open handle to a persistent key, then closing the handle - * will free all resources associated with the key in volatile memory. The key - * data in persistent storage is not affected and can be opened again later - * with a call to psa_open_key(). - * - * Closing the key handle makes the handle invalid, and the key handle - * must not be used again by the application. - * - * \note This API is not part of the PSA Cryptography API Release 1.0.0 - * specification. It was defined in the 1.0 Beta 3 version of the - * specification but was removed in the 1.0.0 released version. This API is - * kept for the time being to not break applications relying on it. It is not - * deprecated yet but will be in the near future. - * - * \note If the key handle was used to set up an active - * :ref:\`multipart operation \`, then closing the - * key handle can cause the multipart operation to fail. Applications should - * maintain the key handle until after the multipart operation has finished. - * - * \param key The key to close. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle or \c 0. It is now closed. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_close_key(psa_key_id_t key); - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/bsp/interface/include/psa/error.h b/bsp/interface/include/psa/error.h deleted file mode 100644 index e8903f0..0000000 --- a/bsp/interface/include/psa/error.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** - * \file psa/error.h - * \brief Standard error codes for the SPM and RoT Services - */ - -#ifndef __PSA_ERROR_H__ -#define __PSA_ERROR_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* If #PSA_SUCCESS is already defined, it means that #psa_status_t - * is also defined in an external header, so prevent its multiple - * definition. - */ -#ifndef PSA_SUCCESS -typedef int32_t psa_status_t; -#endif - -#define PSA_SUCCESS ((psa_status_t)0) -#define PSA_SUCCESS_REBOOT ((psa_status_t)1) -#define PSA_SUCCESS_RESTART ((psa_status_t)2) - -#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) -#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) -#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) -#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DEPENDENCY_NEEDED ((psa_status_t)-156) -#define PSA_ERROR_CURRENTLY_INSTALLING ((psa_status_t)-157) -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_ERROR_H__ */ diff --git a/bsp/interface/include/psa/internal_trusted_storage.h b/bsp/interface/include/psa/internal_trusted_storage.h deleted file mode 100644 index 3920bc9..0000000 --- a/bsp/interface/include/psa/internal_trusted_storage.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** This file describes the PSA Internal Trusted Storage API -*/ - -#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H -#define PSA_INTERNAL_TRUSTED_STORAGE_H - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" { -#endif -#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the - * PSA ITS API - */ -#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the - * PSA ITS API - */ -// This version of the header file is associated with 1.0 final release. - -/** - * \brief Create a new, or modify an existing, uid/value pair - * - * Stores data in the internal storage. - * - * \param[in] uid The identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the - * provided `uid` value was already - * created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or - * more of the flags provided in - * `create_flags` is not supported or is - * not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there - * was insufficient space on the - * storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one - * of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - */ -psa_status_t psa_its_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve data associated with a provided UID - * - * Retrieves up to `data_size` bytes of the data associated with `uid`, starting - * at `data_offset` bytes from the beginning of the data. Upon successful - * completion, the data will be placed in the `p_data` buffer, which must be at - * least `data_size` bytes in size. The length of the data returned will be in - * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will - * be set to zero. - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_size The amount of data requested - * \param[out] p_data On success, the buffer where the data will - * be placed - * \param[out] p_data_length On success, this will contain size of the data - * placed in `p_data` - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the - * provided `uid` value was not found in - * the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided arguments (`p_data`, - * `p_data_length`) is invalid, for example - * is `NULL` or references memory the - * caller cannot access. In addition, this - * can also happen if `data_offset` is - * larger than the size of the data - * associated with `uid` - */ -psa_status_t psa_its_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * Retrieves the metadata stored for a given `uid` as a `psa_storage_info_t` - * structure. - * - * \param[in] uid The `uid` value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will - * be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided pointers(`p_info`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - */ -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided uid and its associated data from the storage - * - * Deletes the data from internal storage. - * - * \param[in] uid The `uid` value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the given arguments were invalid (null - * pointer, wrong flags and so on) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided - * uid value was created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - */ -psa_status_t psa_its_remove(psa_storage_uid_t uid); - -#ifdef __cplusplus -} -#endif - -#endif // PSA_INTERNAL_TRUSTED_STORAGE_H diff --git a/bsp/interface/include/psa/service.h b/bsp/interface/include/psa/service.h deleted file mode 100644 index 12efd2e..0000000 --- a/bsp/interface/include/psa/service.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __PSA_SERVICE_H__ -#define __PSA_SERVICE_H__ - -#include -#include - -#include "psa/error.h" -#include "psa/client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/********************** PSA Secure Partition Macros and Types ****************/ - -/** - * A timeout value that requests a polling wait operation. - */ -#define PSA_POLL (0x00000000u) - -/** - * A timeout value that requests a blocking wait operation. - */ -#define PSA_BLOCK (0x80000000u) - -/** - * A mask value that includes all Secure Partition signals. - */ -#define PSA_WAIT_ANY (0xFFFFFFFFu) - -/** - * The signal number for the Secure Partition doorbell. - */ -#define PSA_DOORBELL (0x00000008u) - -/* PSA message types */ -/* An IPC message type that indicates a new connection. */ -#define PSA_IPC_CONNECT (-1) -/* An IPC message type that indicates the end of a connection. */ -#define PSA_IPC_DISCONNECT (-2) - -/* FLIH return types */ -#define PSA_FLIH_NO_SIGNAL ((psa_flih_result_t) 0) -#define PSA_FLIH_SIGNAL ((psa_flih_result_t) 1) - -/* Store a set of one or more Secure Partition signals */ -typedef uint32_t psa_signal_t; - -/* A type used to temporarily store a previous interrupt state. */ -typedef uint32_t psa_irq_status_t; - -/* The type of the return value from an FLIH function */ -typedef uint32_t psa_flih_result_t; - -/** - * Describe a message received by an RoT Service after calling \ref psa_get(). - */ -typedef struct psa_msg_t { - int32_t type; /* One of the following values: - * \ref PSA_IPC_CONNECT - * >= 0 - * \ref PSA_IPC_DISCONNECT - */ - psa_handle_t handle; /* A reference generated by the SPM to the - * message returned by psa_get(). - */ - int32_t client_id; /* Partition ID of the sender of the message */ - void *rhandle; /* Be useful for binding a connection to some - * application-specific data or function - * pointer within the RoT Service - * implementation. - */ - size_t in_size[PSA_MAX_IOVEC]; /* Provide the size of each client input - * vector in bytes. - */ - size_t out_size[PSA_MAX_IOVEC];/* Provide the size of each client output - * vector in bytes. - */ -} psa_msg_t; - -/************************* PSA Secure Partition API **************************/ - -/** - * \brief Return the Secure Partition interrupt signals that have been asserted - * from a subset of signals provided by the caller. - * - * \param[in] signal_mask A set of signals to query. Signals that are not - * in this set will be ignored. - * \param[in] timeout Specify either blocking \ref PSA_BLOCK or - * polling \ref PSA_POLL operation. - * - * \retval >0 At least one signal is asserted. - * \retval 0 No signals are asserted. This is only seen when - * a polling timeout is used. - */ -psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout); - -/** - * \brief Retrieve the message which corresponds to a given RoT Service signal - * and remove the message from the RoT Service queue. - * - * \param[in] signal The signal value for an asserted RoT Service. - * \param[out] msg Pointer to \ref psa_msg_t object for receiving - * the message. - * - * \retval PSA_SUCCESS Success, *msg will contain the delivered - * message. - * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered. - * \retval "PROGRAMMER ERROR" The call is invalid because one or more of the - * following are true: - * \arg signal has more than a single bit set. - * \arg signal does not correspond to an RoT Service. - * \arg The RoT Service signal is not currently - * asserted. - * \arg The msg pointer provided is not a valid memory - * reference. - */ -psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg); - -/** - * \brief Associate some RoT Service private data with a client connection. - * - * \param[in] msg_handle Handle for the client's message. - * \param[in] rhandle Reverse handle allocated by the RoT Service. - * - * \retval void Success, rhandle will be provided with all - * subsequent messages delivered on this - * connection. - * \retval "PROGRAMMER ERROR" msg_handle is invalid. - */ -void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle); - -/** - * \brief Read a message parameter or part of a message parameter from a client - * input vector. - * - * \param[in] msg_handle Handle for the client's message. - * \param[in] invec_idx Index of the input vector to read from. Must be - * less than \ref PSA_MAX_IOVEC. - * \param[out] buffer Buffer in the Secure Partition to copy the - * requested data to. - * \param[in] num_bytes Maximum number of bytes to be read from the - * client input vector. - * - * \retval >0 Number of bytes copied. - * \retval 0 There was no remaining data in this input - * vector. - * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the - * following are true: - * \arg msg_handle is invalid. - * \arg msg_handle does not refer to a - * \ref PSA_IPC_CALL message. - * \arg invec_idx is equal to or greater than - * \ref PSA_MAX_IOVEC. - * \arg the memory reference for buffer is invalid or - * not writable. - */ -size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, - void *buffer, size_t num_bytes); - -/** - * \brief Skip over part of a client input vector. - * - * \param[in] msg_handle Handle for the client's message. - * \param[in] invec_idx Index of input vector to skip from. Must be - * less than \ref PSA_MAX_IOVEC. - * \param[in] num_bytes Maximum number of bytes to skip in the client - * input vector. - * - * \retval >0 Number of bytes skipped. - * \retval 0 There was no remaining data in this input - * vector. - * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the - * following are true: - * \arg msg_handle is invalid. - * \arg msg_handle does not refer to a request - * message. - * \arg invec_idx is equal to or greater than - * \ref PSA_MAX_IOVEC. - */ -size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes); - -/** - * \brief Write a message response to a client output vector. - * - * \param[in] msg_handle Handle for the client's message. - * \param[out] outvec_idx Index of output vector in message to write to. - * Must be less than \ref PSA_MAX_IOVEC. - * \param[in] buffer Buffer with the data to write. - * \param[in] num_bytes Number of bytes to write to the client output - * vector. - * - * \retval void Success - * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the - * following are true: - * \arg msg_handle is invalid. - * \arg msg_handle does not refer to a request - * message. - * \arg outvec_idx is equal to or greater than - * \ref PSA_MAX_IOVEC. - * \arg The memory reference for buffer is invalid. - * \arg The call attempts to write data past the end - * of the client output vector. - */ -void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, - const void *buffer, size_t num_bytes); - -/** - * \brief Complete handling of a specific message and unblock the client. - * - * \param[in] msg_handle Handle for the client's message. - * \param[in] status Message result value to be reported to the - * client. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the - * following are true: - * \arg msg_handle is invalid. - * \arg An invalid status code is specified for the - * type of message. - */ -void psa_reply(psa_handle_t msg_handle, psa_status_t status); - -/** - * \brief Send a PSA_DOORBELL signal to a specific Secure Partition. - * - * \param[in] partition_id Secure Partition ID of the target partition. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" partition_id does not correspond to a Secure - * Partition. - */ -void psa_notify(int32_t partition_id); - -/** - * \brief Clear the PSA_DOORBELL signal. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The Secure Partition's doorbell signal is not - * currently asserted. - */ -void psa_clear(void); - -/** - * \brief Inform the SPM that an interrupt has been handled (end of interrupt). - * - * \param[in] irq_signal The interrupt signal that has been processed. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The call is invalid, one or more of the - * following are true: - * \arg irq_signal is not an interrupt signal. - * \arg irq_signal indicates more than one signal. - * \arg irq_signal is not currently asserted. - * \arg The interrupt is not using SLIH. - */ -void psa_eoi(psa_signal_t irq_signal); - -/** - * \brief Terminate execution within the calling Secure Partition and will not - * return. - * - * \retval "Does not return" - */ -void psa_panic(void); - -/** - * \brief Enable an interrupt. - * - * \param[in] irq_signal The signal for the interrupt to be enabled. - * This must have a single bit set, which must be the - * signal value for an interrupt in the calling Secure - * Partition. - * - * \retval void - * \retval "PROGRAMMER ERROR" If one or more of the following are true: - * \arg \a irq_signal is not an interrupt signal. - * \arg \a irq_signal indicates more than one signal. - */ -void psa_irq_enable(psa_signal_t irq_signal); - -/** - * \brief Disable an interrupt and return the status of the interrupt prior to - * being disabled by this call. - * - * \param[in] irq_signal The signal for the interrupt to be disabled. - * This must have a single bit set, which must be the - * signal value for an interrupt in the calling Secure - * Partition. - * - * \retval 0 The interrupt was disabled prior to this call. - * 1 The interrupt was enabled prior to this call. - * \retval "PROGRAMMER ERROR" If one or more of the following are true: - * \arg \a irq_signal is not an interrupt signal. - * \arg \a irq_signal indicates more than one signal. - * - * \note The current implementation always return 1. Do not use the return. - */ -psa_irq_status_t psa_irq_disable(psa_signal_t irq_signal); - -/** - * \brief Reset the signal for an interrupt that is using FLIH handling. - * - * \param[in] irq_signal The interrupt signal to be reset. - * This must have a single bit set, corresponding to a - * currently asserted signal for an interrupt that is - * defined to use FLIH handling. - * - * \retval void - * \retval "Programmer Error" if one or more of the following are true: - * \arg \a irq_signal is not a signal for an interrupt - * that is specified with FLIH handling in the Secure - * Partition manifest. - * \arg \a irq_signal indicates more than one signal. - * \arg \a irq_signal is not currently asserted. - */ -void psa_reset_signal(psa_signal_t irq_signal); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_SERVICE_H__ */ diff --git a/bsp/interface/include/psa/storage_common.h b/bsp/interface/include/psa/storage_common.h deleted file mode 100644 index 3f901c5..0000000 --- a/bsp/interface/include/psa/storage_common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* This file includes common definitions for PSA storage -*/ - -#ifndef PSA_STORAGE_COMMON_H -#define PSA_STORAGE_COMMON_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint32_t psa_storage_create_flags_t; - -typedef uint64_t psa_storage_uid_t; - -/* Flags */ - -#define PSA_STORAGE_FLAG_NONE 0u -#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0) -#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1) -#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2) - -/* A container for metadata associated with a specific uid */ - -struct psa_storage_info_t { - size_t capacity; - size_t size; - psa_storage_create_flags_t flags; -}; - -#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0) - -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -#ifdef __cplusplus -} -#endif - -#endif // PSA_STORAGE_COMMON_H diff --git a/bsp/interface/include/psa_manifest/pid.h b/bsp/interface/include/psa_manifest/pid.h deleted file mode 100644 index 6ff22f1..0000000 --- a/bsp/interface/include/psa_manifest/pid.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_PID_H__ -#define __PSA_MANIFEST_PID_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_PS (256) -#define TFM_SP_ITS (257) -#define TFM_SP_AUDIT_LOG (258) -#define TFM_SP_CRYPTO (259) -#define TFM_SP_PLATFORM (260) -#define TFM_SP_INITIAL_ATTESTATION (261) -#define TFM_SP_CORE_TEST (262) -#define TFM_SP_CORE_TEST_2 (263) -#define TFM_SP_SECURE_TEST_PARTITION (264) -#define TFM_SP_IPC_SERVICE_TEST (265) -#define TFM_SP_IPC_CLIENT_TEST (266) -#define TFM_SP_PS_TEST (268) -#define TFM_SP_SECURE_CLIENT_2 (269) -#define TFM_SP_FWU (271) -#define TFM_SP_FFM11 (272) -#define TFM_SP_ATTEST_TEST (273) -#define TFM_SP_SLIH_TEST (267) -#define TFM_SP_FLIH_TEST (270) - -#define TFM_MAX_USER_PARTITIONS (18) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_PID_H__ */ diff --git a/bsp/interface/include/psa_manifest/sid.h b/bsp/interface/include/psa_manifest/sid.h deleted file mode 100644 index 847472f..0000000 --- a/bsp/interface/include/psa_manifest/sid.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_SID_H__ -#define __PSA_MANIFEST_SID_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/******** TFM_SP_PS ********/ -#define TFM_PS_SET_SID (0x00000060U) -#define TFM_PS_SET_VERSION (1U) -#define TFM_PS_GET_SID (0x00000061U) -#define TFM_PS_GET_VERSION (1U) -#define TFM_PS_GET_INFO_SID (0x00000062U) -#define TFM_PS_GET_INFO_VERSION (1U) -#define TFM_PS_REMOVE_SID (0x00000063U) -#define TFM_PS_REMOVE_VERSION (1U) -#define TFM_PS_GET_SUPPORT_SID (0x00000064U) -#define TFM_PS_GET_SUPPORT_VERSION (1U) - -/******** TFM_SP_ITS ********/ -#define TFM_ITS_SET_SID (0x00000070U) -#define TFM_ITS_SET_VERSION (1U) -#define TFM_ITS_GET_SID (0x00000071U) -#define TFM_ITS_GET_VERSION (1U) -#define TFM_ITS_GET_INFO_SID (0x00000072U) -#define TFM_ITS_GET_INFO_VERSION (1U) -#define TFM_ITS_REMOVE_SID (0x00000073U) -#define TFM_ITS_REMOVE_VERSION (1U) - -/******** TFM_SP_CRYPTO ********/ -#define TFM_CRYPTO_SID (0x00000080U) -#define TFM_CRYPTO_VERSION (1U) -#define TFM_CRYPTO_HANDLE (0x40000100U) - -/******** TFM_SP_PLATFORM ********/ -#define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) -#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) -#define TFM_SP_PLATFORM_IOCTL_SID (0x00000041U) -#define TFM_SP_PLATFORM_IOCTL_VERSION (1U) -#define TFM_SP_PLATFORM_NV_COUNTER_SID (0x00000042U) -#define TFM_SP_PLATFORM_NV_COUNTER_VERSION (1U) - -/******** TFM_SP_INITIAL_ATTESTATION ********/ -#define TFM_ATTEST_GET_TOKEN_SID (0x00000020U) -#define TFM_ATTEST_GET_TOKEN_VERSION (1U) -#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U) -#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U) - -/******** TFM_SP_CORE_TEST ********/ -#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U) -#define SPM_CORE_TEST_INIT_SUCCESS_VERSION (1U) -#define SPM_CORE_TEST_DIRECT_RECURSION_SID (0x0000F021U) -#define SPM_CORE_TEST_DIRECT_RECURSION_VERSION (1U) -#define SPM_CORE_TEST_SS_TO_SS_SID (0x0000F024U) -#define SPM_CORE_TEST_SS_TO_SS_VERSION (1U) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SID (0x0000F025U) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_VERSION (1U) -#define SPM_CORE_TEST_OUTVEC_WRITE_SID (0x0000F026U) -#define SPM_CORE_TEST_OUTVEC_WRITE_VERSION (1U) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SID (0x0000F027U) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_VERSION (1U) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SID (0x0000F028U) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_VERSION (1U) -#define SPM_CORE_TEST_SPM_REQUEST_SID (0x0000F029U) -#define SPM_CORE_TEST_SPM_REQUEST_VERSION (1U) -#define SPM_CORE_TEST_BLOCK_SID (0x0000F02AU) -#define SPM_CORE_TEST_BLOCK_VERSION (1U) -#define SPM_CORE_TEST_NS_THREAD_SID (0x0000F02BU) -#define SPM_CORE_TEST_NS_THREAD_VERSION (1U) - -/******** TFM_SP_CORE_TEST_2 ********/ -#define SPM_CORE_TEST_2_SLAVE_SERVICE_SID (0x0000F040U) -#define SPM_CORE_TEST_2_SLAVE_SERVICE_VERSION (1U) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID (0x0000F041U) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_VERSION (1U) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID (0x0000F042U) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_VERSION (1U) -#define SPM_CORE_TEST_2_INVERT_SID (0x0000F043U) -#define SPM_CORE_TEST_2_INVERT_VERSION (1U) - -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SID (0x0000F000U) -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_VERSION (1U) - -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#define IPC_SERVICE_TEST_BASIC_SID (0x0000F080U) -#define IPC_SERVICE_TEST_BASIC_VERSION (1U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F081U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F082U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F083U) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SID (0x0000F084U) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_VERSION (1U) - -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#define IPC_CLIENT_TEST_BASIC_SID (0x0000F060U) -#define IPC_CLIENT_TEST_BASIC_VERSION (1U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F061U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F062U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F063U) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_MEM_CHECK_SID (0x0000F064U) -#define IPC_CLIENT_TEST_MEM_CHECK_VERSION (1U) -#define IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SID (0x0000F065U) -#define IPC_CLIENT_TEST_RETRIEVE_APP_MEM_VERSION (1U) - -/******** TFM_SP_PS_TEST ********/ -#define TFM_PS_TEST_PREPARE_SID (0x0000F0C0U) -#define TFM_PS_TEST_PREPARE_VERSION (1U) - -/******** TFM_SP_SECURE_CLIENT_2 ********/ -#define TFM_SECURE_CLIENT_2_SID (0x0000F0E0U) -#define TFM_SECURE_CLIENT_2_VERSION (1U) - -/******** TFM_SP_FWU ********/ -#define TFM_FWU_WRITE_SID (0x000000A0U) -#define TFM_FWU_WRITE_VERSION (1U) -#define TFM_FWU_INSTALL_SID (0x000000A1U) -#define TFM_FWU_INSTALL_VERSION (1U) -#define TFM_FWU_ABORT_SID (0x000000A2U) -#define TFM_FWU_ABORT_VERSION (1U) -#define TFM_FWU_QUERY_SID (0x000000A3U) -#define TFM_FWU_QUERY_VERSION (1U) -#define TFM_FWU_REQUEST_REBOOT_SID (0x000000A4U) -#define TFM_FWU_REQUEST_REBOOT_VERSION (1U) -#define TFM_FWU_ACCEPT_SID (0x000000A5U) -#define TFM_FWU_ACCEPT_VERSION (1U) - -/******** TFM_SP_FFM11 ********/ -#define TFM_FFM11_SERVICE1_SID (0x0000F120U) -#define TFM_FFM11_SERVICE1_VERSION (1U) -#define TFM_FFM11_SERVICE1_HANDLE (0x40000103U) -#define TFM_FFM11_SERVICE2_SID (0x0000F121U) -#define TFM_FFM11_SERVICE2_VERSION (1U) -#define TFM_FFM11_SERVICE2_HANDLE (0x40000101U) -#define TFM_FFM11_SERVICE3_SID (0x0000F122U) -#define TFM_FFM11_SERVICE3_VERSION (1U) -#define TFM_FFM11_SERVICE3_HANDLE (0x40000102U) - -/******** TFM_SP_ATTEST_TEST ********/ -#define TFM_ATTEST_TEST_GET_PUBLIC_KEY_SID (0x0000F140U) -#define TFM_ATTEST_TEST_GET_PUBLIC_KEY_VERSION (1U) - -/******** TFM_SP_SLIH_TEST ********/ -#define TFM_SLIH_TEST_CASE_SID (0x0000F0A0U) -#define TFM_SLIH_TEST_CASE_VERSION (1U) -#define TFM_SLIH_TEST_CASE_HANDLE (0x40000104U) - -/******** TFM_SP_FLIH_TEST ********/ -#define TFM_FLIH_TEST_CASE_SID (0x0000F0B0U) -#define TFM_FLIH_TEST_CASE_VERSION (1U) -#define TFM_FLIH_TEST_CASE_HANDLE (0x40000105U) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_SID_H__ */ diff --git a/bsp/interface/include/tfm_api.h b/bsp/interface/include/tfm_api.h deleted file mode 100644 index 1d4c9ee..0000000 --- a/bsp/interface/include/tfm_api.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2017-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_API_H__ -#define __TFM_API_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "psa/client.h" - -#define TFM_INVALID_CLIENT_ID 0 - -/** - * \brief Checks if the provided client ID is a secure client ID. - * - * \param[in] client_id Client ID to check. - * - * \retval 1 Client ID is secure. - * \retval 0 Client ID is non-secure. - */ -#define TFM_CLIENT_ID_IS_S(client_id) ((client_id)>0) - -/** - * \brief Checks if the provided client ID is a non-secure client ID. - * - * \param[in] client_id Client ID to check. - * - * \retval 1 Client ID is non-secure. - * \retval 0 Client ID is secure. - */ -#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0) - -/* The mask used for timeout values */ -#define PSA_TIMEOUT_MASK PSA_BLOCK - -/* FixMe: sort out DEBUG compile option and limit return value options - * on external interfaces */ -enum tfm_status_e -{ - TFM_SUCCESS = 0, - TFM_PARTITION_BUSY, - TFM_ERROR_SECURE_DOMAIN_LOCKED, - TFM_ERROR_INVALID_PARAMETER, - TFM_ERROR_PARTITION_NON_REENTRANT, - TFM_ERROR_NS_THREAD_MODE_CALL, - TFM_ERROR_NOT_INITIALIZED, - TFM_ERROR_NO_ACTIVE_PARTITION, - TFM_ERROR_INVALID_EXC_MODE, - TFM_ERROR_NOT_IN_RANGE, - TFM_SECURE_LOCK_FAILED, - TFM_SECURE_UNLOCK_FAILED, - TFM_ERROR_GENERIC = 0x1F, -}; - -/* - * Structure to package type, in_len and out_len, it is mainly used for - * psa_call. - */ -struct tfm_control_parameter_t { - int32_t type; - size_t in_len; - size_t out_len; -}; - -/********************* Secure function declarations ***************************/ - -/** - * \brief Assign client ID to the current TZ context. - * - * \param[in] ns_client_id The client ID to be assigned to the current - * context. - * \retval TFM_SUCCESS The client ID assigned successfully. - * \retval error code The client ID assignment failed, an error code - * returned according to \ref tfm_status_e. - * \note This function have to be called from handler mode. - */ -enum tfm_status_e tfm_register_client_id (int32_t ns_client_id); - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return The version of the PSA Framework. - */ -uint32_t tfm_psa_framework_version_veneer(void); - -/** - * \brief Return version of secure function provided by secure binary. - * - * \param[in] sid ID of secure service. - * - * \return Version number of secure function. - */ -uint32_t tfm_psa_version_veneer(uint32_t sid); - -/** - * \brief Connect to secure function. - * - * \param[in] sid ID of secure service. - * \param[in] version Version of SF requested by client. - * - * \return Returns handle to connection. - */ -psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version); - -/** - * \brief Call a secure function referenced by a connection handle. - * - * \param[in] handle Handle to connection. - * \param[in] ctrl_param Parameters combined in uint32_t, - * includes request type, in_num and out_num. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in,out] out_vec Array of output \ref psa_outvec structures. - * - * \return Returns \ref psa_status_t status code. - */ -psa_status_t tfm_psa_call_veneer(psa_handle_t handle, - uint32_t ctrl_param, - const psa_invec *in_vec, - psa_outvec *out_vec); - -/** - * \brief Close connection to secure function referenced by a connection handle. - * - * \param[in] handle Handle to connection - */ -void tfm_psa_close_veneer(psa_handle_t handle); - -/***************** End Secure function declarations ***************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_API_H__ */ diff --git a/bsp/interface/include/tfm_crypto_defs.h b/bsp/interface/include/tfm_crypto_defs.h deleted file mode 100644 index 5a860b8..0000000 --- a/bsp/interface/include/tfm_crypto_defs.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_CRYPTO_DEFS_H__ -#define __TFM_CRYPTO_DEFS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "tfm_api.h" -#include "psa/crypto.h" - -/** - * \brief This type is used to overcome a limitation in the number of maximum - * IOVECs that can be used especially in psa_aead_encrypt and - * psa_aead_decrypt. To be removed in case the AEAD APIs number of - * parameters passed gets restructured - */ -#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u) -struct tfm_crypto_aead_pack_input { - uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH]; - uint32_t nonce_length; -}; - -/** - * \brief Structure used to pack non-pointer types in a call - * - */ -struct tfm_crypto_pack_iovec { - uint32_t sfn_id; /*!< Secure function ID used to dispatch the - * request - */ - uint16_t step; /*!< Key derivation step */ - psa_key_id_t key_id; /*!< Key id */ - psa_algorithm_t alg; /*!< Algorithm */ - uint32_t op_handle; /*!< Frontend context handle associated to a - * multipart operation - */ - size_t capacity; /*!< Key derivation capacity */ - - struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for - * AEAD until the API is - * restructured - */ -}; - -/** - * \brief Define a progressive numerical value for each SID which can be used - * when dispatching the requests to the service - */ -enum { - TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), - TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, - TFM_CRYPTO_OPEN_KEY_SID, - TFM_CRYPTO_CLOSE_KEY_SID, - TFM_CRYPTO_IMPORT_KEY_SID, - TFM_CRYPTO_DESTROY_KEY_SID, - TFM_CRYPTO_EXPORT_KEY_SID, - TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, - TFM_CRYPTO_PURGE_KEY_SID, - TFM_CRYPTO_COPY_KEY_SID, - TFM_CRYPTO_HASH_COMPUTE_SID, - TFM_CRYPTO_HASH_COMPARE_SID, - TFM_CRYPTO_HASH_SETUP_SID, - TFM_CRYPTO_HASH_UPDATE_SID, - TFM_CRYPTO_HASH_FINISH_SID, - TFM_CRYPTO_HASH_VERIFY_SID, - TFM_CRYPTO_HASH_ABORT_SID, - TFM_CRYPTO_HASH_CLONE_SID, - TFM_CRYPTO_MAC_COMPUTE_SID, - TFM_CRYPTO_MAC_VERIFY_SID, - TFM_CRYPTO_MAC_SIGN_SETUP_SID, - TFM_CRYPTO_MAC_VERIFY_SETUP_SID, - TFM_CRYPTO_MAC_UPDATE_SID, - TFM_CRYPTO_MAC_SIGN_FINISH_SID, - TFM_CRYPTO_MAC_VERIFY_FINISH_SID, - TFM_CRYPTO_MAC_ABORT_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_GENERATE_IV_SID, - TFM_CRYPTO_CIPHER_SET_IV_SID, - TFM_CRYPTO_CIPHER_UPDATE_SID, - TFM_CRYPTO_CIPHER_FINISH_SID, - TFM_CRYPTO_CIPHER_ABORT_SID, - TFM_CRYPTO_AEAD_ENCRYPT_SID, - TFM_CRYPTO_AEAD_DECRYPT_SID, - TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, - TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, - TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, - TFM_CRYPTO_AEAD_SET_NONCE_SID, - TFM_CRYPTO_AEAD_SET_LENGTHS_SID, - TFM_CRYPTO_AEAD_UPDATE_AD_SID, - TFM_CRYPTO_AEAD_UPDATE_SID, - TFM_CRYPTO_AEAD_FINISH_SID, - TFM_CRYPTO_AEAD_VERIFY_SID, - TFM_CRYPTO_AEAD_ABORT_SID, - TFM_CRYPTO_SIGN_MESSAGE_SID, - TFM_CRYPTO_VERIFY_MESSAGE_SID, - TFM_CRYPTO_SIGN_HASH_SID, - TFM_CRYPTO_VERIFY_HASH_SID, - TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, - TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, - TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, - TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, - TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, - TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, - TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, - TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, - TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, - TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, - TFM_CRYPTO_GENERATE_RANDOM_SID, - TFM_CRYPTO_GENERATE_KEY_SID, - TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, - TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, - TFM_CRYPTO_SID_MAX, -}; - -/** - * \brief Define an invalid value for an SID - * - */ -#define TFM_CRYPTO_SID_INVALID (~0x0u) - -/** - * \brief This value is used to mark an handle as invalid. - * - */ -#define TFM_CRYPTO_INVALID_HANDLE (0x0u) - -/** - * \brief The persistent key identifier that refers to the hardware unique key. - * - */ -#define TFM_CRYPTO_KEY_ID_HUK (0xFFFF815Bu) - -/** - * \brief The algorithm identifier that refers to key derivation from the - * hardware unique key. - * - */ -#define TFM_CRYPTO_ALG_HUK_DERIVATION ((psa_algorithm_t)0xB0000F00) - -/** - * \brief Define miscellaneous literal constants that are used in the service - * - */ -enum { - TFM_CRYPTO_NOT_IN_USE = 0, - TFM_CRYPTO_IN_USE = 1 -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_CRYPTO_DEFS_H__ */ diff --git a/bsp/interface/include/tfm_veneers.h b/bsp/interface/include/tfm_veneers.h deleted file mode 100644 index c556a15..0000000 --- a/bsp/interface/include/tfm_veneers.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __TFM_VENEERS_H__ -#define __TFM_VENEERS_H__ - -#include "tfm_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TFM_PARTITION_PROTECTED_STORAGE -/******** TFM_SP_PS ********/ -psa_status_t tfm_ps_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_ps_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_ps_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_ps_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_ps_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -/******** TFM_SP_ITS ********/ -psa_status_t tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -/******** TFM_SP_AUDIT_LOG ********/ -psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_add_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_get_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_get_record_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -/******** TFM_SP_CRYPTO ********/ -psa_status_t tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_purge_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_sign_message_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_verify_message_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -/******** TFM_SP_PLATFORM ********/ -psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -/******** TFM_SP_INITIAL_ATTESTATION ********/ -psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST ********/ -psa_status_t tfm_spm_core_test_sfn_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_sfn_init_success_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_sfn_direct_recursion_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST_2 ********/ -psa_status_t tfm_spm_core_test_2_slave_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -psa_status_t tfm_secure_client_service_sfn_run_tests_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -/******** TFM_SP_PS_TEST ********/ -psa_status_t tfm_ps_test_prepare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_CLIENT_2 ********/ -psa_status_t tfm_secure_client_2_call_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -/******** TFM_SP_FWU ********/ -psa_status_t tfm_fwu_write_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_fwu_install_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_fwu_abort_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_fwu_query_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_fwu_request_reboot_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_fwu_accept_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 -/******** TFM_SP_FFM11 ********/ -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -/******** TFM_SP_ATTEST_TEST ********/ -psa_status_t tfm_attest_test_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST -/******** TFM_SP_SLIH_TEST ********/ -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -/******** TFM_SP_FLIH_TEST ********/ -#endif /* TFM_ENABLE_FLIH_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_VENEERS_H__ */ diff --git a/bsp/mcuboot_config/mcuboot_config.h b/bsp/mcuboot_config/mcuboot_config.h deleted file mode 100644 index 2c921f0..0000000 --- a/bsp/mcuboot_config/mcuboot_config.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2018 Open Source Foundries Limited - * Copyright (c) 2019-2021 Arm Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * Original code taken from mcuboot project at: - * https://github.com/mcu-tools/mcuboot - * Git SHA of the original version: ac55554059147fff718015be9f4bd3108123f50a - */ - -#ifndef __MCUBOOT_CONFIG_H__ -#define __MCUBOOT_CONFIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file is also included by the simulator, but we don't want to - * define anything here in simulator builds. - * - * Instead of using mcuboot_config.h, the simulator adds MCUBOOT_xxx - * configuration flags to the compiler command lines based on the - * values of environment variables. However, the file still must - * exist, or bootutil won't build. - */ -#ifndef __BOOTSIM__ - -#define MCUBOOT_VALIDATE_PRIMARY_SLOT -#define MCUBOOT_USE_FLASH_AREA_GET_SECTORS -#define MCUBOOT_TARGET_CONFIG "flash_layout.h" - -#define MCUBOOT_HW_ROLLBACK_PROT -#define MCUBOOT_MEASURED_BOOT -/* #undef MCUBOOT_DATA_SHARING */ - -/* - * Maximum size of the measured boot record. - * - * Its size can be calculated based on the following aspects: - * - There are 5 allowed software component claims, - * - SHA256 is used as the measurement method for the other claims. - * Considering these aspects, the only claim which size can vary is the type - * of the software component with a maximum length of 12 bytes, which means - * the boot record size can be up to 100 bytes. - */ -#define MAX_BOOT_RECORD_SZ (100u) - -/* #undef MCUBOOT_ENC_IMAGES */ -/* #undef MCUBOOT_ENCRYPT_RSA */ - -/* - * Cryptographic settings - */ -#define MCUBOOT_USE_MBED_TLS - -/* - * Logging - */ -#define MCUBOOT_HAVE_LOGGING 1 -#define MCUBOOT_LOG_LEVEL 3 - -#endif /* !__BOOTSIM__ */ - -/* - * Watchdog feeding - */ -#define MCUBOOT_WATCHDOG_FEED() \ - do { \ - /* Do nothing. */ \ - } while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* __MCUBOOT_CONFIG_H__ */ diff --git a/bsp/secure_fw/partitions/audit_logging/auto_generated/intermedia_tfm_audit_logging.c b/bsp/secure_fw/partitions/audit_logging/auto_generated/intermedia_tfm_audit_logging.c deleted file mode 100644 index 4e23100..0000000 --- a/bsp/secure_fw/partitions/audit_logging/auto_generated/intermedia_tfm_audit_logging.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_audit_log_stack[0x0200] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/audit_logging/auto_generated/load_info_tfm_audit_logging.c b/bsp/secure_fw/partitions/audit_logging/auto_generated/load_info_tfm_audit_logging.c deleted file mode 100644 index 39aac10..0000000 --- a/bsp/secure_fw/partitions/audit_logging/auto_generated/load_info_tfm_audit_logging.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_audit_logging.h" - -#define TFM_SP_AUDIT_LOG_NDEPS (0) -#define TFM_SP_AUDIT_LOG_NSERVS (0) -#if TFM_LVL == 3 -#define TFM_SP_AUDIT_LOG_NASSETS (1 + 1) -#else -#define TFM_SP_AUDIT_LOG_NASSETS (1) -#endif -#define TFM_SP_AUDIT_LOG_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_AUDIT_LOG_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_AUDIT_LOG_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_audit_log_stack[]; - -/* Entrypoint function declaration */ -extern void audit_core_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_audit_log_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_AUDIT_LOG_NASSETS]; -#else - struct asset_desc_t assets[TFM_SP_AUDIT_LOG_NASSETS]; -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_audit_log_load_info_t tfm_sp_audit_log_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_AUDIT_LOG, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(audit_core_init), - .stack_size = 0x0200, - .heap_size = 0, - .ndeps = TFM_SP_AUDIT_LOG_NDEPS, - .nservices = TFM_SP_AUDIT_LOG_NSERVS, - .nassets = TFM_SP_AUDIT_LOG_NASSETS, - .nirqs = TFM_SP_AUDIT_LOG_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_audit_log_stack, - .heap_addr = 0, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_AUDIT_LOG_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_AUDIT_LOG_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, -#ifdef AUDIT_UART_REDIRECTION - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_UART1), - .attr = ASSET_DEV_REF_BIT, - }, -#endif - }, -#else - .assets = { -#ifdef AUDIT_UART_REDIRECTION - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_UART1), - .attr = ASSET_DEV_REF_BIT, - }, -#endif - }, -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_audit_log_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); diff --git a/bsp/secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h b/bsp/secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h deleted file mode 100644 index 3ec8c6f..0000000 --- a/bsp/secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_AUDIT_LOGGING_H__ -#define __PSA_MANIFEST_TFM_AUDIT_LOGGING_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_AUDIT_LOG_MODEL_IPC 1 -#define TFM_SP_AUDIT_LOG_MODEL_SFN 0 - -#error "Service and IRQ at least one must be declared!" - - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_AUDIT_LOGGING_H__ */ diff --git a/bsp/secure_fw/partitions/crypto/auto_generated/intermedia_tfm_crypto.c b/bsp/secure_fw/partitions/crypto/auto_generated/intermedia_tfm_crypto.c deleted file mode 100644 index 96f1d67..0000000 --- a/bsp/secure_fw/partitions/crypto/auto_generated/intermedia_tfm_crypto.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_crypto_stack[0x2000] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/crypto/auto_generated/load_info_tfm_crypto.c b/bsp/secure_fw/partitions/crypto/auto_generated/load_info_tfm_crypto.c deleted file mode 100644 index 1727214..0000000 --- a/bsp/secure_fw/partitions/crypto/auto_generated/load_info_tfm_crypto.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_crypto.h" - -#define TFM_SP_CRYPTO_NDEPS (4) -#define TFM_SP_CRYPTO_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_CRYPTO_NASSETS (0 + 1) -#else -#define TFM_SP_CRYPTO_NASSETS (0) -#endif -#define TFM_SP_CRYPTO_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_CRYPTO_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_CRYPTO_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_crypto_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_crypto_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_crypto_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_CRYPTO_NDEPS]; - struct service_load_info_t services[TFM_SP_CRYPTO_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_CRYPTO_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_crypto_load_info_t tfm_sp_crypto_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0101 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_CRYPTO, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_crypto_init), - .stack_size = 0x2000, - .heap_size = 0, - .ndeps = TFM_SP_CRYPTO_NDEPS, - .nservices = TFM_SP_CRYPTO_NSERVS, - .nassets = TFM_SP_CRYPTO_NASSETS, - .nirqs = TFM_SP_CRYPTO_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_crypto_stack, - .heap_addr = 0, - .deps = { - TFM_ITS_SET_SID, - TFM_ITS_GET_SID, - TFM_ITS_GET_INFO_SID, - TFM_ITS_REMOVE_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_CRYPTO"), - .signal = TFM_CRYPTO_SIGNAL, - .sid = 0x00000080, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_FLAG_STATELESS | 0x0 - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_CRYPTO_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_CRYPTO_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_crypto_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_crypto_service_runtime_item[TFM_SP_CRYPTO_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h b/bsp/secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h deleted file mode 100644 index 9626eae..0000000 --- a/bsp/secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_CRYPTO_H__ -#define __PSA_MANIFEST_TFM_CRYPTO_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_CRYPTO_MODEL_IPC 1 -#define TFM_SP_CRYPTO_MODEL_SFN 0 - - -#define TFM_CRYPTO_SIGNAL (1U << 4) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_CRYPTO_H__ */ diff --git a/bsp/secure_fw/partitions/firmware_update/auto_generated/intermedia_tfm_firmware_update.c b/bsp/secure_fw/partitions/firmware_update/auto_generated/intermedia_tfm_firmware_update.c deleted file mode 100644 index 8804ab5..0000000 --- a/bsp/secure_fw/partitions/firmware_update/auto_generated/intermedia_tfm_firmware_update.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_fwu_stack[0x2000] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/firmware_update/auto_generated/load_info_tfm_firmware_update.c b/bsp/secure_fw/partitions/firmware_update/auto_generated/load_info_tfm_firmware_update.c deleted file mode 100644 index 1f06742..0000000 --- a/bsp/secure_fw/partitions/firmware_update/auto_generated/load_info_tfm_firmware_update.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_firmware_update.h" - -#define TFM_SP_FWU_NDEPS (2) -#define TFM_SP_FWU_NSERVS (6) -#if TFM_LVL == 3 -#define TFM_SP_FWU_NASSETS (0 + 1) -#else -#define TFM_SP_FWU_NASSETS (0) -#endif -#define TFM_SP_FWU_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_FWU_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_FWU_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_fwu_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_fwu_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_fwu_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_FWU_NDEPS]; - struct service_load_info_t services[TFM_SP_FWU_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_FWU_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_fwu_load_info_t tfm_sp_fwu_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_FWU, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_fwu_init), - .stack_size = 0x2000, - .heap_size = 0, - .ndeps = TFM_SP_FWU_NDEPS, - .nservices = TFM_SP_FWU_NSERVS, - .nassets = TFM_SP_FWU_NASSETS, - .nirqs = TFM_SP_FWU_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_fwu_stack, - .heap_addr = 0, - .deps = { - TFM_CRYPTO_SID, - TFM_SP_PLATFORM_SYSTEM_RESET_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_FWU_WRITE"), - .signal = TFM_FWU_WRITE_SIGNAL, - .sid = 0x000000A0, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FWU_INSTALL"), - .signal = TFM_FWU_INSTALL_SIGNAL, - .sid = 0x000000A1, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FWU_ABORT"), - .signal = TFM_FWU_ABORT_SIGNAL, - .sid = 0x000000A2, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FWU_QUERY"), - .signal = TFM_FWU_QUERY_SIGNAL, - .sid = 0x000000A3, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FWU_REQUEST_REBOOT"), - .signal = TFM_FWU_REQUEST_REBOOT_SIGNAL, - .sid = 0x000000A4, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FWU_ACCEPT"), - .signal = TFM_FWU_ACCEPT_SIGNAL, - .sid = 0x000000A5, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_FWU_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_FWU_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_fwu_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_fwu_service_runtime_item[TFM_SP_FWU_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/firmware_update/psa_manifest/tfm_firmware_update.h b/bsp/secure_fw/partitions/firmware_update/psa_manifest/tfm_firmware_update.h deleted file mode 100644 index a07e0b2..0000000 --- a/bsp/secure_fw/partitions/firmware_update/psa_manifest/tfm_firmware_update.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_FIRMWARE_UPDATE_H__ -#define __PSA_MANIFEST_TFM_FIRMWARE_UPDATE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_FWU_MODEL_IPC 1 -#define TFM_SP_FWU_MODEL_SFN 0 - - -#define TFM_FWU_WRITE_SIGNAL (1U << 4) -#define TFM_FWU_INSTALL_SIGNAL (1U << 5) -#define TFM_FWU_ABORT_SIGNAL (1U << 6) -#define TFM_FWU_QUERY_SIGNAL (1U << 7) -#define TFM_FWU_REQUEST_REBOOT_SIGNAL (1U << 8) -#define TFM_FWU_ACCEPT_SIGNAL (1U << 9) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_FIRMWARE_UPDATE_H__ */ diff --git a/bsp/secure_fw/partitions/initial_attestation/auto_generated/intermedia_tfm_initial_attestation.c b/bsp/secure_fw/partitions/initial_attestation/auto_generated/intermedia_tfm_initial_attestation.c deleted file mode 100644 index 4738215..0000000 --- a/bsp/secure_fw/partitions/initial_attestation/auto_generated/intermedia_tfm_initial_attestation.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_initial_attestation_stack[0x0A80] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/initial_attestation/auto_generated/load_info_tfm_initial_attestation.c b/bsp/secure_fw/partitions/initial_attestation/auto_generated/load_info_tfm_initial_attestation.c deleted file mode 100644 index f356d4b..0000000 --- a/bsp/secure_fw/partitions/initial_attestation/auto_generated/load_info_tfm_initial_attestation.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_initial_attestation.h" - -#define TFM_SP_INITIAL_ATTESTATION_NDEPS (1) -#define TFM_SP_INITIAL_ATTESTATION_NSERVS (2) -#if TFM_LVL == 3 -#define TFM_SP_INITIAL_ATTESTATION_NASSETS (0 + 1) -#else -#define TFM_SP_INITIAL_ATTESTATION_NASSETS (0) -#endif -#define TFM_SP_INITIAL_ATTESTATION_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_INITIAL_ATTESTATION_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_INITIAL_ATTESTATION_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_initial_attestation_stack[]; - -/* Entrypoint function declaration */ -extern void attest_partition_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_initial_attestation_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_INITIAL_ATTESTATION_NDEPS]; - struct service_load_info_t services[TFM_SP_INITIAL_ATTESTATION_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_INITIAL_ATTESTATION_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_initial_attestation_load_info_t tfm_sp_initial_attestation_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_INITIAL_ATTESTATION, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(attest_partition_init), - .stack_size = 0x0A80, - .heap_size = 0, - .ndeps = TFM_SP_INITIAL_ATTESTATION_NDEPS, - .nservices = TFM_SP_INITIAL_ATTESTATION_NSERVS, - .nassets = TFM_SP_INITIAL_ATTESTATION_NASSETS, - .nirqs = TFM_SP_INITIAL_ATTESTATION_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_initial_attestation_stack, - .heap_addr = 0, - .deps = { - TFM_CRYPTO_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_ATTEST_GET_TOKEN"), - .signal = TFM_ATTEST_GET_TOKEN_SIGNAL, - .sid = 0x00000020, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_ATTEST_GET_TOKEN_SIZE"), - .signal = TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL, - .sid = 0x00000021, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_INITIAL_ATTESTATION_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_INITIAL_ATTESTATION_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_initial_attestation_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_initial_attestation_service_runtime_item[TFM_SP_INITIAL_ATTESTATION_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h b/bsp/secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h deleted file mode 100644 index 68ff243..0000000 --- a/bsp/secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_INITIAL_ATTESTATION_H__ -#define __PSA_MANIFEST_TFM_INITIAL_ATTESTATION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_INITIAL_ATTESTATION_MODEL_IPC 1 -#define TFM_SP_INITIAL_ATTESTATION_MODEL_SFN 0 - - -#define TFM_ATTEST_GET_TOKEN_SIGNAL (1U << 4) -#define TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL (1U << 5) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_INITIAL_ATTESTATION_H__ */ diff --git a/bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/intermedia_tfm_internal_trusted_storage.c b/bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/intermedia_tfm_internal_trusted_storage.c deleted file mode 100644 index 2d8d3cc..0000000 --- a/bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/intermedia_tfm_internal_trusted_storage.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_its_stack[0x680] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/load_info_tfm_internal_trusted_storage.c b/bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/load_info_tfm_internal_trusted_storage.c deleted file mode 100644 index 37fe432..0000000 --- a/bsp/secure_fw/partitions/internal_trusted_storage/auto_generated/load_info_tfm_internal_trusted_storage.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_internal_trusted_storage.h" - -#define TFM_SP_ITS_NDEPS (0) -#define TFM_SP_ITS_NSERVS (4) -#if TFM_LVL == 3 -#define TFM_SP_ITS_NASSETS (0 + 1) -#else -#define TFM_SP_ITS_NASSETS (0) -#endif -#define TFM_SP_ITS_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_ITS_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_ITS_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_its_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_its_req_mngr_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_its_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_ITS_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_ITS_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_its_load_info_t tfm_sp_its_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_ITS, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_its_req_mngr_init), - .stack_size = 0x680, - .heap_size = 0, - .ndeps = TFM_SP_ITS_NDEPS, - .nservices = TFM_SP_ITS_NSERVS, - .nassets = TFM_SP_ITS_NASSETS, - .nirqs = TFM_SP_ITS_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_its_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_ITS_SET"), - .signal = TFM_ITS_SET_SIGNAL, - .sid = 0x00000070, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_ITS_GET"), - .signal = TFM_ITS_GET_SIGNAL, - .sid = 0x00000071, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_ITS_GET_INFO"), - .signal = TFM_ITS_GET_INFO_SIGNAL, - .sid = 0x00000072, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_ITS_REMOVE"), - .signal = TFM_ITS_REMOVE_SIGNAL, - .sid = 0x00000073, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_ITS_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_ITS_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_its_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_its_service_runtime_item[TFM_SP_ITS_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h b/bsp/secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h deleted file mode 100644 index 21be0a6..0000000 --- a/bsp/secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_INTERNAL_TRUSTED_STORAGE_H__ -#define __PSA_MANIFEST_TFM_INTERNAL_TRUSTED_STORAGE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_ITS_MODEL_IPC 1 -#define TFM_SP_ITS_MODEL_SFN 0 - - -#define TFM_ITS_SET_SIGNAL (1U << 4) -#define TFM_ITS_GET_SIGNAL (1U << 5) -#define TFM_ITS_GET_INFO_SIGNAL (1U << 6) -#define TFM_ITS_REMOVE_SIGNAL (1U << 7) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_INTERNAL_TRUSTED_STORAGE_H__ */ diff --git a/bsp/secure_fw/partitions/platform/auto_generated/intermedia_tfm_platform.c b/bsp/secure_fw/partitions/platform/auto_generated/intermedia_tfm_platform.c deleted file mode 100644 index 9742a71..0000000 --- a/bsp/secure_fw/partitions/platform/auto_generated/intermedia_tfm_platform.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_platform_stack[0x0500] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/platform/auto_generated/load_info_tfm_platform.c b/bsp/secure_fw/partitions/platform/auto_generated/load_info_tfm_platform.c deleted file mode 100644 index 870c4e4..0000000 --- a/bsp/secure_fw/partitions/platform/auto_generated/load_info_tfm_platform.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_platform.h" - -#define TFM_SP_PLATFORM_NDEPS (0) -#define TFM_SP_PLATFORM_NSERVS (3) -#if TFM_LVL == 3 -#define TFM_SP_PLATFORM_NASSETS (0 + 1) -#else -#define TFM_SP_PLATFORM_NASSETS (0) -#endif -#define TFM_SP_PLATFORM_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_PLATFORM_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_PLATFORM_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_platform_stack[]; - -/* Entrypoint function declaration */ -extern void platform_sp_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_platform_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_PLATFORM_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_PLATFORM_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_platform_load_info_t tfm_sp_platform_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_PLATFORM, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(platform_sp_init), - .stack_size = 0x0500, - .heap_size = 0, - .ndeps = TFM_SP_PLATFORM_NDEPS, - .nservices = TFM_SP_PLATFORM_NSERVS, - .nassets = TFM_SP_PLATFORM_NASSETS, - .nirqs = TFM_SP_PLATFORM_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_platform_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_SP_PLATFORM_SYSTEM_RESET"), - .signal = TFM_SP_PLATFORM_SYSTEM_RESET_SIGNAL, - .sid = 0x00000040, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_SP_PLATFORM_IOCTL"), - .signal = TFM_SP_PLATFORM_IOCTL_SIGNAL, - .sid = 0x00000041, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_SP_PLATFORM_NV_COUNTER"), - .signal = TFM_SP_PLATFORM_NV_COUNTER_SIGNAL, - .sid = 0x00000042, - .flags = 0 - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_PLATFORM_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_PLATFORM_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_platform_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_platform_service_runtime_item[TFM_SP_PLATFORM_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/platform/psa_manifest/tfm_platform.h b/bsp/secure_fw/partitions/platform/psa_manifest/tfm_platform.h deleted file mode 100644 index 4c0360b..0000000 --- a/bsp/secure_fw/partitions/platform/psa_manifest/tfm_platform.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_PLATFORM_H__ -#define __PSA_MANIFEST_TFM_PLATFORM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_PLATFORM_MODEL_IPC 1 -#define TFM_SP_PLATFORM_MODEL_SFN 0 - - -#define TFM_SP_PLATFORM_SYSTEM_RESET_SIGNAL (1U << 4) -#define TFM_SP_PLATFORM_IOCTL_SIGNAL (1U << 5) -#define TFM_SP_PLATFORM_NV_COUNTER_SIGNAL (1U << 6) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_PLATFORM_H__ */ diff --git a/bsp/secure_fw/partitions/protected_storage/auto_generated/intermedia_tfm_protected_storage.c b/bsp/secure_fw/partitions/protected_storage/auto_generated/intermedia_tfm_protected_storage.c deleted file mode 100644 index 42b23d8..0000000 --- a/bsp/secure_fw/partitions/protected_storage/auto_generated/intermedia_tfm_protected_storage.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_ps_stack[0x800] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/protected_storage/auto_generated/load_info_tfm_protected_storage.c b/bsp/secure_fw/partitions/protected_storage/auto_generated/load_info_tfm_protected_storage.c deleted file mode 100644 index 52300bf..0000000 --- a/bsp/secure_fw/partitions/protected_storage/auto_generated/load_info_tfm_protected_storage.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_protected_storage.h" - -#define TFM_SP_PS_NDEPS (6) -#define TFM_SP_PS_NSERVS (5) -#if TFM_LVL == 3 -#define TFM_SP_PS_NASSETS (0 + 1) -#else -#define TFM_SP_PS_NASSETS (0) -#endif -#define TFM_SP_PS_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_PS_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_PS_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_ps_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_ps_req_mngr_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_ps_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_PS_NDEPS]; - struct service_load_info_t services[TFM_SP_PS_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_PS_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_ps_load_info_t tfm_sp_ps_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_PS, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_ps_req_mngr_init), - .stack_size = 0x800, - .heap_size = 0, - .ndeps = TFM_SP_PS_NDEPS, - .nservices = TFM_SP_PS_NSERVS, - .nassets = TFM_SP_PS_NASSETS, - .nirqs = TFM_SP_PS_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_ps_stack, - .heap_addr = 0, - .deps = { - TFM_CRYPTO_SID, - TFM_ITS_SET_SID, - TFM_ITS_GET_SID, - TFM_ITS_GET_INFO_SID, - TFM_ITS_REMOVE_SID, - TFM_SP_PLATFORM_NV_COUNTER_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_PS_SET"), - .signal = TFM_PS_SET_SIGNAL, - .sid = 0x00000060, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_PS_GET"), - .signal = TFM_PS_GET_SIGNAL, - .sid = 0x00000061, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_PS_GET_INFO"), - .signal = TFM_PS_GET_INFO_SIGNAL, - .sid = 0x00000062, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_PS_REMOVE"), - .signal = TFM_PS_REMOVE_SIGNAL, - .sid = 0x00000063, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_PS_GET_SUPPORT"), - .signal = TFM_PS_GET_SUPPORT_SIGNAL, - .sid = 0x00000064, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_PS_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_PS_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_ps_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_ps_service_runtime_item[TFM_SP_PS_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/protected_storage/psa_manifest/tfm_protected_storage.h b/bsp/secure_fw/partitions/protected_storage/psa_manifest/tfm_protected_storage.h deleted file mode 100644 index 05327bb..0000000 --- a/bsp/secure_fw/partitions/protected_storage/psa_manifest/tfm_protected_storage.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_PROTECTED_STORAGE_H__ -#define __PSA_MANIFEST_TFM_PROTECTED_STORAGE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_PS_MODEL_IPC 1 -#define TFM_SP_PS_MODEL_SFN 0 - - -#define TFM_PS_SET_SIGNAL (1U << 4) -#define TFM_PS_GET_SIGNAL (1U << 5) -#define TFM_PS_GET_INFO_SIGNAL (1U << 6) -#define TFM_PS_REMOVE_SIGNAL (1U << 7) -#define TFM_PS_GET_SUPPORT_SIGNAL (1U << 8) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_PROTECTED_STORAGE_H__ */ diff --git a/bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/intermedia_tfm_ffm11_partition.c b/bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/intermedia_tfm_ffm11_partition.c deleted file mode 100644 index 07cd081..0000000 --- a/bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/intermedia_tfm_ffm11_partition.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_ffm11_stack[0x200] __attribute__((aligned(8))); diff --git a/bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/load_info_tfm_ffm11_partition.c b/bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/load_info_tfm_ffm11_partition.c deleted file mode 100644 index 7eadcf8..0000000 --- a/bsp/secure_fw/partitions/tfm_ffm11_partition/auto_generated/load_info_tfm_ffm11_partition.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_ffm11_partition.h" - -#define TFM_SP_FFM11_NDEPS (0) -#define TFM_SP_FFM11_NSERVS (3) -#if TFM_LVL == 3 -#define TFM_SP_FFM11_NASSETS (0 + 1) -#else -#define TFM_SP_FFM11_NASSETS (0) -#endif -#define TFM_SP_FFM11_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_FFM11_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_FFM11_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_ffm11_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_ffm11_partition_main(void); - -/* partition load info type definition */ -struct partition_tfm_sp_ffm11_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_FFM11_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_FFM11_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_ffm11_load_info_t tfm_sp_ffm11_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0101 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_FFM11, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_ffm11_partition_main), - .stack_size = 0x200, - .heap_size = 0, - .ndeps = TFM_SP_FFM11_NDEPS, - .nservices = TFM_SP_FFM11_NSERVS, - .nassets = TFM_SP_FFM11_NASSETS, - .nirqs = TFM_SP_FFM11_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_ffm11_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_FFM11_SERVICE1"), - .signal = TFM_FFM11_SERVICE1_SIGNAL, - .sid = 0x0000F120, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_FLAG_STATELESS | 0x3 - | SERVICE_VERSION_POLICY_RELAXED, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FFM11_SERVICE2"), - .signal = TFM_FFM11_SERVICE2_SIGNAL, - .sid = 0x0000F121, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_FLAG_STATELESS | 0x1 - | SERVICE_VERSION_POLICY_RELAXED, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("TFM_FFM11_SERVICE3"), - .signal = TFM_FFM11_SERVICE3_SIGNAL, - .sid = 0x0000F122, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_FLAG_STATELESS | 0x2 - | SERVICE_VERSION_POLICY_RELAXED, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_FFM11_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_FFM11_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_ffm11_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_ffm11_service_runtime_item[TFM_SP_FFM11_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/secure_fw/partitions/tfm_ffm11_partition/psa_manifest/tfm_ffm11_partition.h b/bsp/secure_fw/partitions/tfm_ffm11_partition/psa_manifest/tfm_ffm11_partition.h deleted file mode 100644 index 8d0a9ac..0000000 --- a/bsp/secure_fw/partitions/tfm_ffm11_partition/psa_manifest/tfm_ffm11_partition.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_FFM11_PARTITION_H__ -#define __PSA_MANIFEST_TFM_FFM11_PARTITION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_FFM11_MODEL_IPC 1 -#define TFM_SP_FFM11_MODEL_SFN 0 - - -#define TFM_FFM11_SERVICE1_SIGNAL (1U << 4) -#define TFM_FFM11_SERVICE2_SIGNAL (1U << 5) -#define TFM_FFM11_SERVICE3_SIGNAL (1U << 6) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_FFM11_PARTITION_H__ */ diff --git a/bsp/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc b/bsp/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc deleted file mode 100644 index 3bf55fd..0000000 --- a/bsp/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include "psa_manifest/pid.h" - -#ifdef TFM_ENABLE_SLIH_TEST -#error "Framework version greater than 1.0 is not supported" -#define (1U << (31)) -#endif /* TFM_ENABLE_SLIH_TEST */ -#ifdef TFM_ENABLE_FLIH_TEST -#error "Framework version greater than 1.0 is not supported" -#define (1U << (31)) -#endif /* TFM_ENABLE_FLIH_TEST */ - -/* Definitions of the signals of the IRQs */ -const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = { -#ifdef TFM_ENABLE_SLIH_TEST - { TFM_SP_SLIH_TEST, , TFM_TIMER0_IRQ }, -#endif /* TFM_ENABLE_SLIH_TEST */ -#ifdef TFM_ENABLE_FLIH_TEST - { TFM_SP_FLIH_TEST, , TFM_TIMER0_IRQ }, -#endif /* TFM_ENABLE_FLIH_TEST */ - {0,0,0} /* add dummy element to avoid non-standard empty array */ -}; - -const size_t tfm_core_irq_signals_count = (sizeof(tfm_core_irq_signals) / - sizeof(*tfm_core_irq_signals)) - 1; /* adjust for the dummy element */ - -extern void priv_irq_handler_main(uint32_t partition_id, - uint32_t unpriv_handler, - uint32_t irq_signal, - uint32_t irq_line); - -/* Forward declarations of unpriv IRQ handlers*/ -#ifdef TFM_ENABLE_SLIH_TEST -extern void _isr(void); -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -extern void _isr(void); -#endif /* TFM_ENABLE_FLIH_TEST */ - - -/* Definitions of privileged IRQ handlers */ -#ifdef TFM_ENABLE_SLIH_TEST -void TFM_TIMER0_IRQ_Handler(void) -{ - priv_irq_handler_main(TFM_SP_SLIH_TEST, - (uint32_t)_isr, - , - TFM_TIMER0_IRQ); -} - -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -void TFM_TIMER0_IRQ_Handler(void) -{ - priv_irq_handler_main(TFM_SP_FLIH_TEST, - (uint32_t)_isr, - , - TFM_TIMER0_IRQ); -} - -#endif /* TFM_ENABLE_FLIH_TEST */ - diff --git a/bsp/secure_fw/spm/cmsis_func/tfm_spm_db_func.inc b/bsp/secure_fw/spm/cmsis_func/tfm_spm_db_func.inc deleted file mode 100644 index 5a528d5..0000000 --- a/bsp/secure_fw/spm/cmsis_func/tfm_spm_db_func.inc +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __TFM_SPM_DB_FUNC_INC__ -#define __TFM_SPM_DB_FUNC_INC__ - -#include "array.h" -#include "psa_manifest/sid.h" - -/**************************************************************************/ -/** IRQ count per partition */ -/**************************************************************************/ -#ifdef TFM_PARTITION_PROTECTED_STORAGE -#define TFM_PARTITION_TFM_SP_PS_IRQ_COUNT 0 -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -#define TFM_PARTITION_TFM_SP_ITS_IRQ_COUNT 0 -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -#define TFM_PARTITION_TFM_SP_AUDIT_LOG_IRQ_COUNT 0 -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -#define TFM_PARTITION_TFM_SP_CRYPTO_IRQ_COUNT 0 -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -#define TFM_PARTITION_TFM_SP_PLATFORM_IRQ_COUNT 0 -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -#define TFM_PARTITION_TFM_SP_INITIAL_ATTESTATION_IRQ_COUNT 0 -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -#define TFM_PARTITION_TFM_SP_CORE_TEST_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -#define TFM_PARTITION_TFM_SP_CORE_TEST_2_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -#define TFM_PARTITION_TFM_SP_SECURE_TEST_PARTITION_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -#define TFM_PARTITION_TFM_SP_IPC_SERVICE_TEST_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -#define TFM_PARTITION_TFM_SP_IPC_CLIENT_TEST_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -#define TFM_PARTITION_TFM_SP_PS_TEST_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -#define TFM_PARTITION_TFM_SP_SECURE_CLIENT_2_IRQ_COUNT 0 -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -#define TFM_PARTITION_TFM_SP_FWU_IRQ_COUNT 0 -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 -#define TFM_PARTITION_TFM_SP_FFM11_IRQ_COUNT 0 -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -#define TFM_PARTITION_TFM_SP_ATTEST_TEST_IRQ_COUNT 0 -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST -#define TFM_PARTITION_TFM_SP_SLIH_TEST_IRQ_COUNT 1 -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -#define TFM_PARTITION_TFM_SP_FLIH_TEST_IRQ_COUNT 1 -#endif /* TFM_ENABLE_FLIH_TEST */ - -/**************************************************************************/ -/** Declarations of partition init functions */ -/**************************************************************************/ -#ifdef TFM_PARTITION_PROTECTED_STORAGE -extern void tfm_ps_req_mngr_init(void); -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -extern void tfm_its_req_mngr_init(void); -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -extern void audit_core_init(void); -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -extern void tfm_crypto_init(void); -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -extern void platform_sp_init(void); -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -extern void attest_partition_init(void); -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -extern void core_test_init(void); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -extern void core_test_2_init(void); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -extern void tfm_secure_client_service_init(void); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -extern void ipc_service_test_main(void); -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -extern void ipc_client_test_main(void); -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -extern void tfm_ps_test_init(void); -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -extern void tfm_secure_client_2_init(void); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -extern void tfm_fwu_init(void); -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 -extern void tfm_ffm11_partition_main(void); -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -extern void tfm_attest_test_service_init(void); -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST -extern void tfm_slih_test_service_entry(void); -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -extern void tfm_flih_test_service_entry(void); -#endif /* TFM_ENABLE_FLIH_TEST */ - -/**************************************************************************/ -/** Context stacks for IRQ handling */ -/**************************************************************************/ -/* The max size of the context stack can be calculated as a function of the IRQ - * count of the secure partition: - * - * max_stack_size = intr_ctx_size + (IRQ_CNT * (intr_ctx_size + hndl_ctx_size)) - * - * where: - * intr_ctx: Frame pushed when the partition is interrupted - * hndl_ctx: Frame pushed when the partition is handling an interrupt - */ -static uint32_t ns_interrupt_ctx_stack[ - sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t)]; - -static uint32_t tfm_core_interrupt_ctx_stack[ - sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t)]; - -#ifdef TFM_PARTITION_PROTECTED_STORAGE -static uint32_t ctx_stack_TFM_SP_PS[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_PS_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -static uint32_t ctx_stack_TFM_SP_ITS[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_ITS_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -static uint32_t ctx_stack_TFM_SP_AUDIT_LOG[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_AUDIT_LOG_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -static uint32_t ctx_stack_TFM_SP_CRYPTO[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_CRYPTO_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -static uint32_t ctx_stack_TFM_SP_PLATFORM[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_PLATFORM_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -static uint32_t ctx_stack_TFM_SP_INITIAL_ATTESTATION[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_INITIAL_ATTESTATION_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -static uint32_t ctx_stack_TFM_SP_CORE_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_CORE_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -static uint32_t ctx_stack_TFM_SP_CORE_TEST_2[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_CORE_TEST_2_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -static uint32_t ctx_stack_TFM_SP_SECURE_TEST_PARTITION[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_SECURE_TEST_PARTITION_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -static uint32_t ctx_stack_TFM_SP_IPC_SERVICE_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_IPC_SERVICE_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -static uint32_t ctx_stack_TFM_SP_IPC_CLIENT_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_IPC_CLIENT_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -static uint32_t ctx_stack_TFM_SP_PS_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_PS_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -static uint32_t ctx_stack_TFM_SP_SECURE_CLIENT_2[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_SECURE_CLIENT_2_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -static uint32_t ctx_stack_TFM_SP_FWU[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_FWU_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 -static uint32_t ctx_stack_TFM_SP_FFM11[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_FFM11_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -static uint32_t ctx_stack_TFM_SP_ATTEST_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_ATTEST_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST -static uint32_t ctx_stack_TFM_SP_SLIH_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_SLIH_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -static uint32_t ctx_stack_TFM_SP_FLIH_TEST[ - (sizeof(struct interrupted_ctx_stack_frame_t) + - (TFM_PARTITION_TFM_SP_FLIH_TEST_IRQ_COUNT) * ( - sizeof(struct interrupted_ctx_stack_frame_t) + - sizeof(struct handler_ctx_stack_frame_t) - )) / sizeof(uint32_t)]; -#endif /* TFM_ENABLE_FLIH_TEST */ - -uint32_t *ctx_stack_list[] = -{ - ns_interrupt_ctx_stack, - tfm_core_interrupt_ctx_stack, -#ifdef TFM_PARTITION_PROTECTED_STORAGE - ctx_stack_TFM_SP_PS, -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE - ctx_stack_TFM_SP_ITS, -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ -#ifdef TFM_PARTITION_AUDIT_LOG - ctx_stack_TFM_SP_AUDIT_LOG, -#endif /* TFM_PARTITION_AUDIT_LOG */ -#ifdef TFM_PARTITION_CRYPTO - ctx_stack_TFM_SP_CRYPTO, -#endif /* TFM_PARTITION_CRYPTO */ -#ifdef TFM_PARTITION_PLATFORM - ctx_stack_TFM_SP_PLATFORM, -#endif /* TFM_PARTITION_PLATFORM */ -#ifdef TFM_PARTITION_INITIAL_ATTESTATION - ctx_stack_TFM_SP_INITIAL_ATTESTATION, -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ -#ifdef TFM_PARTITION_TEST_CORE - ctx_stack_TFM_SP_CORE_TEST, -#endif /* TFM_PARTITION_TEST_CORE */ -#ifdef TFM_PARTITION_TEST_CORE - ctx_stack_TFM_SP_CORE_TEST_2, -#endif /* TFM_PARTITION_TEST_CORE */ -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - ctx_stack_TFM_SP_SECURE_TEST_PARTITION, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ -#ifdef TFM_PARTITION_TEST_CORE_IPC - ctx_stack_TFM_SP_IPC_SERVICE_TEST, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ -#ifdef TFM_PARTITION_TEST_CORE_IPC - ctx_stack_TFM_SP_IPC_CLIENT_TEST, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ -#ifdef TFM_PARTITION_TEST_PS - ctx_stack_TFM_SP_PS_TEST, -#endif /* TFM_PARTITION_TEST_PS */ -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - ctx_stack_TFM_SP_SECURE_CLIENT_2, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ -#ifdef TFM_PARTITION_FIRMWARE_UPDATE - ctx_stack_TFM_SP_FWU, -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ -#ifdef TFM_PARTITION_FFM11 - ctx_stack_TFM_SP_FFM11, -#endif /* TFM_PARTITION_FFM11 */ -#ifdef ATTEST_TEST_GET_PUBLIC_KEY - ctx_stack_TFM_SP_ATTEST_TEST, -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ -#ifdef TFM_ENABLE_SLIH_TEST - ctx_stack_TFM_SP_SLIH_TEST, -#endif /* TFM_ENABLE_SLIH_TEST */ -#ifdef TFM_ENABLE_FLIH_TEST - ctx_stack_TFM_SP_FLIH_TEST, -#endif /* TFM_ENABLE_FLIH_TEST */ -}; - -/**************************************************************************/ -/** Dependencies array for Secure Partition */ -/**************************************************************************/ -#ifdef TFM_PARTITION_PROTECTED_STORAGE -static int32_t dependencies_TFM_SP_PS[] = -{ - TFM_CRYPTO_SID, - TFM_ITS_SET_SID, - TFM_ITS_GET_SID, - TFM_ITS_GET_INFO_SID, - TFM_ITS_REMOVE_SID, - TFM_SP_PLATFORM_NV_COUNTER_SID, -}; -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_CRYPTO -static int32_t dependencies_TFM_SP_CRYPTO[] = -{ - TFM_ITS_SET_SID, - TFM_ITS_GET_SID, - TFM_ITS_GET_INFO_SID, - TFM_ITS_REMOVE_SID, -}; -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -static int32_t dependencies_TFM_SP_INITIAL_ATTESTATION[] = -{ - TFM_CRYPTO_SID, -}; -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -static int32_t dependencies_TFM_SP_CORE_TEST[] = -{ - SPM_CORE_TEST_2_INVERT_SID, - SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID, - SPM_CORE_TEST_2_SLAVE_SERVICE_SID, -}; -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -static int32_t dependencies_TFM_SP_SECURE_TEST_PARTITION[] = -{ - TFM_SECURE_CLIENT_2_SID, - TFM_CRYPTO_SID, - TFM_PS_SET_SID, - TFM_PS_GET_SID, - TFM_PS_GET_INFO_SID, - TFM_PS_REMOVE_SID, - TFM_PS_GET_SUPPORT_SID, - TFM_ITS_SET_SID, - TFM_ITS_GET_SID, - TFM_ITS_GET_INFO_SID, - TFM_ITS_REMOVE_SID, - TFM_ATTEST_GET_TOKEN_SID, - TFM_ATTEST_GET_TOKEN_SIZE_SID, - TFM_PS_TEST_PREPARE_SID, - TFM_SP_PLATFORM_SYSTEM_RESET_SID, - TFM_SP_PLATFORM_IOCTL_SID, - TFM_FWU_WRITE_SID, - TFM_FWU_INSTALL_SID, - TFM_FWU_ABORT_SID, - TFM_FWU_QUERY_SID, - TFM_FWU_REQUEST_REBOOT_SID, - TFM_FWU_ACCEPT_SID, - TFM_FFM11_SERVICE1_SID, - TFM_ATTEST_TEST_GET_PUBLIC_KEY_SID, -}; -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -static int32_t dependencies_TFM_SP_IPC_CLIENT_TEST[] = -{ - IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID, - IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID, - IPC_SERVICE_TEST_BASIC_SID, - IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID, - TFM_SECURE_CLIENT_2_SID, -}; -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -static int32_t dependencies_TFM_SP_PS_TEST[] = -{ - TFM_CRYPTO_SID, - TFM_ITS_GET_SID, - TFM_ITS_REMOVE_SID, -}; -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -static int32_t dependencies_TFM_SP_SECURE_CLIENT_2[] = -{ - TFM_ITS_GET_SID, - TFM_CRYPTO_SID, -}; -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -static int32_t dependencies_TFM_SP_FWU[] = -{ - TFM_CRYPTO_SID, - TFM_SP_PLATFORM_SYSTEM_RESET_SID, -}; -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -static int32_t dependencies_TFM_SP_ATTEST_TEST[] = -{ - TFM_CRYPTO_SID, -}; -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -/**************************************************************************/ -/** The static data of the partition list */ -/**************************************************************************/ -const struct spm_partition_static_data_t static_data_list[] = -{ - { - .partition_id = TFM_SP_NON_SECURE_ID, - .partition_flags = 0, - }, - - { - .partition_id = TFM_SP_CORE_ID, - .partition_flags = SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_PSA_ROT, - }, - -#ifdef TFM_PARTITION_PROTECTED_STORAGE - { - .partition_id = TFM_SP_PS, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_ps_req_mngr_init, - .dependencies_num = 6, - .p_dependencies = dependencies_TFM_SP_PS, - }, -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE - { - .partition_id = TFM_SP_ITS, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_its_req_mngr_init, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG - { - .partition_id = TFM_SP_AUDIT_LOG, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = audit_core_init, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO - { - .partition_id = TFM_SP_CRYPTO, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_crypto_init, - .dependencies_num = 4, - .p_dependencies = dependencies_TFM_SP_CRYPTO, - }, -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM - { - .partition_id = TFM_SP_PLATFORM, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = platform_sp_init, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION - { - .partition_id = TFM_SP_INITIAL_ATTESTATION, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = attest_partition_init, - .dependencies_num = 1, - .p_dependencies = dependencies_TFM_SP_INITIAL_ATTESTATION, - }, -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE - { - .partition_id = TFM_SP_CORE_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = core_test_init, - .dependencies_num = 3, - .p_dependencies = dependencies_TFM_SP_CORE_TEST, - }, -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE - { - .partition_id = TFM_SP_CORE_TEST_2, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = core_test_2_init, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - { - .partition_id = TFM_SP_SECURE_TEST_PARTITION, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_secure_client_service_init, - .dependencies_num = 24, - .p_dependencies = dependencies_TFM_SP_SECURE_TEST_PARTITION, - }, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC - { - .partition_id = TFM_SP_IPC_SERVICE_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(HIGH), - .partition_init = ipc_service_test_main, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC - { - .partition_id = TFM_SP_IPC_CLIENT_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = ipc_client_test_main, - .dependencies_num = 5, - .p_dependencies = dependencies_TFM_SP_IPC_CLIENT_TEST, - }, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS - { - .partition_id = TFM_SP_PS_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_ps_test_init, - .dependencies_num = 3, - .p_dependencies = dependencies_TFM_SP_PS_TEST, - }, -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - { - .partition_id = TFM_SP_SECURE_CLIENT_2, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_secure_client_2_init, - .dependencies_num = 2, - .p_dependencies = dependencies_TFM_SP_SECURE_CLIENT_2, - }, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE - { - .partition_id = TFM_SP_FWU, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_fwu_init, - .dependencies_num = 2, - .p_dependencies = dependencies_TFM_SP_FWU, - }, -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 - { - .partition_id = TFM_SP_FFM11, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_ffm11_partition_main, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY - { - .partition_id = TFM_SP_ATTEST_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_attest_test_service_init, - .dependencies_num = 1, - .p_dependencies = dependencies_TFM_SP_ATTEST_TEST, - }, -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST - { - .partition_id = TFM_SP_SLIH_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_slih_test_service_entry, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST - { - .partition_id = TFM_SP_FLIH_TEST, - .partition_flags = 0 - | SPM_PART_FLAG_APP_ROT - , - .partition_priority = TFM_PRIORITY(NORMAL), - .partition_init = tfm_flih_test_service_entry, - .dependencies_num = 0, - .p_dependencies = NULL, - }, -#endif /* TFM_ENABLE_FLIH_TEST */ - -}; - -/**************************************************************************/ -/** The platform data of the partition list */ -/**************************************************************************/ -#ifdef TFM_PARTITION_AUDIT_LOG -const struct platform_data_t * - platform_data_list_TFM_SP_AUDIT_LOG[] = -{ -#ifdef AUDIT_UART_REDIRECTION - TFM_PERIPHERAL_UART1, -#endif /* AUDIT_UART_REDIRECTION */ - NULL -}; -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_TEST_CORE -const struct platform_data_t * - platform_data_list_TFM_SP_CORE_TEST[] = -{ - TFM_PERIPHERAL_FPGA_IO, - NULL -}; -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -const struct platform_data_t * - platform_data_list_TFM_SP_SECURE_TEST_PARTITION[] = -{ - TFM_PERIPHERAL_STD_UART, - NULL -}; -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_ENABLE_SLIH_TEST -const struct platform_data_t * - platform_data_list_TFM_SP_SLIH_TEST[] = -{ - TFM_PERIPHERAL_TIMER0, - NULL -}; -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -const struct platform_data_t * - platform_data_list_TFM_SP_FLIH_TEST[] = -{ - TFM_PERIPHERAL_TIMER0, - NULL -}; -#endif /* TFM_ENABLE_FLIH_TEST */ - -const struct platform_data_t **platform_data_list_list[] = -{ - NULL, - NULL, - -#ifdef TFM_PARTITION_PROTECTED_STORAGE - NULL, -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE - NULL, -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG - platform_data_list_TFM_SP_AUDIT_LOG, -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO - NULL, -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM - NULL, -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION - NULL, -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE - platform_data_list_TFM_SP_CORE_TEST, -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE - NULL, -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - platform_data_list_TFM_SP_SECURE_TEST_PARTITION, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC - NULL, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC - NULL, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS - NULL, -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - NULL, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE - NULL, -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 - NULL, -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY - NULL, -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST - platform_data_list_TFM_SP_SLIH_TEST, -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST - platform_data_list_TFM_SP_FLIH_TEST, -#endif /* TFM_ENABLE_FLIH_TEST */ - -}; - -/**************************************************************************/ -/** The partition list for the DB */ -/**************************************************************************/ -static struct spm_partition_desc_t partition_list [] = -{ - {{0}}, /* placeholder for Non-secure internal partition */ - {{0}}, /* placeholder for TF-M Core internal partition */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_PS */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_PROTECTED_STORAGE - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_ITS */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_AUDIT_LOG */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_AUDIT_LOG - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_AUDIT_LOG */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_CRYPTO */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_CRYPTO - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_CRYPTO */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_PLATFORM */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_PLATFORM - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_PLATFORM */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_INITIAL_ATTESTATION */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_INITIAL_ATTESTATION - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_CORE_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_CORE - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_CORE */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_CORE_TEST_2 */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_CORE - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_CORE */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_SECURE_TEST_PARTITION */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_IPC_SERVICE_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_CORE_IPC - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_IPC_CLIENT_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_CORE_IPC - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_PS_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_PS - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_PS */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_SECURE_CLIENT_2 */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_FWU */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_FIRMWARE_UPDATE - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_FFM11 */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_PARTITION_FFM11 - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_PARTITION_FFM11 */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_ATTEST_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef ATTEST_TEST_GET_PUBLIC_KEY - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_SLIH_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_ENABLE_SLIH_TEST - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_ENABLE_SLIH_TEST */ - - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for TFM_SP_FLIH_TEST */ - /* -----------------------------------------------------------------------*/ -#ifdef TFM_ENABLE_FLIH_TEST - { - /* Runtime data */ - .runtime_data = {0}, - .static_data = NULL, - .platform_data_list = NULL, - }, -#endif /* TFM_ENABLE_FLIH_TEST */ - -}; - -struct spm_partition_db_t g_spm_partition_db = { - .is_init = 0, - .partition_count = ARRAY_SIZE(partition_list), - .running_partition_idx = 0, - .partitions = partition_list, -}; - -#endif /* __TFM_SPM_DB_FUNC_INC__ */ diff --git a/bsp/secure_fw/spm/cmsis_func/tfm_veneers.c b/bsp/secure_fw/spm/cmsis_func/tfm_veneers.c deleted file mode 100644 index 6e8ab90..0000000 --- a/bsp/secure_fw/spm/cmsis_func/tfm_veneers.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include "tfm_secure_api.h" -#include "spm_partition_defs.h" - -#ifdef TFM_PARTITION_PROTECTED_STORAGE -/******** TFM_SP_PS ********/ -psa_status_t tfm_ps_set_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_ps_get_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_ps_get_info_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_ps_remove_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_ps_get_support_req(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -/******** TFM_SP_ITS ********/ -psa_status_t tfm_its_set_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_its_get_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_its_get_info_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_its_remove_req(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -/******** TFM_SP_AUDIT_LOG ********/ -psa_status_t audit_core_retrieve_record(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t audit_core_add_record(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t audit_core_get_info(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t audit_core_get_record_info(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t audit_core_delete_record(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -/******** TFM_SP_CRYPTO ********/ -psa_status_t tfm_crypto_get_key_attributes(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_open_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_close_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_reset_key_attributes(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_import_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_destroy_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_export_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_export_public_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_purge_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_copy_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_compute(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_compare(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_update(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_finish(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_verify(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_abort(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_hash_clone(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_compute(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_verify(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_sign_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_verify_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_update(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_sign_finish(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_verify_finish(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_mac_abort(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_encrypt(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_decrypt(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_generate_iv(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_set_iv(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_update(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_finish(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_cipher_abort(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_encrypt(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_decrypt(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_encrypt_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_decrypt_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_generate_nonce(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_set_nonce(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_set_lengths(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_update_ad(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_update(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_finish(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_verify(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_aead_abort(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_sign_message(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_verify_message(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_sign_hash(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_verify_hash(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_asymmetric_encrypt(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_asymmetric_decrypt(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_setup(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_get_capacity(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_set_capacity(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_input_bytes(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_input_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_key_agreement(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_output_bytes(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_output_key(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_key_derivation_abort(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_raw_key_agreement(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_generate_random(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_crypto_generate_key(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -/******** TFM_SP_PLATFORM ********/ -psa_status_t platform_sp_system_reset(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t platform_sp_ioctl(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t platform_sp_nv_counter_read(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t platform_sp_nv_counter_increment(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -/******** TFM_SP_INITIAL_ATTESTATION ********/ -psa_status_t initial_attest_get_token(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t initial_attest_get_token_size(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST ********/ -psa_status_t spm_core_test_sfn(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t spm_core_test_sfn_init_success(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t spm_core_test_sfn_direct_recursion(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST_2 ********/ -psa_status_t spm_core_test_2_slave_service(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t spm_core_test_2_sfn_invert(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t spm_core_test_2_check_caller_client_id(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t spm_core_test_2_get_every_second_byte(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -psa_status_t tfm_secure_client_service_sfn_run_tests(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -/******** TFM_SP_PS_TEST ********/ -psa_status_t tfm_ps_test_prepare(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_CLIENT_2 ********/ -psa_status_t tfm_secure_client_2_call(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -/******** TFM_SP_FWU ********/ -psa_status_t tfm_fwu_write_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_fwu_install_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_fwu_abort_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_fwu_query_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_fwu_request_reboot_req(psa_invec *, size_t, psa_outvec *, size_t); -psa_status_t tfm_fwu_accept_req(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 -/******** TFM_SP_FFM11 ********/ -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -/******** TFM_SP_ATTEST_TEST ********/ -psa_status_t tfm_attest_test_get_public_key(psa_invec *, size_t, psa_outvec *, size_t); -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST -/******** TFM_SP_SLIH_TEST ********/ -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -/******** TFM_SP_FLIH_TEST ********/ -#endif /* TFM_ENABLE_FLIH_TEST */ - - -#define TFM_VENEER_FUNCTION(partition_name, func_name, sfn_name) \ - __tfm_secure_gateway_attributes__ \ - psa_status_t func_name##_veneer(psa_invec *in_vec, \ - size_t in_len, \ - psa_outvec *out_vec, \ - size_t out_len) \ - { \ - bool is_ns = tfm_core_is_ns_client(); \ - \ - TFM_CORE_IOVEC_SFN_REQUEST(partition_name, \ - is_ns, \ - (void *) sfn_name, \ - in_vec, in_len, out_vec, out_len); \ - } - -#ifdef TFM_PARTITION_PROTECTED_STORAGE -/******** TFM_SP_PS ********/ -TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_set_req, tfm_ps_set_req) -TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_get_req, tfm_ps_get_req) -TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_get_info_req, tfm_ps_get_info_req) -TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_remove_req, tfm_ps_remove_req) -TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_get_support_req, tfm_ps_get_support_req) -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -/******** TFM_SP_ITS ********/ -TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_set_req, tfm_its_set_req) -TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_req, tfm_its_get_req) -TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_info_req, tfm_its_get_info_req) -TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_remove_req, tfm_its_remove_req) -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -/******** TFM_SP_AUDIT_LOG ********/ -TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, tfm_audit_core_retrieve_record, audit_core_retrieve_record) -TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, tfm_audit_core_add_record, audit_core_add_record) -TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, tfm_audit_core_get_info, audit_core_get_info) -TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, tfm_audit_core_get_record_info, audit_core_get_record_info) -TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, tfm_audit_core_delete_record, audit_core_delete_record) -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -/******** TFM_SP_CRYPTO ********/ -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_get_key_attributes, tfm_crypto_get_key_attributes) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_open_key, tfm_crypto_open_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_close_key, tfm_crypto_close_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_reset_key_attributes, tfm_crypto_reset_key_attributes) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_import_key, tfm_crypto_import_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_destroy_key, tfm_crypto_destroy_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_key, tfm_crypto_export_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_public_key, tfm_crypto_export_public_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_purge_key, tfm_crypto_purge_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_copy_key, tfm_crypto_copy_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_compute, tfm_crypto_hash_compute) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_compare, tfm_crypto_hash_compare) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_setup, tfm_crypto_hash_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_update, tfm_crypto_hash_update) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_finish, tfm_crypto_hash_finish) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_verify, tfm_crypto_hash_verify) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_abort, tfm_crypto_hash_abort) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_clone, tfm_crypto_hash_clone) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_compute, tfm_crypto_mac_compute) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify, tfm_crypto_mac_verify) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_sign_setup, tfm_crypto_mac_sign_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify_setup, tfm_crypto_mac_verify_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_update, tfm_crypto_mac_update) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_sign_finish, tfm_crypto_mac_sign_finish) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify_finish, tfm_crypto_mac_verify_finish) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_abort, tfm_crypto_mac_abort) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt, tfm_crypto_cipher_encrypt) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt, tfm_crypto_cipher_decrypt) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt_setup, tfm_crypto_cipher_encrypt_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt_setup, tfm_crypto_cipher_decrypt_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_generate_iv, tfm_crypto_cipher_generate_iv) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_set_iv, tfm_crypto_cipher_set_iv) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_update, tfm_crypto_cipher_update) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_finish, tfm_crypto_cipher_finish) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_abort, tfm_crypto_cipher_abort) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt, tfm_crypto_aead_encrypt) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_decrypt, tfm_crypto_aead_decrypt) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt_setup, tfm_crypto_aead_encrypt_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_decrypt_setup, tfm_crypto_aead_decrypt_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_generate_nonce, tfm_crypto_aead_generate_nonce) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_set_nonce, tfm_crypto_aead_set_nonce) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_set_lengths, tfm_crypto_aead_set_lengths) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_update_ad, tfm_crypto_aead_update_ad) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_update, tfm_crypto_aead_update) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_finish, tfm_crypto_aead_finish) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_verify, tfm_crypto_aead_verify) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_abort, tfm_crypto_aead_abort) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_sign_message, tfm_crypto_sign_message) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_verify_message, tfm_crypto_verify_message) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_sign_hash, tfm_crypto_sign_hash) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_verify_hash, tfm_crypto_verify_hash) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_asymmetric_encrypt, tfm_crypto_asymmetric_encrypt) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_asymmetric_decrypt, tfm_crypto_asymmetric_decrypt) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_setup, tfm_crypto_key_derivation_setup) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_get_capacity, tfm_crypto_key_derivation_get_capacity) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_set_capacity, tfm_crypto_key_derivation_set_capacity) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_input_bytes, tfm_crypto_key_derivation_input_bytes) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_input_key, tfm_crypto_key_derivation_input_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_key_agreement, tfm_crypto_key_derivation_key_agreement) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_output_bytes, tfm_crypto_key_derivation_output_bytes) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_output_key, tfm_crypto_key_derivation_output_key) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_abort, tfm_crypto_key_derivation_abort) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_raw_key_agreement, tfm_crypto_raw_key_agreement) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_generate_random, tfm_crypto_generate_random) -TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_generate_key, tfm_crypto_generate_key) -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -/******** TFM_SP_PLATFORM ********/ -TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, tfm_platform_sp_system_reset, platform_sp_system_reset) -TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, tfm_platform_sp_ioctl, platform_sp_ioctl) -TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, tfm_platform_sp_nv_counter_read, platform_sp_nv_counter_read) -TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, tfm_platform_sp_nv_counter_increment, platform_sp_nv_counter_increment) -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -/******** TFM_SP_INITIAL_ATTESTATION ********/ -TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, tfm_initial_attest_get_token, initial_attest_get_token) -TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, tfm_initial_attest_get_token_size, initial_attest_get_token_size) -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST ********/ -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, tfm_spm_core_test_sfn, spm_core_test_sfn) -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, tfm_spm_core_test_sfn_init_success, spm_core_test_sfn_init_success) -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, tfm_spm_core_test_sfn_direct_recursion, spm_core_test_sfn_direct_recursion) -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST_2 ********/ -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, tfm_spm_core_test_2_slave_service, spm_core_test_2_slave_service) -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, tfm_spm_core_test_2_sfn_invert, spm_core_test_2_sfn_invert) -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, tfm_spm_core_test_2_check_caller_client_id, spm_core_test_2_check_caller_client_id) -TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, tfm_spm_core_test_2_get_every_second_byte, spm_core_test_2_get_every_second_byte) -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -TFM_VENEER_FUNCTION(TFM_SP_SECURE_TEST_PARTITION, tfm_secure_client_service_sfn_run_tests, tfm_secure_client_service_sfn_run_tests) -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_PS -/******** TFM_SP_PS_TEST ********/ -TFM_VENEER_FUNCTION(TFM_SP_PS_TEST, tfm_ps_test_prepare, tfm_ps_test_prepare) -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_CLIENT_2 ********/ -TFM_VENEER_FUNCTION(TFM_SP_SECURE_CLIENT_2, tfm_secure_client_2_call, tfm_secure_client_2_call) -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_FIRMWARE_UPDATE -/******** TFM_SP_FWU ********/ -TFM_VENEER_FUNCTION(TFM_SP_FWU, tfm_fwu_write_req, tfm_fwu_write_req) -TFM_VENEER_FUNCTION(TFM_SP_FWU, tfm_fwu_install_req, tfm_fwu_install_req) -TFM_VENEER_FUNCTION(TFM_SP_FWU, tfm_fwu_abort_req, tfm_fwu_abort_req) -TFM_VENEER_FUNCTION(TFM_SP_FWU, tfm_fwu_query_req, tfm_fwu_query_req) -TFM_VENEER_FUNCTION(TFM_SP_FWU, tfm_fwu_request_reboot_req, tfm_fwu_request_reboot_req) -TFM_VENEER_FUNCTION(TFM_SP_FWU, tfm_fwu_accept_req, tfm_fwu_accept_req) -#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ - -#ifdef TFM_PARTITION_FFM11 -/******** TFM_SP_FFM11 ********/ -#endif /* TFM_PARTITION_FFM11 */ - -#ifdef ATTEST_TEST_GET_PUBLIC_KEY -/******** TFM_SP_ATTEST_TEST ********/ -TFM_VENEER_FUNCTION(TFM_SP_ATTEST_TEST, tfm_attest_test_get_public_key, tfm_attest_test_get_public_key) -#endif /* ATTEST_TEST_GET_PUBLIC_KEY */ - -#ifdef TFM_ENABLE_SLIH_TEST -/******** TFM_SP_SLIH_TEST ********/ -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -/******** TFM_SP_FLIH_TEST ********/ -#endif /* TFM_ENABLE_FLIH_TEST */ - diff --git a/bsp/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc b/bsp/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc deleted file mode 100644 index b02f9c6..0000000 --- a/bsp/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -/* Definitions of privileged IRQ handlers (if any) */ -#ifdef TFM_ENABLE_SLIH_TEST -#include "/home/pawszc02/devsummit/tf-m/clang_test/generated/test_services/tfm_slih_test_service/psa_manifest/tfm_slih_test_service.h" -extern struct partition_tfm_sp_slih_test_load_info_t tfm_sp_slih_test_load; -void TFM_TIMER0_IRQ_Handler(void) -{ - spm_interrupt_handler((struct partition_load_info_t *)&tfm_sp_slih_test_load, TFM_TIMER0_IRQ_SIGNAL, TFM_TIMER0_IRQ, NULL); -} -#endif /* TFM_ENABLE_SLIH_TEST */ - -#ifdef TFM_ENABLE_FLIH_TEST -#include "/home/pawszc02/devsummit/tf-m/clang_test/generated/test_services/tfm_flih_test_service/psa_manifest/tfm_flih_test_service.h" -extern struct partition_tfm_sp_flih_test_load_info_t tfm_sp_flih_test_load; -void TFM_TIMER0_IRQ_Handler(void) -{ - spm_interrupt_handler((struct partition_load_info_t *)&tfm_sp_flih_test_load, TFM_TIMER0_IRQ_SIGNAL, TFM_TIMER0_IRQ, tfm_timer0_irq_flih); -} -#endif /* TFM_ENABLE_FLIH_TEST */ - diff --git a/bsp/test_services/tfm_attest_test_service/auto_generated/intermedia_tfm_attest_test_service.c b/bsp/test_services/tfm_attest_test_service/auto_generated/intermedia_tfm_attest_test_service.c deleted file mode 100644 index 01cb76d..0000000 --- a/bsp/test_services/tfm_attest_test_service/auto_generated/intermedia_tfm_attest_test_service.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_attest_test_stack[0x0400] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_attest_test_service/auto_generated/load_info_tfm_attest_test_service.c b/bsp/test_services/tfm_attest_test_service/auto_generated/load_info_tfm_attest_test_service.c deleted file mode 100644 index 7bb6049..0000000 --- a/bsp/test_services/tfm_attest_test_service/auto_generated/load_info_tfm_attest_test_service.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_attest_test_service.h" - -#define TFM_SP_ATTEST_TEST_NDEPS (1) -#define TFM_SP_ATTEST_TEST_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_ATTEST_TEST_NASSETS (0 + 1) -#else -#define TFM_SP_ATTEST_TEST_NASSETS (0) -#endif -#define TFM_SP_ATTEST_TEST_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_ATTEST_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_ATTEST_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_attest_test_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_attest_test_service_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_attest_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_ATTEST_TEST_NDEPS]; - struct service_load_info_t services[TFM_SP_ATTEST_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_ATTEST_TEST_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_attest_test_load_info_t tfm_sp_attest_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_ATTEST_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_attest_test_service_init), - .stack_size = 0x0400, - .heap_size = 0, - .ndeps = TFM_SP_ATTEST_TEST_NDEPS, - .nservices = TFM_SP_ATTEST_TEST_NSERVS, - .nassets = TFM_SP_ATTEST_TEST_NASSETS, - .nirqs = TFM_SP_ATTEST_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_attest_test_stack, - .heap_addr = 0, - .deps = { - TFM_CRYPTO_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_ATTEST_TEST_GET_PUBLIC_KEY"), - .signal = TFM_ATTEST_TEST_GET_PUBLIC_KEY_SIGNAL, - .sid = 0x0000F140, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_ATTEST_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_ATTEST_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_attest_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_attest_test_service_runtime_item[TFM_SP_ATTEST_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_attest_test_service/psa_manifest/tfm_attest_test_service.h b/bsp/test_services/tfm_attest_test_service/psa_manifest/tfm_attest_test_service.h deleted file mode 100644 index c7d35d2..0000000 --- a/bsp/test_services/tfm_attest_test_service/psa_manifest/tfm_attest_test_service.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_ATTEST_TEST_SERVICE_H__ -#define __PSA_MANIFEST_TFM_ATTEST_TEST_SERVICE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_ATTEST_TEST_MODEL_IPC 1 -#define TFM_SP_ATTEST_TEST_MODEL_SFN 0 - - -#define TFM_ATTEST_TEST_GET_PUBLIC_KEY_SIGNAL (1U << 4) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_ATTEST_TEST_SERVICE_H__ */ diff --git a/bsp/test_services/tfm_core_test/auto_generated/intermedia_tfm_ss_core_test.c b/bsp/test_services/tfm_core_test/auto_generated/intermedia_tfm_ss_core_test.c deleted file mode 100644 index 20e415b..0000000 --- a/bsp/test_services/tfm_core_test/auto_generated/intermedia_tfm_ss_core_test.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_core_test_stack[0x0380] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_core_test/auto_generated/load_info_tfm_ss_core_test.c b/bsp/test_services/tfm_core_test/auto_generated/load_info_tfm_ss_core_test.c deleted file mode 100644 index 9d4202d..0000000 --- a/bsp/test_services/tfm_core_test/auto_generated/load_info_tfm_ss_core_test.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_ss_core_test.h" - -#define TFM_SP_CORE_TEST_NDEPS (3) -#define TFM_SP_CORE_TEST_NSERVS (10) -#if TFM_LVL == 3 -#define TFM_SP_CORE_TEST_NASSETS (1 + 1) -#else -#define TFM_SP_CORE_TEST_NASSETS (1) -#endif -#define TFM_SP_CORE_TEST_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_CORE_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_CORE_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_core_test_stack[]; - -/* Entrypoint function declaration */ -extern void core_test_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_core_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_CORE_TEST_NDEPS]; - struct service_load_info_t services[TFM_SP_CORE_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_CORE_TEST_NASSETS]; -#else - struct asset_desc_t assets[TFM_SP_CORE_TEST_NASSETS]; -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_core_test_load_info_t tfm_sp_core_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_CORE_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(core_test_init), - .stack_size = 0x0380, - .heap_size = 0, - .ndeps = TFM_SP_CORE_TEST_NDEPS, - .nservices = TFM_SP_CORE_TEST_NSERVS, - .nassets = TFM_SP_CORE_TEST_NASSETS, - .nirqs = TFM_SP_CORE_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_core_test_stack, - .heap_addr = 0, - .deps = { - SPM_CORE_TEST_2_INVERT_SID, - SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID, - SPM_CORE_TEST_2_SLAVE_SERVICE_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_INIT_SUCCESS"), - .signal = SPM_CORE_TEST_INIT_SUCCESS_SIGNAL, - .sid = 0x0000F020, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_DIRECT_RECURSION"), - .signal = SPM_CORE_TEST_DIRECT_RECURSION_SIGNAL, - .sid = 0x0000F021, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_SS_TO_SS"), - .signal = SPM_CORE_TEST_SS_TO_SS_SIGNAL, - .sid = 0x0000F024, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_SS_TO_SS_BUFFER"), - .signal = SPM_CORE_TEST_SS_TO_SS_BUFFER_SIGNAL, - .sid = 0x0000F025, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_OUTVEC_WRITE"), - .signal = SPM_CORE_TEST_OUTVEC_WRITE_SIGNAL, - .sid = 0x0000F026, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_PERIPHERAL_ACCESS"), - .signal = SPM_CORE_TEST_PERIPHERAL_ACCESS_SIGNAL, - .sid = 0x0000F027, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_GET_CALLER_CLIENT_ID"), - .signal = SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SIGNAL, - .sid = 0x0000F028, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_SPM_REQUEST"), - .signal = SPM_CORE_TEST_SPM_REQUEST_SIGNAL, - .sid = 0x0000F029, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_BLOCK"), - .signal = SPM_CORE_TEST_BLOCK_SIGNAL, - .sid = 0x0000F02A, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_NS_THREAD"), - .signal = SPM_CORE_TEST_NS_THREAD_SIGNAL, - .sid = 0x0000F02B, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_CORE_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_CORE_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_FPGA_IO), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#else - .assets = { - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_FPGA_IO), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_core_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_core_test_service_runtime_item[TFM_SP_CORE_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_core_test/psa_manifest/tfm_ss_core_test.h b/bsp/test_services/tfm_core_test/psa_manifest/tfm_ss_core_test.h deleted file mode 100644 index bb85d37..0000000 --- a/bsp/test_services/tfm_core_test/psa_manifest/tfm_ss_core_test.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_SS_CORE_TEST_H__ -#define __PSA_MANIFEST_TFM_SS_CORE_TEST_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_CORE_TEST_MODEL_IPC 1 -#define TFM_SP_CORE_TEST_MODEL_SFN 0 - - -#define SPM_CORE_TEST_INIT_SUCCESS_SIGNAL (1U << 4) -#define SPM_CORE_TEST_DIRECT_RECURSION_SIGNAL (1U << 5) -#define SPM_CORE_TEST_SS_TO_SS_SIGNAL (1U << 6) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SIGNAL (1U << 7) -#define SPM_CORE_TEST_OUTVEC_WRITE_SIGNAL (1U << 8) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SIGNAL (1U << 9) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SIGNAL (1U << 10) -#define SPM_CORE_TEST_SPM_REQUEST_SIGNAL (1U << 11) -#define SPM_CORE_TEST_BLOCK_SIGNAL (1U << 12) -#define SPM_CORE_TEST_NS_THREAD_SIGNAL (1U << 13) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_SS_CORE_TEST_H__ */ diff --git a/bsp/test_services/tfm_core_test_2/auto_generated/intermedia_tfm_ss_core_test_2.c b/bsp/test_services/tfm_core_test_2/auto_generated/intermedia_tfm_ss_core_test_2.c deleted file mode 100644 index 9033ee7..0000000 --- a/bsp/test_services/tfm_core_test_2/auto_generated/intermedia_tfm_ss_core_test_2.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_core_test_2_stack[0x0280] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_core_test_2/auto_generated/load_info_tfm_ss_core_test_2.c b/bsp/test_services/tfm_core_test_2/auto_generated/load_info_tfm_ss_core_test_2.c deleted file mode 100644 index d70aeec..0000000 --- a/bsp/test_services/tfm_core_test_2/auto_generated/load_info_tfm_ss_core_test_2.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_ss_core_test_2.h" - -#define TFM_SP_CORE_TEST_2_NDEPS (0) -#define TFM_SP_CORE_TEST_2_NSERVS (4) -#if TFM_LVL == 3 -#define TFM_SP_CORE_TEST_2_NASSETS (0 + 1) -#else -#define TFM_SP_CORE_TEST_2_NASSETS (0) -#endif -#define TFM_SP_CORE_TEST_2_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_CORE_TEST_2_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_CORE_TEST_2_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_core_test_2_stack[]; - -/* Entrypoint function declaration */ -extern void core_test_2_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_core_test_2_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_CORE_TEST_2_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_CORE_TEST_2_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_core_test_2_load_info_t tfm_sp_core_test_2_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_CORE_TEST_2, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(core_test_2_init), - .stack_size = 0x0280, - .heap_size = 0, - .ndeps = TFM_SP_CORE_TEST_2_NDEPS, - .nservices = TFM_SP_CORE_TEST_2_NSERVS, - .nassets = TFM_SP_CORE_TEST_2_NASSETS, - .nirqs = TFM_SP_CORE_TEST_2_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_core_test_2_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_2_SLAVE_SERVICE"), - .signal = SPM_CORE_TEST_2_SLAVE_SERVICE_SIGNAL, - .sid = 0x0000F040, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID"), - .signal = SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SIGNAL, - .sid = 0x0000F041, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE"), - .signal = SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SIGNAL, - .sid = 0x0000F042, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("SPM_CORE_TEST_2_INVERT"), - .signal = SPM_CORE_TEST_2_INVERT_SIGNAL, - .sid = 0x0000F043, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_CORE_TEST_2_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_CORE_TEST_2_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_core_test_2_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_core_test_2_service_runtime_item[TFM_SP_CORE_TEST_2_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_core_test_2/psa_manifest/tfm_ss_core_test_2.h b/bsp/test_services/tfm_core_test_2/psa_manifest/tfm_ss_core_test_2.h deleted file mode 100644 index 92a9a00..0000000 --- a/bsp/test_services/tfm_core_test_2/psa_manifest/tfm_ss_core_test_2.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_SS_CORE_TEST_2_H__ -#define __PSA_MANIFEST_TFM_SS_CORE_TEST_2_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_CORE_TEST_2_MODEL_IPC 1 -#define TFM_SP_CORE_TEST_2_MODEL_SFN 0 - - -#define SPM_CORE_TEST_2_SLAVE_SERVICE_SIGNAL (1U << 4) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SIGNAL (1U << 5) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SIGNAL (1U << 6) -#define SPM_CORE_TEST_2_INVERT_SIGNAL (1U << 7) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_SS_CORE_TEST_2_H__ */ diff --git a/bsp/test_services/tfm_flih_test_service/auto_generated/intermedia_tfm_flih_test_service.c b/bsp/test_services/tfm_flih_test_service/auto_generated/intermedia_tfm_flih_test_service.c deleted file mode 100644 index 322f3d6..0000000 --- a/bsp/test_services/tfm_flih_test_service/auto_generated/intermedia_tfm_flih_test_service.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_flih_test_stack[0x0400] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_flih_test_service/auto_generated/load_info_tfm_flih_test_service.c b/bsp/test_services/tfm_flih_test_service/auto_generated/load_info_tfm_flih_test_service.c deleted file mode 100644 index 93c2ed3..0000000 --- a/bsp/test_services/tfm_flih_test_service/auto_generated/load_info_tfm_flih_test_service.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_flih_test_service.h" - -#define TFM_SP_FLIH_TEST_NDEPS (0) -#define TFM_SP_FLIH_TEST_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_FLIH_TEST_NASSETS (1 + 1) -#else -#define TFM_SP_FLIH_TEST_NASSETS (1) -#endif -#define TFM_SP_FLIH_TEST_NIRQS (1) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_FLIH_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_FLIH_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_flih_test_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_flih_test_service_entry(void); - -/* partition load info type definition */ -struct partition_tfm_sp_flih_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_FLIH_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_FLIH_TEST_NASSETS]; -#else - struct asset_desc_t assets[TFM_SP_FLIH_TEST_NASSETS]; -#endif - struct irq_load_info_t irqs[TFM_SP_FLIH_TEST_NIRQS]; -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_flih_test_load_info_t tfm_sp_flih_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0101 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_FLIH_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_flih_test_service_entry), - .stack_size = 0x0400, - .heap_size = 0, - .ndeps = TFM_SP_FLIH_TEST_NDEPS, - .nservices = TFM_SP_FLIH_TEST_NSERVS, - .nassets = TFM_SP_FLIH_TEST_NASSETS, - .nirqs = TFM_SP_FLIH_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_flih_test_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_FLIH_TEST_CASE"), - .signal = TFM_FLIH_TEST_CASE_SIGNAL, - .sid = 0x0000F0B0, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_FLAG_STATELESS | 0x5 - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_FLIH_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_FLIH_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_TIMER0), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#else - .assets = { - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_TIMER0), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#endif - .irqs = { - { - .source = TFM_TIMER0_IRQ, - .flih_func = (uint32_t)tfm_timer0_irq_flih, - .signal = TFM_TIMER0_IRQ_SIGNAL, - }, - }, -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_flih_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_flih_test_service_runtime_item[TFM_SP_FLIH_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_flih_test_service/psa_manifest/tfm_flih_test_service.h b/bsp/test_services/tfm_flih_test_service/psa_manifest/tfm_flih_test_service.h deleted file mode 100644 index 2669307..0000000 --- a/bsp/test_services/tfm_flih_test_service/psa_manifest/tfm_flih_test_service.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_FLIH_TEST_SERVICE_H__ -#define __PSA_MANIFEST_TFM_FLIH_TEST_SERVICE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_FLIH_TEST_MODEL_IPC 1 -#define TFM_SP_FLIH_TEST_MODEL_SFN 0 - - -#define TFM_FLIH_TEST_CASE_SIGNAL (1U << 4) - -#define TFM_TIMER0_IRQ_SIGNAL (1U << 31) -psa_flih_result_t tfm_timer0_irq_flih(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_FLIH_TEST_SERVICE_H__ */ diff --git a/bsp/test_services/tfm_ipc_client/auto_generated/intermedia_tfm_ipc_client_test.c b/bsp/test_services/tfm_ipc_client/auto_generated/intermedia_tfm_ipc_client_test.c deleted file mode 100644 index f70c9e3..0000000 --- a/bsp/test_services/tfm_ipc_client/auto_generated/intermedia_tfm_ipc_client_test.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_ipc_client_test_stack[0x0300] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_ipc_client/auto_generated/load_info_tfm_ipc_client_test.c b/bsp/test_services/tfm_ipc_client/auto_generated/load_info_tfm_ipc_client_test.c deleted file mode 100644 index 753e00b..0000000 --- a/bsp/test_services/tfm_ipc_client/auto_generated/load_info_tfm_ipc_client_test.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_ipc_client_test.h" - -#define TFM_SP_IPC_CLIENT_TEST_NDEPS (5) -#define TFM_SP_IPC_CLIENT_TEST_NSERVS (6) -#if TFM_LVL == 3 -#define TFM_SP_IPC_CLIENT_TEST_NASSETS (0 + 1) -#else -#define TFM_SP_IPC_CLIENT_TEST_NASSETS (0) -#endif -#define TFM_SP_IPC_CLIENT_TEST_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_IPC_CLIENT_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_IPC_CLIENT_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_ipc_client_test_stack[]; - -/* Entrypoint function declaration */ -extern void ipc_client_test_main(void); - -/* partition load info type definition */ -struct partition_tfm_sp_ipc_client_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_IPC_CLIENT_TEST_NDEPS]; - struct service_load_info_t services[TFM_SP_IPC_CLIENT_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_IPC_CLIENT_TEST_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_ipc_client_test_load_info_t tfm_sp_ipc_client_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_IPC_CLIENT_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(ipc_client_test_main), - .stack_size = 0x0300, - .heap_size = 0, - .ndeps = TFM_SP_IPC_CLIENT_TEST_NDEPS, - .nservices = TFM_SP_IPC_CLIENT_TEST_NSERVS, - .nassets = TFM_SP_IPC_CLIENT_TEST_NASSETS, - .nirqs = TFM_SP_IPC_CLIENT_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_ipc_client_test_stack, - .heap_addr = 0, - .deps = { - IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID, - IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID, - IPC_SERVICE_TEST_BASIC_SID, - IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID, - TFM_SECURE_CLIENT_2_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("IPC_CLIENT_TEST_BASIC"), - .signal = IPC_CLIENT_TEST_BASIC_SIGNAL, - .sid = 0x0000F060, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM"), - .signal = IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SIGNAL, - .sid = 0x0000F061, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM"), - .signal = IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL, - .sid = 0x0000F062, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM"), - .signal = IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SIGNAL, - .sid = 0x0000F063, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_CLIENT_TEST_MEM_CHECK"), - .signal = IPC_CLIENT_TEST_MEM_CHECK_SIGNAL, - .sid = 0x0000F064, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_CLIENT_TEST_RETRIEVE_APP_MEM"), - .signal = IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SIGNAL, - .sid = 0x0000F065, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_IPC_CLIENT_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_IPC_CLIENT_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_ipc_client_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_ipc_client_test_service_runtime_item[TFM_SP_IPC_CLIENT_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h b/bsp/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h deleted file mode 100644 index f215faf..0000000 --- a/bsp/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_IPC_CLIENT_TEST_H__ -#define __PSA_MANIFEST_TFM_IPC_CLIENT_TEST_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_IPC_CLIENT_TEST_MODEL_IPC 1 -#define TFM_SP_IPC_CLIENT_TEST_MODEL_SFN 0 - - -#define IPC_CLIENT_TEST_BASIC_SIGNAL (1U << 4) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SIGNAL (1U << 5) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL (1U << 6) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SIGNAL (1U << 7) -#define IPC_CLIENT_TEST_MEM_CHECK_SIGNAL (1U << 8) -#define IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SIGNAL (1U << 9) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_IPC_CLIENT_TEST_H__ */ diff --git a/bsp/test_services/tfm_ipc_service/auto_generated/intermedia_tfm_ipc_service_test.c b/bsp/test_services/tfm_ipc_service/auto_generated/intermedia_tfm_ipc_service_test.c deleted file mode 100644 index 44a7659..0000000 --- a/bsp/test_services/tfm_ipc_service/auto_generated/intermedia_tfm_ipc_service_test.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_ipc_service_test_stack[0x0220] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_ipc_service/auto_generated/load_info_tfm_ipc_service_test.c b/bsp/test_services/tfm_ipc_service/auto_generated/load_info_tfm_ipc_service_test.c deleted file mode 100644 index 6fcf52d..0000000 --- a/bsp/test_services/tfm_ipc_service/auto_generated/load_info_tfm_ipc_service_test.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_ipc_service_test.h" - -#define TFM_SP_IPC_SERVICE_TEST_NDEPS (0) -#define TFM_SP_IPC_SERVICE_TEST_NSERVS (5) -#if TFM_LVL == 3 -#define TFM_SP_IPC_SERVICE_TEST_NASSETS (0 + 1) -#else -#define TFM_SP_IPC_SERVICE_TEST_NASSETS (0) -#endif -#define TFM_SP_IPC_SERVICE_TEST_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_IPC_SERVICE_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_IPC_SERVICE_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_ipc_service_test_stack[]; - -/* Entrypoint function declaration */ -extern void ipc_service_test_main(void); - -/* partition load info type definition */ -struct partition_tfm_sp_ipc_service_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_IPC_SERVICE_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_IPC_SERVICE_TEST_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_ipc_service_test_load_info_t tfm_sp_ipc_service_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_IPC_SERVICE_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_HIGH, - .entry = ENTRY_TO_POSITION(ipc_service_test_main), - .stack_size = 0x0220, - .heap_size = 0, - .ndeps = TFM_SP_IPC_SERVICE_TEST_NDEPS, - .nservices = TFM_SP_IPC_SERVICE_TEST_NSERVS, - .nassets = TFM_SP_IPC_SERVICE_TEST_NASSETS, - .nirqs = TFM_SP_IPC_SERVICE_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_ipc_service_test_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("IPC_SERVICE_TEST_BASIC"), - .signal = IPC_SERVICE_TEST_BASIC_SIGNAL, - .sid = 0x0000F080, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM"), - .signal = IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SIGNAL, - .sid = 0x0000F081, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM"), - .signal = IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL, - .sid = 0x0000F082, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM"), - .signal = IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SIGNAL, - .sid = 0x0000F083, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - { - .name_strid = STRING_PTR_TO_STRID("IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR"), - .signal = IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SIGNAL, - .sid = 0x0000F084, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_IPC_SERVICE_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_IPC_SERVICE_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_ipc_service_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_ipc_service_test_service_runtime_item[TFM_SP_IPC_SERVICE_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_test.h b/bsp/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_test.h deleted file mode 100644 index 52400ce..0000000 --- a/bsp/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_test.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_IPC_SERVICE_TEST_H__ -#define __PSA_MANIFEST_TFM_IPC_SERVICE_TEST_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_IPC_SERVICE_TEST_MODEL_IPC 1 -#define TFM_SP_IPC_SERVICE_TEST_MODEL_SFN 0 - - -#define IPC_SERVICE_TEST_BASIC_SIGNAL (1U << 4) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SIGNAL (1U << 5) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL (1U << 6) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SIGNAL (1U << 7) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SIGNAL (1U << 8) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_IPC_SERVICE_TEST_H__ */ diff --git a/bsp/test_services/tfm_ps_test_service/auto_generated/intermedia_tfm_ps_test_service.c b/bsp/test_services/tfm_ps_test_service/auto_generated/intermedia_tfm_ps_test_service.c deleted file mode 100644 index 18cfa14..0000000 --- a/bsp/test_services/tfm_ps_test_service/auto_generated/intermedia_tfm_ps_test_service.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_ps_test_stack[0x500] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_ps_test_service/auto_generated/load_info_tfm_ps_test_service.c b/bsp/test_services/tfm_ps_test_service/auto_generated/load_info_tfm_ps_test_service.c deleted file mode 100644 index 3ddc055..0000000 --- a/bsp/test_services/tfm_ps_test_service/auto_generated/load_info_tfm_ps_test_service.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_ps_test_service.h" - -#define TFM_SP_PS_TEST_NDEPS (3) -#define TFM_SP_PS_TEST_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_PS_TEST_NASSETS (0 + 1) -#else -#define TFM_SP_PS_TEST_NASSETS (0) -#endif -#define TFM_SP_PS_TEST_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_PS_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_PS_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_ps_test_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_ps_test_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_ps_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_PS_TEST_NDEPS]; - struct service_load_info_t services[TFM_SP_PS_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_PS_TEST_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_ps_test_load_info_t tfm_sp_ps_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_PS_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_ps_test_init), - .stack_size = 0x500, - .heap_size = 0, - .ndeps = TFM_SP_PS_TEST_NDEPS, - .nservices = TFM_SP_PS_TEST_NSERVS, - .nassets = TFM_SP_PS_TEST_NASSETS, - .nirqs = TFM_SP_PS_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_ps_test_stack, - .heap_addr = 0, - .deps = { - TFM_CRYPTO_SID, - TFM_ITS_GET_SID, - TFM_ITS_REMOVE_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_PS_TEST_PREPARE"), - .signal = TFM_PS_TEST_PREPARE_SIGNAL, - .sid = 0x0000F0C0, - .flags = 0 - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_PS_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_PS_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_ps_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_ps_test_service_runtime_item[TFM_SP_PS_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_ps_test_service/psa_manifest/tfm_ps_test_service.h b/bsp/test_services/tfm_ps_test_service/psa_manifest/tfm_ps_test_service.h deleted file mode 100644 index 5571ea8..0000000 --- a/bsp/test_services/tfm_ps_test_service/psa_manifest/tfm_ps_test_service.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_PS_TEST_SERVICE_H__ -#define __PSA_MANIFEST_TFM_PS_TEST_SERVICE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_PS_TEST_MODEL_IPC 1 -#define TFM_SP_PS_TEST_MODEL_SFN 0 - - -#define TFM_PS_TEST_PREPARE_SIGNAL (1U << 4) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_PS_TEST_SERVICE_H__ */ diff --git a/bsp/test_services/tfm_secure_client_2/auto_generated/intermedia_tfm_secure_client_2.c b/bsp/test_services/tfm_secure_client_2/auto_generated/intermedia_tfm_secure_client_2.c deleted file mode 100644 index 352bcda..0000000 --- a/bsp/test_services/tfm_secure_client_2/auto_generated/intermedia_tfm_secure_client_2.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_secure_client_2_stack[0x300] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_secure_client_2/auto_generated/load_info_tfm_secure_client_2.c b/bsp/test_services/tfm_secure_client_2/auto_generated/load_info_tfm_secure_client_2.c deleted file mode 100644 index 115a8d9..0000000 --- a/bsp/test_services/tfm_secure_client_2/auto_generated/load_info_tfm_secure_client_2.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_secure_client_2.h" - -#define TFM_SP_SECURE_CLIENT_2_NDEPS (2) -#define TFM_SP_SECURE_CLIENT_2_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_SECURE_CLIENT_2_NASSETS (0 + 1) -#else -#define TFM_SP_SECURE_CLIENT_2_NASSETS (0) -#endif -#define TFM_SP_SECURE_CLIENT_2_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_SECURE_CLIENT_2_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_SECURE_CLIENT_2_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_secure_client_2_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_secure_client_2_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_secure_client_2_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_SECURE_CLIENT_2_NDEPS]; - struct service_load_info_t services[TFM_SP_SECURE_CLIENT_2_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_SECURE_CLIENT_2_NASSETS]; -#else -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_secure_client_2_load_info_t tfm_sp_secure_client_2_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_SECURE_CLIENT_2, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_secure_client_2_init), - .stack_size = 0x300, - .heap_size = 0, - .ndeps = TFM_SP_SECURE_CLIENT_2_NDEPS, - .nservices = TFM_SP_SECURE_CLIENT_2_NSERVS, - .nassets = TFM_SP_SECURE_CLIENT_2_NASSETS, - .nirqs = TFM_SP_SECURE_CLIENT_2_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_secure_client_2_stack, - .heap_addr = 0, - .deps = { - TFM_ITS_GET_SID, - TFM_CRYPTO_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_SECURE_CLIENT_2"), - .signal = TFM_SECURE_CLIENT_2_SIGNAL, - .sid = 0x0000F0E0, - .flags = 0 - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_SECURE_CLIENT_2_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_SECURE_CLIENT_2_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - }, -#else -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_secure_client_2_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_secure_client_2_service_runtime_item[TFM_SP_SECURE_CLIENT_2_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h b/bsp/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h deleted file mode 100644 index 3bc6589..0000000 --- a/bsp/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_SECURE_CLIENT_2_H__ -#define __PSA_MANIFEST_TFM_SECURE_CLIENT_2_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_SECURE_CLIENT_2_MODEL_IPC 1 -#define TFM_SP_SECURE_CLIENT_2_MODEL_SFN 0 - - -#define TFM_SECURE_CLIENT_2_SIGNAL (1U << 4) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_SECURE_CLIENT_2_H__ */ diff --git a/bsp/test_services/tfm_secure_client_service/auto_generated/intermedia_tfm_secure_client_service.c b/bsp/test_services/tfm_secure_client_service/auto_generated/intermedia_tfm_secure_client_service.c deleted file mode 100644 index b116415..0000000 --- a/bsp/test_services/tfm_secure_client_service/auto_generated/intermedia_tfm_secure_client_service.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_secure_test_partition_stack[0x0D00] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_secure_client_service/auto_generated/load_info_tfm_secure_client_service.c b/bsp/test_services/tfm_secure_client_service/auto_generated/load_info_tfm_secure_client_service.c deleted file mode 100644 index 91041b5..0000000 --- a/bsp/test_services/tfm_secure_client_service/auto_generated/load_info_tfm_secure_client_service.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_secure_client_service.h" - -#define TFM_SP_SECURE_TEST_PARTITION_NDEPS (24) -#define TFM_SP_SECURE_TEST_PARTITION_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_SECURE_TEST_PARTITION_NASSETS (1 + 1) -#else -#define TFM_SP_SECURE_TEST_PARTITION_NASSETS (1) -#endif -#define TFM_SP_SECURE_TEST_PARTITION_NIRQS (0) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_SECURE_TEST_PARTITION_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_SECURE_TEST_PARTITION_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_secure_test_partition_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_secure_client_service_init(void); - -/* partition load info type definition */ -struct partition_tfm_sp_secure_test_partition_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - uint32_t deps[TFM_SP_SECURE_TEST_PARTITION_NDEPS]; - struct service_load_info_t services[TFM_SP_SECURE_TEST_PARTITION_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_SECURE_TEST_PARTITION_NASSETS]; -#else - struct asset_desc_t assets[TFM_SP_SECURE_TEST_PARTITION_NASSETS]; -#endif -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_secure_test_partition_load_info_t tfm_sp_secure_test_partition_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0100 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_SECURE_TEST_PARTITION, - .flags = 0 - | SPM_PART_FLAG_IPC - | SPM_PART_FLAG_PSA_ROT - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_secure_client_service_init), - .stack_size = 0x0D00, - .heap_size = 0, - .ndeps = TFM_SP_SECURE_TEST_PARTITION_NDEPS, - .nservices = TFM_SP_SECURE_TEST_PARTITION_NSERVS, - .nassets = TFM_SP_SECURE_TEST_PARTITION_NASSETS, - .nirqs = TFM_SP_SECURE_TEST_PARTITION_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_secure_test_partition_stack, - .heap_addr = 0, - .deps = { - TFM_SECURE_CLIENT_2_SID, - TFM_CRYPTO_SID, - TFM_PS_SET_SID, - TFM_PS_GET_SID, - TFM_PS_GET_INFO_SID, - TFM_PS_REMOVE_SID, - TFM_PS_GET_SUPPORT_SID, - TFM_ITS_SET_SID, - TFM_ITS_GET_SID, - TFM_ITS_GET_INFO_SID, - TFM_ITS_REMOVE_SID, - TFM_ATTEST_GET_TOKEN_SID, - TFM_ATTEST_GET_TOKEN_SIZE_SID, - TFM_PS_TEST_PREPARE_SID, - TFM_SP_PLATFORM_SYSTEM_RESET_SID, - TFM_SP_PLATFORM_IOCTL_SID, - TFM_FWU_WRITE_SID, - TFM_FWU_INSTALL_SID, - TFM_FWU_ABORT_SID, - TFM_FWU_QUERY_SID, - TFM_FWU_REQUEST_REBOOT_SID, - TFM_FWU_ACCEPT_SID, - TFM_FFM11_SERVICE1_SID, - TFM_ATTEST_TEST_GET_PUBLIC_KEY_SID, - }, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_SECURE_CLIENT_SFN_RUN_TESTS"), - .signal = TFM_SECURE_CLIENT_SFN_RUN_TESTS_SIGNAL, - .sid = 0x0000F000, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_SECURE_TEST_PARTITION_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_SECURE_TEST_PARTITION_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_STD_UART), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#else - .assets = { - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_STD_UART), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#endif -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_secure_test_partition_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_secure_test_partition_service_runtime_item[TFM_SP_SECURE_TEST_PARTITION_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_secure_client_service/psa_manifest/tfm_secure_client_service.h b/bsp/test_services/tfm_secure_client_service/psa_manifest/tfm_secure_client_service.h deleted file mode 100644 index 37acd5a..0000000 --- a/bsp/test_services/tfm_secure_client_service/psa_manifest/tfm_secure_client_service.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_SECURE_CLIENT_SERVICE_H__ -#define __PSA_MANIFEST_TFM_SECURE_CLIENT_SERVICE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_SECURE_TEST_PARTITION_MODEL_IPC 1 -#define TFM_SP_SECURE_TEST_PARTITION_MODEL_SFN 0 - - -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SIGNAL (1U << 4) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_SECURE_CLIENT_SERVICE_H__ */ diff --git a/bsp/test_services/tfm_slih_test_service/auto_generated/intermedia_tfm_slih_test_service.c b/bsp/test_services/tfm_slih_test_service/auto_generated/intermedia_tfm_slih_test_service.c deleted file mode 100644 index c066f3a..0000000 --- a/bsp/test_services/tfm_slih_test_service/auto_generated/intermedia_tfm_slih_test_service.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include - -uint8_t tfm_sp_slih_test_stack[0x0400] __attribute__((aligned(8))); diff --git a/bsp/test_services/tfm_slih_test_service/auto_generated/load_info_tfm_slih_test_service.c b/bsp/test_services/tfm_slih_test_service/auto_generated/load_info_tfm_slih_test_service.c deleted file mode 100644 index ca775cc..0000000 --- a/bsp/test_services/tfm_slih_test_service/auto_generated/load_info_tfm_slih_test_service.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#include -#include -#include "region.h" -#include "spm_ipc.h" -#include "load/irq_defs.h" -#include "load/partition_defs.h" -#include "load/service_defs.h" -#include "load/asset_defs.h" -#include "tfm_peripherals_def.h" -#include "psa_manifest/pid.h" -#include "psa_manifest/sid.h" -#include "psa_manifest/tfm_slih_test_service.h" - -#define TFM_SP_SLIH_TEST_NDEPS (0) -#define TFM_SP_SLIH_TEST_NSERVS (1) -#if TFM_LVL == 3 -#define TFM_SP_SLIH_TEST_NASSETS (1 + 1) -#else -#define TFM_SP_SLIH_TEST_NASSETS (1) -#endif -#define TFM_SP_SLIH_TEST_NIRQS (1) - -/* Memory region declaration */ -#if TFM_LVL == 3 -REGION_DECLARE(Image$$, PT_TFM_SP_SLIH_TEST_PRIVATE, _DATA_START$$Base); -REGION_DECLARE(Image$$, PT_TFM_SP_SLIH_TEST_PRIVATE, _DATA_END$$Base); -#endif -extern uint8_t tfm_sp_slih_test_stack[]; - -/* Entrypoint function declaration */ -extern void tfm_slih_test_service_entry(void); - -/* partition load info type definition */ -struct partition_tfm_sp_slih_test_load_info_t { - /* common length load data */ - struct partition_load_info_t load_info; - /* per-partition variable length load data */ - uintptr_t stack_addr; - uintptr_t heap_addr; - struct service_load_info_t services[TFM_SP_SLIH_TEST_NSERVS]; -#if TFM_LVL == 3 - struct asset_desc_t assets[TFM_SP_SLIH_TEST_NASSETS]; -#else - struct asset_desc_t assets[TFM_SP_SLIH_TEST_NASSETS]; -#endif - struct irq_load_info_t irqs[TFM_SP_SLIH_TEST_NIRQS]; -} __attribute__((aligned(4))); - -/* Partition load, deps, service load data. Put to a dedicated section. */ -const struct partition_tfm_sp_slih_test_load_info_t tfm_sp_slih_test_load - __attribute__((used, section(".part_load"))) = { - .load_info = { - .psa_ff_ver = 0x0101 | PARTITION_INFO_MAGIC, - .pid = TFM_SP_SLIH_TEST, - .flags = 0 - | SPM_PART_FLAG_IPC - | PARTITION_PRI_NORMAL, - .entry = ENTRY_TO_POSITION(tfm_slih_test_service_entry), - .stack_size = 0x0400, - .heap_size = 0, - .ndeps = TFM_SP_SLIH_TEST_NDEPS, - .nservices = TFM_SP_SLIH_TEST_NSERVS, - .nassets = TFM_SP_SLIH_TEST_NASSETS, - .nirqs = TFM_SP_SLIH_TEST_NIRQS, - }, - .stack_addr = (uintptr_t)tfm_sp_slih_test_stack, - .heap_addr = 0, - .services = { - { - .name_strid = STRING_PTR_TO_STRID("TFM_SLIH_TEST_CASE"), - .signal = TFM_SLIH_TEST_CASE_SIGNAL, - .sid = 0x0000F0A0, - .flags = 0 - | SERVICE_FLAG_NS_ACCESSIBLE - | SERVICE_FLAG_STATELESS | 0x4 - | SERVICE_VERSION_POLICY_STRICT, - .version = 1, - }, - }, -#if TFM_LVL == 3 - .assets = { - { - .mem.addr_x = PART_REGION_ADDR(PT_TFM_SP_SLIH_TEST_PRIVATE, _DATA_START$$Base), - .mem.addr_y = PART_REGION_ADDR(PT_TFM_SP_SLIH_TEST_PRIVATE, _DATA_END$$Base), - .attr = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT, - }, - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_TIMER0), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#else - .assets = { - { - .dev.addr_ref = PTR_TO_REFERENCE(TFM_PERIPHERAL_TIMER0), - .attr = ASSET_DEV_REF_BIT, - }, - }, -#endif - .irqs = { - { - .source = TFM_TIMER0_IRQ, - .flih_func = 0, - .signal = TFM_TIMER0_IRQ_SIGNAL, - }, - }, -}; - -/* Placeholder for partition and service runtime space. Do not reference it. */ -static struct partition_t tfm_sp_slih_test_partition_runtime_item - __attribute__((used, section(".bss.part_runtime"))); -static struct service_t tfm_sp_slih_test_service_runtime_item[TFM_SP_SLIH_TEST_NSERVS] - __attribute__((used, section(".bss.serv_runtime"))); diff --git a/bsp/test_services/tfm_slih_test_service/psa_manifest/tfm_slih_test_service.h b/bsp/test_services/tfm_slih_test_service/psa_manifest/tfm_slih_test_service.h deleted file mode 100644 index 3071b44..0000000 --- a/bsp/test_services/tfm_slih_test_service/psa_manifest/tfm_slih_test_service.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_TFM_SLIH_TEST_SERVICE_H__ -#define __PSA_MANIFEST_TFM_SLIH_TEST_SERVICE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TFM_SP_SLIH_TEST_MODEL_IPC 1 -#define TFM_SP_SLIH_TEST_MODEL_SFN 0 - - -#define TFM_SLIH_TEST_CASE_SIGNAL (1U << 4) - -#define TFM_TIMER0_IRQ_SIGNAL (1U << 31) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_TFM_SLIH_TEST_SERVICE_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/CMakeLists.txt b/bsp/tf_m_targets/arm/mps3/an547/CMakeLists.txt new file mode 100644 index 0000000..6d7cf62 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/CMakeLists.txt @@ -0,0 +1,187 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +cmake_policy(SET CMP0076 NEW) +set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) + +#========================= Platform region defs ===============================# + +target_include_directories(platform_region_defs + INTERFACE + partition +) + +#========================= Platform common defs ===============================# + +if (${CMAKE_C_COMPILER_ID} STREQUAL IAR) + message(FATAL_ERROR "IAR is currently not supported on the mps3/an547 due to a lack of scatter files") +endif() + +if (${CMAKE_C_COMPILER_ID} STREQUAL ARMClang) + if (${CMAKE_C_COMPILER_VERSION} VERSION_LESS "6.14") + message(FATAL_ERROR "CPU (Cortex-M55) is only supported in ARMCLANG version 6.14 or newer.") + endif() +endif() + +# Specify the location of platform specific build dependencies. +target_sources(tfm_s + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/device/source/startup_an547_s.c +) +target_add_scatter_file(tfm_s + $<$:${CMAKE_SOURCE_DIR}/platform/ext/common/armclang/tfm_common_s.sct> + $<$:${CMAKE_SOURCE_DIR}/platform/ext/common/gcc/tfm_common_s.ld> +) + +if(NS) + target_sources(tfm_ns + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/device/source/startup_an547_ns.c + ) + target_add_scatter_file(tfm_ns + $<$:${CMAKE_CURRENT_SOURCE_DIR}/device/source/armclang/an547_ns.sct> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/device/source/gcc/an547_ns.ld> + ) + target_link_libraries(CMSIS_5_tfm_ns + INTERFACE + CMSIS_5_RTX_V8MMN + ) +endif() + +if(BL2) + target_sources(bl2 + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/device/source/startup_an547_bl2.c + ) + target_add_scatter_file(bl2 + $<$:${CMAKE_CURRENT_SOURCE_DIR}/device/source/armclang/an547_bl2.sct> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/device/source/gcc/an547_bl2.ld> + ) +endif() + +#========================= Platform Secure ====================================# + +target_include_directories(platform_s + PUBLIC + . + ../common + cmsis_drivers + cmsis_drivers/config + device + device/config + device/include + device/source/armclang + native_drivers + partition + services/src + ${PLATFORM_DIR}/.. +) + +target_sources(platform_s + PRIVATE + cmsis_drivers/Driver_Flash.c + cmsis_drivers/Driver_AN547_MPC.c + cmsis_drivers/Driver_SSE300_PPC.c + cmsis_drivers/Driver_USART.c + device/source/device_definition.c + device/source/system_core_init.c + native_drivers/mpc_sie_drv.c + native_drivers/mpu_armv8m_drv.c + native_drivers/ppc_sse300_drv.c + native_drivers/syscounter_armv8-m_cntrl_drv.c + native_drivers/systimer_armv8-m_drv.c + native_drivers/uart_cmsdk_drv.c + spm_hal.c + target_cfg.c + tfm_hal_isolation.c + ${CMAKE_SOURCE_DIR}/platform/ext/common/tfm_hal_isolation_mpu_v8m.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/plat_test.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/services/src/tfm_platform_system.c> +) + +target_link_libraries(platform_s + PRIVATE + tfm_utilities +) + +target_compile_options(platform_s + PUBLIC + ${COMPILER_CMSE_FLAG} +) + +#========================= Platform Non-Secure ================================# + +target_sources(platform_ns + PRIVATE + cmsis_drivers/Driver_Flash.c + cmsis_drivers/Driver_USART.c + device/source/device_definition.c + device/source/system_core_init.c + native_drivers/systimer_armv8-m_drv.c + native_drivers/uart_cmsdk_drv.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/plat_test.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/services/src/tfm_platform_system.c> +) + +target_include_directories(platform_ns + PUBLIC + . + ../common + ${PLATFORM_DIR}/.. + cmsis_drivers + cmsis_drivers/config + device + device/config + device/include + device/source/armclang + native_drivers + partition + services/src +) + +# TODO: For some reason this is needed +target_link_libraries(platform_ns + PRIVATE + psa_interface +) + +#========================= Platform BL2 =======================================# + +if(BL2) + target_sources(platform_bl2 + PRIVATE + cmsis_drivers/Driver_Flash.c + cmsis_drivers/Driver_USART.c + device/source/device_definition.c + device/source/system_core_init.c + native_drivers/uart_cmsdk_drv.c + boot_hal.c + ) + + target_include_directories(platform_bl2 + PUBLIC + cmsis_drivers + cmsis_drivers/config + device + device/config + device/include + device/source/armclang + native_drivers + partition + services/src + + PRIVATE + . + ${PLATFORM_DIR}/.. + native_drivers + ) + + target_compile_options(platform_bl2 + PRIVATE + ${BL2_COMPILER_FLAG} + ) +endif() diff --git a/bsp/tf_m_targets/arm/mps3/an547/README.rst b/bsp/tf_m_targets/arm/mps3/an547/README.rst new file mode 100644 index 0000000..02041c8 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/README.rst @@ -0,0 +1,101 @@ +Corstone-300 Ethos-U55 FPGA and FVP +=================================== + +Building TF-M +------------- + +Follow the instructions in :doc:`Building instructions `. +Build instructions with platform name: arm/mps3/an547 (-DTFM_PLATFORM=arm/mps3/an547). + +.. note:: + + When building with GNUARM, please use the version of gcc shipped with zephyr + SDK 0.13.0-alpha1, arm-zephyr-eabi-gcc version 10.3.0. + +.. note:: + + This platform support does not provide software for Ethos-U55 IP, only + contains base address and interrupt number for it. + +.. note:: + + The built binaries can be run on both the Corstone-300 Ethos-U55 Ecosystem + FVP (FVP_SSE300_MPS3) and Corstone SSE-300 with Ethos-U55 Example Subsystem + for MPS3 (AN547). + +To run the example code on Corstone SSE-300 with Ethos-U55 Example Subsystem for MPS3 (AN547) +--------------------------------------------------------------------------------------------- +FPGA image is available to download `here `__ + +To run BL2 bootloader and TF-M example application and tests in the MPS3 board, +it is required to have AN547 image in the MPS3 board SD card. The image should +be located in ``/MB/HBI/AN547`` + +The MPS3 board tested is HBI0309C. + +#. Copy ``bl2.bin`` and ``tfm_s_ns_signed.bin`` files from + build dir to ``/SOFTWARE/`` +#. Rename ``tfm_s_ns_signed.bin`` to ``tfm.bin`` (Filename should not be longer + than 8 charachters.) +#. Open ``/MB/HBI0309C/AN547/images.txt`` +#. Update the ``images.txt`` file as follows:: + + TITLE: Arm MPS3 FPGA prototyping board Images Configuration File + + [IMAGES] + TOTALIMAGES: 2 ;Number of Images (Max: 32) + + IMAGE0UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + IMAGE0ADDRESS: 0x00000000 ;Please select the required executable program + IMAGE0FILE: \SOFTWARE\bl2.bin + IMAGE1UPDATE: AUTO + IMAGE1ADDRESS: 0x02000000 + IMAGE1FILE: \SOFTWARE\tfm.bin + +#. Close ``/MB/HBI0309C/AN547/images.txt`` +#. Unmount/eject the ```` unit +#. Reset the board to execute the TF-M example application +#. After completing the procedure you should be able to visualize on the serial + port (baud 115200 8n1) the following messages:: + + [INF] Swap type: none + [INF] Swap type: none + [INF] Bootloader chainload address offset: 0x0 + [INF] Jumping to the first image slot + [Sec Thread] Secure image initializing! + TF-M isolation level is: 0x00000001 + Booting TFM v1.2.0 + Jumping to non-secure code... + Non-Secure system starting... + +To run the example code on Corstone-300 Ethos-U55 Ecosystem FVP +--------------------------------------------------------------- +FVP is available to download `here `__ + +#. Install the FVP +#. Copy ``bl2.axf`` and ``tfm_s_ns_signed.bin`` files from + build dir to ``/models/Linux64_GCC-6.4/`` +#. Navigate to the same directory and execute the following command to start FVP: + + ./FVP_MPS3_Corstone_SSE-300 -a cpu0*="bl2.axf" --data "tfm_s_ns_signed.bin"@0x01000000 + +#. After completing the procedure you should be able to visualize on the serial + port the following messages:: + + Trying 127.0.0.1... + Connected to localhost. + Escape character is '^]'. + [INF] Starting bootloader + [INF] Swap type: none + [INF] Swap type: none + [INF] Bootloader chainload address offset: 0x0 + [INF] Jumping to the first image slot + [Sec Thread] Secure image initializing! + TF-M isolation level is: 0x00000001 + Booting TFM v1.2.0 + Jumping to non-secure code... + Non-Secure system starting... + +------------- + +*Copyright (c) 2020-2021, Arm Limited. All rights reserved.* diff --git a/bsp/tf_m_targets/arm/mps3/an547/boot_hal.c b/bsp/tf_m_targets/arm/mps3/an547/boot_hal.c new file mode 100644 index 0000000..9e93972 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/boot_hal.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "cmsis.h" +#include "region.h" +#include "target_cfg.h" +#include "boot_hal.h" +#include "Driver_Flash.h" +#include "flash_layout.h" + +/* Flash device name must be specified by target */ +extern ARM_DRIVER_FLASH FLASH_DEV_NAME; + +REGION_DECLARE(Image$$, ER_DATA, $$Base)[]; +REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[]; +REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base); + +__attribute__((naked)) void boot_clear_bl2_ram_area(void) +{ + __ASM volatile( + "mov r0, #0 \n" + "subs %1, %1, %0 \n" + "Loop: \n" + "subs %1, #4 \n" + "itt ge \n" + "strge r0, [%0, %1] \n" + "bge Loop \n" + "bx lr \n" + : + : "r" (REGION_NAME(Image$$, ER_DATA, $$Base)), + "r" (REGION_NAME(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)) + : "r0", "memory" + ); +} + +int32_t boot_platform_init(void) +{ + int32_t result; + + /* Initialize stack limit register */ + uint32_t msp_stack_bottom = + (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base); + + __set_MSPLIM(msp_stack_bottom); + + result = FLASH_DEV_NAME.Initialize(NULL); + if (result != ARM_DRIVER_OK) { + return 1; + } + + return 0; +} + +void boot_platform_quit(struct boot_arm_vector_table *vt) +{ + /* Clang at O0, stores variables on the stack with SP relative addressing. + * When manually set the SP then the place of reset vector is lost. + * Static variables are stored in 'data' or 'bss' section, change of SP has + * no effect on them. + */ + static struct boot_arm_vector_table *vt_cpy; + int32_t result; + + result = FLASH_DEV_NAME.Uninitialize(); + if (result != ARM_DRIVER_OK) { + while (1); + } + + vt_cpy = vt; + + __set_MSPLIM(0); + __set_MSP(vt->msp); + __DSB(); + __ISB(); + + boot_jump_to_next_image(vt_cpy->reset); +} + diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_AN547_MPC.c b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_AN547_MPC.c new file mode 100644 index 0000000..2a6b8b2 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_AN547_MPC.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2016-2020 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Driver_MPC.h" + +#include "mpc_sie_drv.h" +#include "cmsis_driver_config.h" +#include "RTE_Device.h" + +/* Driver version */ +#define ARM_MPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 0) + +/* Driver Version */ +static const ARM_DRIVER_VERSION DriverVersion = { + ARM_MPC_API_VERSION, + ARM_MPC_DRV_VERSION +}; + +static ARM_DRIVER_VERSION ARM_MPC_GetVersion(void) +{ + return DriverVersion; +} + +/* + * \brief Translates error codes from native API to CMSIS API. + * + * \param[in] err Error code to translate (\ref mpc_sie_error_t). + * + * \return Returns CMSIS error code. + */ +static int32_t error_trans(enum mpc_sie_error_t err) +{ + switch(err) { + case MPC_SIE_ERR_NONE: + return ARM_DRIVER_OK; + case MPC_SIE_INVALID_ARG: + return ARM_DRIVER_ERROR_PARAMETER; + case MPC_SIE_NOT_INIT: + return ARM_MPC_ERR_NOT_INIT; + case MPC_SIE_ERR_NOT_IN_RANGE: + return ARM_MPC_ERR_NOT_IN_RANGE; + case MPC_SIE_ERR_NOT_ALIGNED: + return ARM_MPC_ERR_NOT_ALIGNED; + case MPC_SIE_ERR_INVALID_RANGE: + return ARM_MPC_ERR_INVALID_RANGE; + case MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE: + return ARM_MPC_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE; + default: + return ARM_MPC_ERR_UNSPECIFIED; + } +} + +#if (RTE_SRAM_MPC) +/* Ranges controlled by this SRAM_MPC */ +static const struct mpc_sie_memory_range_t MPC_SRAM_RANGE_S = { + .base = MPC_SRAM_RANGE_BASE_S, + .limit = MPC_SRAM_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_SRAM_RANGE_NS = { + .base = MPC_SRAM_RANGE_BASE_NS, + .limit = MPC_SRAM_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +#define MPC_SRAM_RANGE_LIST_LEN 2u +static const struct mpc_sie_memory_range_t* + MPC_SRAM_RANGE_LIST[MPC_SRAM_RANGE_LIST_LEN] = { + &MPC_SRAM_RANGE_S, + &MPC_SRAM_RANGE_NS + }; + +/* SRAM_MPC Driver wrapper functions */ +static int32_t SRAM_MPC_Initialize(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_init(&MPC_SRAM_DEV, + MPC_SRAM_RANGE_LIST, + MPC_SRAM_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t SRAM_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t SRAM_MPC_GetBlockSize(uint32_t *blk_size) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_block_size(&MPC_SRAM_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t SRAM_MPC_GetCtrlConfig(uint32_t *ctrl_val) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_ctrl(&MPC_SRAM_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t SRAM_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_set_ctrl(&MPC_SRAM_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t SRAM_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR *attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_region_config(&MPC_SRAM_DEV, base, limit, + (enum mpc_sie_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t SRAM_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_config_region(&MPC_SRAM_DEV, base, limit, + (enum mpc_sie_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t SRAM_MPC_EnableInterrupt(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_irq_enable(&MPC_SRAM_DEV); + + return error_trans(ret); +} + +static void SRAM_MPC_DisableInterrupt(void) +{ + mpc_sie_irq_disable(&MPC_SRAM_DEV); +} + + +static void SRAM_MPC_ClearInterrupt(void) +{ + mpc_sie_clear_irq(&MPC_SRAM_DEV); +} + +static uint32_t SRAM_MPC_InterruptState(void) +{ + return mpc_sie_irq_state(&MPC_SRAM_DEV); +} + +static int32_t SRAM_MPC_LockDown(void) +{ + return mpc_sie_lock_down(&MPC_SRAM_DEV); +} + +/* SRAM_MPC Driver CMSIS access structure */ +ARM_DRIVER_MPC Driver_SRAM_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = SRAM_MPC_Initialize, + .Uninitialize = SRAM_MPC_Uninitialize, + .GetBlockSize = SRAM_MPC_GetBlockSize, + .GetCtrlConfig = SRAM_MPC_GetCtrlConfig, + .SetCtrlConfig = SRAM_MPC_SetCtrlConfig, + .ConfigRegion = SRAM_MPC_ConfigRegion, + .GetRegionConfig = SRAM_MPC_GetRegionConfig, + .EnableInterrupt = SRAM_MPC_EnableInterrupt, + .DisableInterrupt = SRAM_MPC_DisableInterrupt, + .ClearInterrupt = SRAM_MPC_ClearInterrupt, + .InterruptState = SRAM_MPC_InterruptState, + .LockDown = SRAM_MPC_LockDown, +}; +#endif /* RTE_SRAM_MPC */ + +#if (RTE_ISRAM0_MPC) +/* Ranges controlled by this ISRAM0_MPC */ +static const struct mpc_sie_memory_range_t MPC_ISRAM0_RANGE_S = { + .base = MPC_ISRAM0_RANGE_BASE_S, + .limit = MPC_ISRAM0_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_ISRAM0_RANGE_NS = { + .base = MPC_ISRAM0_RANGE_BASE_NS, + .limit = MPC_ISRAM0_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +#define MPC_ISRAM0_RANGE_LIST_LEN 2u +static const struct mpc_sie_memory_range_t* + MPC_ISRAM0_RANGE_LIST[MPC_ISRAM0_RANGE_LIST_LEN] = { + &MPC_ISRAM0_RANGE_S, + &MPC_ISRAM0_RANGE_NS + }; + +/* ISRAM0_MPC Driver wrapper functions */ +static int32_t ISRAM0_MPC_Initialize(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_init(&MPC_ISRAM0_DEV, + MPC_ISRAM0_RANGE_LIST, + MPC_ISRAM0_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ISRAM0_MPC_GetBlockSize(uint32_t *blk_size) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_block_size(&MPC_ISRAM0_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_GetCtrlConfig(uint32_t *ctrl_val) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_ctrl(&MPC_ISRAM0_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_set_ctrl(&MPC_ISRAM0_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR *attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_region_config(&MPC_ISRAM0_DEV, base, limit, + (enum mpc_sie_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_config_region(&MPC_ISRAM0_DEV, base, limit, + (enum mpc_sie_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t ISRAM0_MPC_EnableInterrupt(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_irq_enable(&MPC_ISRAM0_DEV); + + return error_trans(ret); +} + +static void ISRAM0_MPC_DisableInterrupt(void) +{ + mpc_sie_irq_disable(&MPC_ISRAM0_DEV); +} + + +static void ISRAM0_MPC_ClearInterrupt(void) +{ + mpc_sie_clear_irq(&MPC_ISRAM0_DEV); +} + +static uint32_t ISRAM0_MPC_InterruptState(void) +{ + return mpc_sie_irq_state(&MPC_ISRAM0_DEV); +} + +static int32_t ISRAM0_MPC_LockDown(void) +{ + return mpc_sie_lock_down(&MPC_ISRAM0_DEV); +} + +/* ISRAM0_MPC Driver CMSIS access structure */ +ARM_DRIVER_MPC Driver_ISRAM0_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = ISRAM0_MPC_Initialize, + .Uninitialize = ISRAM0_MPC_Uninitialize, + .GetBlockSize = ISRAM0_MPC_GetBlockSize, + .GetCtrlConfig = ISRAM0_MPC_GetCtrlConfig, + .SetCtrlConfig = ISRAM0_MPC_SetCtrlConfig, + .ConfigRegion = ISRAM0_MPC_ConfigRegion, + .GetRegionConfig = ISRAM0_MPC_GetRegionConfig, + .EnableInterrupt = ISRAM0_MPC_EnableInterrupt, + .DisableInterrupt = ISRAM0_MPC_DisableInterrupt, + .ClearInterrupt = ISRAM0_MPC_ClearInterrupt, + .InterruptState = ISRAM0_MPC_InterruptState, + .LockDown = ISRAM0_MPC_LockDown, +}; +#endif /* RTE_ISRAM0_MPC */ + +#if (RTE_ISRAM1_MPC) +/* Ranges controlled by this ISRAM1_MPC */ +static const struct mpc_sie_memory_range_t MPC_ISRAM1_RANGE_S = { + .base = MPC_ISRAM1_RANGE_BASE_S, + .limit = MPC_ISRAM1_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_ISRAM1_RANGE_NS = { + .base = MPC_ISRAM1_RANGE_BASE_NS, + .limit = MPC_ISRAM1_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +#define MPC_ISRAM1_RANGE_LIST_LEN 2u +static const struct mpc_sie_memory_range_t* + MPC_ISRAM1_RANGE_LIST[MPC_ISRAM1_RANGE_LIST_LEN] = { + &MPC_ISRAM1_RANGE_S, + &MPC_ISRAM1_RANGE_NS + }; + +/* ISRAM1_MPC Driver wrapper functions */ +static int32_t ISRAM1_MPC_Initialize(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_init(&MPC_ISRAM1_DEV, + MPC_ISRAM1_RANGE_LIST, + MPC_ISRAM1_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ISRAM1_MPC_GetBlockSize(uint32_t *blk_size) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_block_size(&MPC_ISRAM1_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_GetCtrlConfig(uint32_t *ctrl_val) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_ctrl(&MPC_ISRAM1_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_set_ctrl(&MPC_ISRAM1_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR *attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_region_config(&MPC_ISRAM1_DEV, base, limit, + (enum mpc_sie_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_config_region(&MPC_ISRAM1_DEV, base, limit, + (enum mpc_sie_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t ISRAM1_MPC_EnableInterrupt(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_irq_enable(&MPC_ISRAM1_DEV); + + return error_trans(ret); +} + +static void ISRAM1_MPC_DisableInterrupt(void) +{ + mpc_sie_irq_disable(&MPC_ISRAM1_DEV); +} + + +static void ISRAM1_MPC_ClearInterrupt(void) +{ + mpc_sie_clear_irq(&MPC_ISRAM1_DEV); +} + +static uint32_t ISRAM1_MPC_InterruptState(void) +{ + return mpc_sie_irq_state(&MPC_ISRAM1_DEV); +} + +static int32_t ISRAM1_MPC_LockDown(void) +{ + return mpc_sie_lock_down(&MPC_ISRAM1_DEV); +} + +/* ISRAM1_MPC Driver CMSIS access structure */ +ARM_DRIVER_MPC Driver_ISRAM1_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = ISRAM1_MPC_Initialize, + .Uninitialize = ISRAM1_MPC_Uninitialize, + .GetBlockSize = ISRAM1_MPC_GetBlockSize, + .GetCtrlConfig = ISRAM1_MPC_GetCtrlConfig, + .SetCtrlConfig = ISRAM1_MPC_SetCtrlConfig, + .ConfigRegion = ISRAM1_MPC_ConfigRegion, + .GetRegionConfig = ISRAM1_MPC_GetRegionConfig, + .EnableInterrupt = ISRAM1_MPC_EnableInterrupt, + .DisableInterrupt = ISRAM1_MPC_DisableInterrupt, + .ClearInterrupt = ISRAM1_MPC_ClearInterrupt, + .InterruptState = ISRAM1_MPC_InterruptState, + .LockDown = ISRAM1_MPC_LockDown, +}; +#endif /* RTE_ISRAM1_MPC */ + +#if (RTE_QSPI_MPC) +/* Ranges controlled by this QSPI_MPC */ +static const struct mpc_sie_memory_range_t MPC_QSPI_RANGE_S = { + .base = MPC_QSPI_RANGE_BASE_S, + .limit = MPC_QSPI_RANGE_LIMIT_S, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_QSPI_RANGE_NS = { + .base = MPC_QSPI_RANGE_BASE_NS, + .limit = MPC_QSPI_RANGE_LIMIT_NS, + .range_offset = 0, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +#define MPC_QSPI_RANGE_LIST_LEN 2u +static const struct mpc_sie_memory_range_t* + MPC_QSPI_RANGE_LIST[MPC_QSPI_RANGE_LIST_LEN] = { + &MPC_QSPI_RANGE_S, + &MPC_QSPI_RANGE_NS + }; + +/* QSPI_MPC Driver wrapper functions */ +static int32_t QSPI_MPC_Initialize(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_init(&MPC_QSPI_DEV, + MPC_QSPI_RANGE_LIST, + MPC_QSPI_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t QSPI_MPC_GetBlockSize(uint32_t *blk_size) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_block_size(&MPC_QSPI_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_GetCtrlConfig(uint32_t *ctrl_val) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_ctrl(&MPC_QSPI_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_set_ctrl(&MPC_QSPI_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR *attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_region_config(&MPC_QSPI_DEV, base, limit, + (enum mpc_sie_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_config_region(&MPC_QSPI_DEV, base, limit, + (enum mpc_sie_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t QSPI_MPC_EnableInterrupt(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_irq_enable(&MPC_QSPI_DEV); + + return error_trans(ret); +} + +static void QSPI_MPC_DisableInterrupt(void) +{ + mpc_sie_irq_disable(&MPC_QSPI_DEV); +} + + +static void QSPI_MPC_ClearInterrupt(void) +{ + mpc_sie_clear_irq(&MPC_QSPI_DEV); +} + +static uint32_t QSPI_MPC_InterruptState(void) +{ + return mpc_sie_irq_state(&MPC_QSPI_DEV); +} + +static int32_t QSPI_MPC_LockDown(void) +{ + return mpc_sie_lock_down(&MPC_QSPI_DEV); +} + +/* QSPI_MPC Driver CMSIS access structure */ +ARM_DRIVER_MPC Driver_QSPI_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = QSPI_MPC_Initialize, + .Uninitialize = QSPI_MPC_Uninitialize, + .GetBlockSize = QSPI_MPC_GetBlockSize, + .GetCtrlConfig = QSPI_MPC_GetCtrlConfig, + .SetCtrlConfig = QSPI_MPC_SetCtrlConfig, + .ConfigRegion = QSPI_MPC_ConfigRegion, + .GetRegionConfig = QSPI_MPC_GetRegionConfig, + .EnableInterrupt = QSPI_MPC_EnableInterrupt, + .DisableInterrupt = QSPI_MPC_DisableInterrupt, + .ClearInterrupt = QSPI_MPC_ClearInterrupt, + .InterruptState = QSPI_MPC_InterruptState, + .LockDown = QSPI_MPC_LockDown, +}; +#endif /* RTE_QSPI_MPC */ + +#if (RTE_DDR4_MPC) +#define MPC_DDR4_RANGE_LIST_LEN 8u +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK0_RANGE_NS = { + .base = MPC_DDR4_BLK0_RANGE_BASE_NS, + .limit = MPC_DDR4_BLK0_RANGE_LIMIT_NS, + .range_offset = MPC_DDR4_BLK0_RANGE_OFFSET_NS, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK1_RANGE_S = { + .base = MPC_DDR4_BLK1_RANGE_BASE_S, + .limit = MPC_DDR4_BLK1_RANGE_LIMIT_S, + .range_offset = MPC_DDR4_BLK1_RANGE_OFFSET_S, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK2_RANGE_NS = { + .base = MPC_DDR4_BLK2_RANGE_BASE_NS, + .limit = MPC_DDR4_BLK2_RANGE_LIMIT_NS, + .range_offset = MPC_DDR4_BLK2_RANGE_OFFSET_NS, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK3_RANGE_S = { + .base = MPC_DDR4_BLK3_RANGE_BASE_S, + .limit = MPC_DDR4_BLK3_RANGE_LIMIT_S, + .range_offset = MPC_DDR4_BLK3_RANGE_OFFSET_S, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK4_RANGE_NS = { + .base = MPC_DDR4_BLK4_RANGE_BASE_NS, + .limit = MPC_DDR4_BLK4_RANGE_LIMIT_NS, + .range_offset = MPC_DDR4_BLK4_RANGE_OFFSET_NS, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK5_RANGE_S = { + .base = MPC_DDR4_BLK5_RANGE_BASE_S, + .limit = MPC_DDR4_BLK5_RANGE_LIMIT_S, + .range_offset = MPC_DDR4_BLK5_RANGE_OFFSET_S, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK6_RANGE_NS = { + .base = MPC_DDR4_BLK6_RANGE_BASE_NS, + .limit = MPC_DDR4_BLK6_RANGE_LIMIT_NS, + .range_offset = MPC_DDR4_BLK6_RANGE_OFFSET_NS, + .attr = MPC_SIE_SEC_ATTR_NONSECURE +}; + +static const struct mpc_sie_memory_range_t MPC_DDR4_BLK7_RANGE_S = { + .base = MPC_DDR4_BLK7_RANGE_BASE_S, + .limit = MPC_DDR4_BLK7_RANGE_LIMIT_S, + .range_offset = MPC_DDR4_BLK7_RANGE_OFFSET_S, + .attr = MPC_SIE_SEC_ATTR_SECURE +}; + +static const struct mpc_sie_memory_range_t* + MPC_DDR4_RANGE_LIST[MPC_DDR4_RANGE_LIST_LEN] = { + &MPC_DDR4_BLK0_RANGE_NS, + &MPC_DDR4_BLK1_RANGE_S, + &MPC_DDR4_BLK2_RANGE_NS, + &MPC_DDR4_BLK3_RANGE_S, + &MPC_DDR4_BLK4_RANGE_NS, + &MPC_DDR4_BLK5_RANGE_S, + &MPC_DDR4_BLK6_RANGE_NS, + &MPC_DDR4_BLK7_RANGE_S, + }; + +/* DDR4_MPC Driver wrapper functions */ +static int32_t DDR4_MPC_Initialize(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_init(&MPC_DDR4_DEV, + MPC_DDR4_RANGE_LIST, + MPC_DDR4_RANGE_LIST_LEN); + + return error_trans(ret); +} + +static int32_t DDR4_MPC_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t DDR4_MPC_GetBlockSize(uint32_t *blk_size) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_block_size(&MPC_DDR4_DEV, blk_size); + + return error_trans(ret); +} + +static int32_t DDR4_MPC_GetCtrlConfig(uint32_t *ctrl_val) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_ctrl(&MPC_DDR4_DEV, ctrl_val); + + return error_trans(ret); +} + +static int32_t DDR4_MPC_SetCtrlConfig(uint32_t ctrl) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_set_ctrl(&MPC_DDR4_DEV, ctrl); + + return error_trans(ret); +} + +static int32_t DDR4_MPC_GetRegionConfig(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR *attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_get_region_config(&MPC_DDR4_DEV, base, limit, + (enum mpc_sie_sec_attr_t*)attr); + + return error_trans(ret); +} + +static int32_t DDR4_MPC_ConfigRegion(uintptr_t base, + uintptr_t limit, + ARM_MPC_SEC_ATTR attr) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_config_region(&MPC_DDR4_DEV, base, limit, + (enum mpc_sie_sec_attr_t)attr); + + return error_trans(ret); +} + +static int32_t DDR4_MPC_EnableInterrupt(void) +{ + enum mpc_sie_error_t ret; + + ret = mpc_sie_irq_enable(&MPC_DDR4_DEV); + + return error_trans(ret); +} + +static void DDR4_MPC_DisableInterrupt(void) +{ + mpc_sie_irq_disable(&MPC_DDR4_DEV); +} + + +static void DDR4_MPC_ClearInterrupt(void) +{ + mpc_sie_clear_irq(&MPC_DDR4_DEV); +} + +static uint32_t DDR4_MPC_InterruptState(void) +{ + return mpc_sie_irq_state(&MPC_DDR4_DEV); +} + +static int32_t DDR4_MPC_LockDown(void) +{ + return mpc_sie_lock_down(&MPC_DDR4_DEV); +} + +/* DDR4_MPC Driver CMSIS access structure */ +ARM_DRIVER_MPC Driver_DDR4_MPC = { + .GetVersion = ARM_MPC_GetVersion, + .Initialize = DDR4_MPC_Initialize, + .Uninitialize = DDR4_MPC_Uninitialize, + .GetBlockSize = DDR4_MPC_GetBlockSize, + .GetCtrlConfig = DDR4_MPC_GetCtrlConfig, + .SetCtrlConfig = DDR4_MPC_SetCtrlConfig, + .ConfigRegion = DDR4_MPC_ConfigRegion, + .GetRegionConfig = DDR4_MPC_GetRegionConfig, + .EnableInterrupt = DDR4_MPC_EnableInterrupt, + .DisableInterrupt = DDR4_MPC_DisableInterrupt, + .ClearInterrupt = DDR4_MPC_ClearInterrupt, + .InterruptState = DDR4_MPC_InterruptState, + .LockDown = DDR4_MPC_LockDown, +}; +#endif /* RTE_DDR4_MPC */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_Flash.c b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_Flash.c new file mode 100644 index 0000000..fb32e14 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_Flash.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013-2020 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "Driver_Flash.h" +#include "RTE_Device.h" +#include "platform_base_address.h" + +#ifndef ARG_UNUSED +#define ARG_UNUSED(arg) ((void)arg) +#endif + +#define FLASH0_BASE_S QSPI_SRAM_BASE_S +#define FLASH0_BASE_NS QSPI_SRAM_BASE_NS +#define FLASH0_SIZE QSPI_SRAM_SIZE +#define FLASH0_SECTOR_SIZE 0x00001000 /* 4 kB */ +#define FLASH0_PAGE_SIZE 0x00001000 /* 4 kB */ +#define FLASH0_PROGRAM_UNIT 0x1 /* Minimum write size */ + +/* Driver version */ +#define ARM_FLASH_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 1) +#define ARM_FLASH_DRV_ERASE_VALUE 0xFF + +/* + * ARM FLASH device structure + * + * This driver just emulates a flash interface and behaviour on top of the SRAM + * memory. + */ +struct arm_flash_dev_t { + const uint32_t memory_base; /*!< FLASH memory base address */ + ARM_FLASH_INFO *data; /*!< FLASH data */ +}; + +/* Flash Status */ +static ARM_FLASH_STATUS FlashStatus = {0, 0, 0}; + +/* Driver Version */ +static const ARM_DRIVER_VERSION DriverVersion = { + ARM_FLASH_API_VERSION, + ARM_FLASH_DRV_VERSION +}; + +/* Driver Capabilities */ +static const ARM_FLASH_CAPABILITIES DriverCapabilities = { + 0, /* event_ready */ + 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */ + 1 /* erase_chip */ +}; + +static int32_t is_range_valid(struct arm_flash_dev_t *flash_dev, + uint32_t offset) +{ + uint32_t flash_limit = 0; + int32_t rc = 0; + + flash_limit = (flash_dev->data->sector_count * flash_dev->data->sector_size) + - 1; + + if (offset > flash_limit) { + rc = -1; + } + return rc; +} + +static int32_t is_write_aligned(struct arm_flash_dev_t *flash_dev, + uint32_t param) +{ + int32_t rc = 0; + + if ((param % flash_dev->data->program_unit) != 0) { + rc = -1; + } + return rc; +} + +static int32_t is_sector_aligned(struct arm_flash_dev_t *flash_dev, + uint32_t offset) +{ + int32_t rc = 0; + + if ((offset % flash_dev->data->sector_size) != 0) { + rc = -1; + } + return rc; +} + +static int32_t is_flash_ready_to_write(const uint8_t *start_addr, uint32_t cnt) +{ + int32_t rc = 0; + uint32_t i; + + for (i = 0; i < cnt; i++) { + if(start_addr[i] != ARM_FLASH_DRV_ERASE_VALUE) { + rc = -1; + break; + } + } + + return rc; +} + +#if (RTE_FLASH0) +static ARM_FLASH_INFO ARM_FLASH0_DEV_DATA = { + .sector_info = NULL, /* Uniform sector layout */ + .sector_count = FLASH0_SIZE / FLASH0_SECTOR_SIZE, + .sector_size = FLASH0_SECTOR_SIZE, + .page_size = FLASH0_PAGE_SIZE, + .program_unit = FLASH0_PROGRAM_UNIT, + .erased_value = ARM_FLASH_DRV_ERASE_VALUE}; + +static struct arm_flash_dev_t ARM_FLASH0_DEV = { +#if (__DOMAIN_NS == 1) + .memory_base = FLASH0_BASE_NS, +#else + .memory_base = FLASH0_BASE_S, +#endif /* __DOMAIN_NS == 1 */ + .data = &(ARM_FLASH0_DEV_DATA)}; + +struct arm_flash_dev_t *FLASH0_DEV = &ARM_FLASH0_DEV; + +/* + * Functions + */ + +static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void) +{ + return DriverVersion; +} + +static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void) +{ + return DriverCapabilities; +} + +static int32_t ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event) +{ + ARG_UNUSED(cb_event); + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_Flash_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_Flash_PowerControl(ARM_POWER_STATE state) +{ + switch (state) { + case ARM_POWER_FULL: + /* Nothing to be done */ + return ARM_DRIVER_OK; + break; + + case ARM_POWER_OFF: + case ARM_POWER_LOW: + default: + return ARM_DRIVER_ERROR_UNSUPPORTED; + } +} + +static int32_t ARM_Flash_ReadData(uint32_t addr, void *data, uint32_t cnt) +{ + uint32_t start_addr = FLASH0_DEV->memory_base + addr; + int32_t rc = 0; + + /* Check flash memory boundaries */ + rc = is_range_valid(FLASH0_DEV, addr + cnt); + if (rc != 0) { + return ARM_DRIVER_ERROR_PARAMETER; + } + + /* Flash interface just emulated over SRAM, use memcpy */ + memcpy(data, (void *)start_addr, cnt); + return ARM_DRIVER_OK; +} + +static int32_t ARM_Flash_ProgramData(uint32_t addr, const void *data, + uint32_t cnt) +{ + uint32_t start_addr = FLASH0_DEV->memory_base + addr; + int32_t rc = 0; + + /* Check flash memory boundaries and alignment with minimal write size */ + rc = is_range_valid(FLASH0_DEV, addr + cnt); + rc |= is_write_aligned(FLASH0_DEV, addr); + rc |= is_write_aligned(FLASH0_DEV, cnt); + if (rc != 0) { + return ARM_DRIVER_ERROR_PARAMETER; + } + + /* Check if the flash area to write the data was erased previously */ + rc = is_flash_ready_to_write((const uint8_t*)start_addr, cnt); + if (rc != 0) { + return ARM_DRIVER_ERROR; + } + + /* Flash interface just emulated over SRAM, use memcpy */ + memcpy((void *)start_addr, data, cnt); + return ARM_DRIVER_OK; +} + +static int32_t ARM_Flash_EraseSector(uint32_t addr) +{ + uint32_t start_addr = FLASH0_DEV->memory_base + addr; + uint32_t rc = 0; + + rc = is_range_valid(FLASH0_DEV, addr); + rc |= is_sector_aligned(FLASH0_DEV, addr); + if (rc != 0) { + return ARM_DRIVER_ERROR_PARAMETER; + } + + /* Flash interface just emulated over SRAM, use memset */ + memset((void *)start_addr, + FLASH0_DEV->data->erased_value, + FLASH0_DEV->data->sector_size); + return ARM_DRIVER_OK; +} + +static int32_t ARM_Flash_EraseChip(void) +{ + uint32_t i; + uint32_t addr = FLASH0_DEV->memory_base; + int32_t rc = ARM_DRIVER_ERROR_UNSUPPORTED; + + /* Check driver capability erase_chip bit */ + if (DriverCapabilities.erase_chip == 1) { + for (i = 0; i < FLASH0_DEV->data->sector_count; i++) { + /* Flash interface just emulated over SRAM, use memset */ + memset((void *)addr, + FLASH0_DEV->data->erased_value, + FLASH0_DEV->data->sector_size); + + addr += FLASH0_DEV->data->sector_size; + rc = ARM_DRIVER_OK; + } + } + return rc; +} + +static ARM_FLASH_STATUS ARM_Flash_GetStatus(void) +{ + return FlashStatus; +} + +static ARM_FLASH_INFO * ARM_Flash_GetInfo(void) +{ + return FLASH0_DEV->data; +} + +ARM_DRIVER_FLASH Driver_FLASH0 = { + ARM_Flash_GetVersion, + ARM_Flash_GetCapabilities, + ARM_Flash_Initialize, + ARM_Flash_Uninitialize, + ARM_Flash_PowerControl, + ARM_Flash_ReadData, + ARM_Flash_ProgramData, + ARM_Flash_EraseSector, + ARM_Flash_EraseChip, + ARM_Flash_GetStatus, + ARM_Flash_GetInfo +}; +#endif /* RTE_FLASH0 */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.c b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.c new file mode 100644 index 0000000..c16cc4a --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.c @@ -0,0 +1,1305 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Driver_SSE300_PPC.h" + +#include "Driver_Common.h" +#include "cmsis.h" +#include "cmsis_driver_config.h" +#include "RTE_Device.h" +#include "ppc_sse300_drv.h" + +/* Driver version */ +#define ARM_PPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) + +/* Driver Version */ +static const ARM_DRIVER_VERSION DriverVersion = { + ARM_PPC_API_VERSION, + ARM_PPC_DRV_VERSION +}; + +ARM_DRIVER_VERSION PPC_SSE300_GetVersion(void) +{ + return DriverVersion; +} + +typedef struct _SSE300_PPC_Resources { + struct ppc_sse300_dev_t* dev; /* PPC device structure */ +} SSE300_PPC_Resources; + +#if (RTE_PPC_SSE300_MAIN0) + +static SSE300_PPC_Resources MAIN0_PPC_DEV = { + .dev = &PPC_SSE300_MAIN0_DEV, +}; + +/* MAIN0 PPC Driver wrapper functions */ +static int32_t PPC_SSE300_MAIN0_Initialize(void) +{ + ppc_sse300_init(MAIN0_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_MAIN0_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_MAIN0_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(MAIN0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN0_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(MAIN0_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_MAIN0_ConfigSecurity(uint32_t periph, PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(MAIN0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN0_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(MAIN0_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_MAIN0_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(MAIN0_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_MAIN0_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(MAIN0_PPC_DEV.dev); +} + +static void PPC_SSE300_MAIN0_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(MAIN0_PPC_DEV.dev); +} + +static bool PPC_SSE300_MAIN0_InterruptState(void) +{ + return ppc_sse300_irq_state(MAIN0_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 MAIN0 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN0 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_MAIN0_Initialize, + .Uninitialize = PPC_SSE300_MAIN0_Uninitialize, + .ConfigPrivilege = PPC_SSE300_MAIN0_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_MAIN0_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_MAIN0_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_MAIN0_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_MAIN0_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_MAIN0_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_MAIN0_ClearInterrupt, + .InterruptState = PPC_SSE300_MAIN0_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_MAIN0 */ + +#if (RTE_PPC_SSE300_MAIN_EXP0) + +static SSE300_PPC_Resources MAIN_EXP0_PPC_DEV = { + .dev = &PPC_SSE300_MAIN_EXP0_DEV, +}; + +/* MAIN PPCEXP0 Driver wrapper functions */ +static int32_t PPC_SSE300_MAIN_EXP0_Initialize(void) +{ + ppc_sse300_init(MAIN_EXP0_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_MAIN_EXP0_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_MAIN_EXP0_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(MAIN_EXP0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP0_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(MAIN_EXP0_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_MAIN_EXP0_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(MAIN_EXP0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP0_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(MAIN_EXP0_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_MAIN_EXP0_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(MAIN_EXP0_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_MAIN_EXP0_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(MAIN_EXP0_PPC_DEV.dev); +} + +static void PPC_SSE300_MAIN_EXP0_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(MAIN_EXP0_PPC_DEV.dev); +} + +static bool PPC_SSE300_MAIN_EXP0_InterruptState(void) +{ + return ppc_sse300_irq_state(MAIN_EXP0_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 MAIN EXP0 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP0 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_MAIN_EXP0_Initialize, + .Uninitialize = PPC_SSE300_MAIN_EXP0_Uninitialize, + .ConfigPrivilege = PPC_SSE300_MAIN_EXP0_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_MAIN_EXP0_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_MAIN_EXP0_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_MAIN_EXP0_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_MAIN_EXP0_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_MAIN_EXP0_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_MAIN_EXP0_ClearInterrupt, + .InterruptState = PPC_SSE300_MAIN_EXP0_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_MAIN_EXP0 */ + +#if (RTE_PPC_SSE300_MAIN_EXP1) + +static SSE300_PPC_Resources MAIN_EXP1_PPC_DEV = { + .dev = &PPC_SSE300_MAIN_EXP1_DEV, +}; + +/* MAIN PPCEXP1 Driver wrapper functions */ +static int32_t PPC_SSE300_MAIN_EXP1_Initialize(void) +{ + ppc_sse300_init(MAIN_EXP1_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_MAIN_EXP1_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_MAIN_EXP1_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(MAIN_EXP1_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP1_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(MAIN_EXP1_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_MAIN_EXP1_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(MAIN_EXP1_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP1_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(MAIN_EXP1_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_MAIN_EXP1_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(MAIN_EXP1_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_MAIN_EXP1_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(MAIN_EXP1_PPC_DEV.dev); +} + +static void PPC_SSE300_MAIN_EXP1_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(MAIN_EXP1_PPC_DEV.dev); +} + +static bool PPC_SSE300_MAIN_EXP1_InterruptState(void) +{ + return ppc_sse300_irq_state(MAIN_EXP1_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 MAIN EXP1 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP1 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_MAIN_EXP1_Initialize, + .Uninitialize = PPC_SSE300_MAIN_EXP1_Uninitialize, + .ConfigPrivilege = PPC_SSE300_MAIN_EXP1_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_MAIN_EXP1_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_MAIN_EXP1_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_MAIN_EXP1_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_MAIN_EXP1_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_MAIN_EXP1_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_MAIN_EXP1_ClearInterrupt, + .InterruptState = PPC_SSE300_MAIN_EXP1_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_MAIN_EXP1 */ + +#if (RTE_PPC_SSE300_MAIN_EXP2) + +static SSE300_PPC_Resources MAIN_EXP2_PPC_DEV = { + .dev = &PPC_SSE300_MAIN_EXP2_DEV, +}; + +/* MAIN PPCEXP2 Driver wrapper functions */ +static int32_t PPC_SSE300_MAIN_EXP2_Initialize(void) +{ + ppc_sse300_init(MAIN_EXP2_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_MAIN_EXP2_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_MAIN_EXP2_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(MAIN_EXP2_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP2_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(MAIN_EXP2_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_MAIN_EXP2_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(MAIN_EXP2_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP2_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(MAIN_EXP2_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_MAIN_EXP2_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(MAIN_EXP2_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_MAIN_EXP2_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(MAIN_EXP2_PPC_DEV.dev); +} + +static void PPC_SSE300_MAIN_EXP2_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(MAIN_EXP2_PPC_DEV.dev); +} + +static bool PPC_SSE300_MAIN_EXP2_InterruptState(void) +{ + return ppc_sse300_irq_state(MAIN_EXP2_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 MAIN EXP2 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP2 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_MAIN_EXP2_Initialize, + .Uninitialize = PPC_SSE300_MAIN_EXP2_Uninitialize, + .ConfigPrivilege = PPC_SSE300_MAIN_EXP2_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_MAIN_EXP2_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_MAIN_EXP2_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_MAIN_EXP2_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_MAIN_EXP2_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_MAIN_EXP2_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_MAIN_EXP2_ClearInterrupt, + .InterruptState = PPC_SSE300_MAIN_EXP2_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_MAIN_EXP2 */ + +#if (RTE_PPC_SSE300_MAIN_EXP3) + +static SSE300_PPC_Resources MAIN_EXP3_PPC_DEV = { + .dev = &PPC_SSE300_MAIN_EXP3_DEV, +}; + +/* MAIN PPCEXP3 Driver wrapper functions */ +static int32_t PPC_SSE300_MAIN_EXP3_Initialize(void) +{ + ppc_sse300_init(MAIN_EXP3_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_MAIN_EXP3_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_MAIN_EXP3_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(MAIN_EXP3_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP3_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(MAIN_EXP3_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_MAIN_EXP3_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(MAIN_EXP3_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_MAIN_EXP3_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(MAIN_EXP3_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_MAIN_EXP3_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(MAIN_EXP3_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_MAIN_EXP3_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(MAIN_EXP3_PPC_DEV.dev); +} + +static void PPC_SSE300_MAIN_EXP3_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(MAIN_EXP3_PPC_DEV.dev); +} + +static bool PPC_SSE300_MAIN_EXP3_InterruptState(void) +{ + return ppc_sse300_irq_state(MAIN_EXP3_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 MAIN EXP3 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP3 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_MAIN_EXP3_Initialize, + .Uninitialize = PPC_SSE300_MAIN_EXP3_Uninitialize, + .ConfigPrivilege = PPC_SSE300_MAIN_EXP3_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_MAIN_EXP3_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_MAIN_EXP3_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_MAIN_EXP3_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_MAIN_EXP3_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_MAIN_EXP3_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_MAIN_EXP3_ClearInterrupt, + .InterruptState = PPC_SSE300_MAIN_EXP3_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_MAIN_EXP3 */ + +#if (RTE_PPC_SSE300_PERIPH0) + +static SSE300_PPC_Resources PERIPH0_PPC_DEV = { + .dev = &PPC_SSE300_PERIPH0_DEV, +}; + +/* PERIPH0 Driver wrapper functions */ +static int32_t PPC_SSE300_PERIPH0_Initialize(void) +{ + ppc_sse300_init(PERIPH0_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_PERIPH0_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_PERIPH0_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(PERIPH0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH0_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(PERIPH0_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_PERIPH0_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(PERIPH0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH0_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(PERIPH0_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_PERIPH0_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(PERIPH0_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_PERIPH0_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(PERIPH0_PPC_DEV.dev); +} + +static void PPC_SSE300_PERIPH0_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(PERIPH0_PPC_DEV.dev); +} + +static bool PPC_SSE300_PERIPH0_InterruptState(void) +{ + return ppc_sse300_irq_state(PERIPH0_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 PERIPH0 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH0 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_PERIPH0_Initialize, + .Uninitialize = PPC_SSE300_PERIPH0_Uninitialize, + .ConfigPrivilege = PPC_SSE300_PERIPH0_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_PERIPH0_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_PERIPH0_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_PERIPH0_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_PERIPH0_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_PERIPH0_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_PERIPH0_ClearInterrupt, + .InterruptState = PPC_SSE300_PERIPH0_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_PERIPH0 */ + +#if (RTE_PPC_SSE300_PERIPH1) + +static SSE300_PPC_Resources PERIPH1_PPC_DEV = { + .dev = &PPC_SSE300_PERIPH1_DEV, +}; + +/* PERIPH1 Driver wrapper functions */ +static int32_t PPC_SSE300_PERIPH1_Initialize(void) +{ + ppc_sse300_init(PERIPH1_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_PERIPH1_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_PERIPH1_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(PERIPH1_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH1_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(PERIPH1_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_PERIPH1_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(PERIPH1_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH1_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(PERIPH1_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_PERIPH1_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(PERIPH1_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_PERIPH1_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(PERIPH1_PPC_DEV.dev); +} + +static void PPC_SSE300_PERIPH1_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(PERIPH1_PPC_DEV.dev); +} + +static bool PPC_SSE300_PERIPH1_InterruptState(void) +{ + return ppc_sse300_irq_state(PERIPH1_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 PERIPH1 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH1 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_PERIPH1_Initialize, + .Uninitialize = PPC_SSE300_PERIPH1_Uninitialize, + .ConfigPrivilege = PPC_SSE300_PERIPH1_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_PERIPH1_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_PERIPH1_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_PERIPH1_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_PERIPH1_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_PERIPH1_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_PERIPH1_ClearInterrupt, + .InterruptState = PPC_SSE300_PERIPH1_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_PERIPH1 */ + +#if (RTE_PPC_SSE300_PERIPH_EXP0) + +static SSE300_PPC_Resources PERIPH_EXP0_PPC_DEV = { + .dev = &PPC_SSE300_PERIPH_EXP0_DEV, +}; + +/* PERIPH PPCEXP0 Driver wrapper functions */ +static int32_t PPC_SSE300_PERIPH_EXP0_Initialize(void) +{ + ppc_sse300_init(PERIPH_EXP0_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_PERIPH_EXP0_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_PERIPH_EXP0_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(PERIPH_EXP0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP0_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(PERIPH_EXP0_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_PERIPH_EXP0_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(PERIPH_EXP0_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP0_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(PERIPH_EXP0_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_PERIPH_EXP0_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(PERIPH_EXP0_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_PERIPH_EXP0_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(PERIPH_EXP0_PPC_DEV.dev); +} + +static void PPC_SSE300_PERIPH_EXP0_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(PERIPH_EXP0_PPC_DEV.dev); +} + +static bool PPC_SSE300_PERIPH_EXP0_InterruptState(void) +{ + return ppc_sse300_irq_state(PERIPH_EXP0_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 PERIPH EXP0 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP0 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_PERIPH_EXP0_Initialize, + .Uninitialize = PPC_SSE300_PERIPH_EXP0_Uninitialize, + .ConfigPrivilege = PPC_SSE300_PERIPH_EXP0_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_PERIPH_EXP0_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_PERIPH_EXP0_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_PERIPH_EXP0_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_PERIPH_EXP0_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_PERIPH_EXP0_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_PERIPH_EXP0_ClearInterrupt, + .InterruptState = PPC_SSE300_PERIPH_EXP0_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_PERIPH_EXP0 */ + +#if (RTE_PPC_SSE300_PERIPH_EXP1) + +static SSE300_PPC_Resources PERIPH_EXP1_PPC_DEV = { + .dev = &PPC_SSE300_PERIPH_EXP1_DEV, +}; + +/* PERIPH PPCEXP1 Driver wrapper functions */ +static int32_t PPC_SSE300_PERIPH_EXP1_Initialize(void) +{ + ppc_sse300_init(PERIPH_EXP1_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_PERIPH_EXP1_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_PERIPH_EXP1_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(PERIPH_EXP1_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP1_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(PERIPH_EXP1_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_PERIPH_EXP1_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(PERIPH_EXP1_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP1_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(PERIPH_EXP1_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_PERIPH_EXP1_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(PERIPH_EXP1_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_PERIPH_EXP1_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(PERIPH_EXP1_PPC_DEV.dev); +} + +static void PPC_SSE300_PERIPH_EXP1_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(PERIPH_EXP1_PPC_DEV.dev); +} + +static bool PPC_SSE300_PERIPH_EXP1_InterruptState(void) +{ + return ppc_sse300_irq_state(PERIPH_EXP1_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 PERIPH EXP1 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP1 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_PERIPH_EXP1_Initialize, + .Uninitialize = PPC_SSE300_PERIPH_EXP1_Uninitialize, + .ConfigPrivilege = PPC_SSE300_PERIPH_EXP1_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_PERIPH_EXP1_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_PERIPH_EXP1_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_PERIPH_EXP1_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_PERIPH_EXP1_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_PERIPH_EXP1_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_PERIPH_EXP1_ClearInterrupt, + .InterruptState = PPC_SSE300_PERIPH_EXP1_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_PERIPH_EXP1 */ + +#if (RTE_PPC_SSE300_PERIPH_EXP2) + +static SSE300_PPC_Resources PERIPH_EXP2_PPC_DEV = { + .dev = &PPC_SSE300_PERIPH_EXP2_DEV, +}; + +/* PERIPH PPCEXP2 Driver wrapper functions */ +static int32_t PPC_SSE300_PERIPH_EXP2_Initialize(void) +{ + ppc_sse300_init(PERIPH_EXP2_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_PERIPH_EXP2_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_PERIPH_EXP2_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(PERIPH_EXP2_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP2_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(PERIPH_EXP2_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_PERIPH_EXP2_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(PERIPH_EXP2_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP2_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(PERIPH_EXP2_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_PERIPH_EXP2_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(PERIPH_EXP2_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_PERIPH_EXP2_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(PERIPH_EXP2_PPC_DEV.dev); +} + +static void PPC_SSE300_PERIPH_EXP2_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(PERIPH_EXP2_PPC_DEV.dev); +} + +static bool PPC_SSE300_PERIPH_EXP2_InterruptState(void) +{ + return ppc_sse300_irq_state(PERIPH_EXP2_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 PERIPH EXP2 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP2 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_PERIPH_EXP2_Initialize, + .Uninitialize = PPC_SSE300_PERIPH_EXP2_Uninitialize, + .ConfigPrivilege = PPC_SSE300_PERIPH_EXP2_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_PERIPH_EXP2_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_PERIPH_EXP2_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_PERIPH_EXP2_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_PERIPH_EXP2_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_PERIPH_EXP2_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_PERIPH_EXP2_ClearInterrupt, + .InterruptState = PPC_SSE300_PERIPH_EXP2_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_PERIPH_EXP2 */ + +#if (RTE_PPC_SSE300_PERIPH_EXP3) + +static SSE300_PPC_Resources PERIPH_EXP3_PPC_DEV = { + .dev = &PPC_SSE300_PERIPH_EXP3_DEV, +}; + +/* PERIPH PPCEXP3 Driver wrapper functions */ +static int32_t PPC_SSE300_PERIPH_EXP3_Initialize(void) +{ + ppc_sse300_init(PERIPH_EXP3_PPC_DEV.dev); + + return ARM_DRIVER_OK; +} + +static int32_t PPC_SSE300_PERIPH_EXP3_Uninitialize(void) +{ + /* Nothing to do */ + return ARM_DRIVER_OK; +} + +static int32_t +PPC_SSE300_PERIPH_EXP3_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_privilege(PERIPH_EXP3_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr, + (enum ppc_sse300_priv_attr_t)priv_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP3_IsPeriphPrivOnly(uint32_t periph) +{ + return ppc_sse300_is_periph_priv_only(PERIPH_EXP3_PPC_DEV.dev, periph); +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +static int32_t +PPC_SSE300_PERIPH_EXP3_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_config_security(PERIPH_EXP3_PPC_DEV.dev, periph, + (enum ppc_sse300_sec_attr_t)sec_attr); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static bool PPC_SSE300_PERIPH_EXP3_IsPeriphSecure(uint32_t periph) +{ + return ppc_sse300_is_periph_secure(PERIPH_EXP3_PPC_DEV.dev, periph); +} + +static int32_t PPC_SSE300_PERIPH_EXP3_EnableInterrupt(void) +{ + enum ppc_sse300_error_t ret; + + ret = ppc_sse300_irq_enable(PERIPH_EXP3_PPC_DEV.dev); + + if( ret != PPC_SSE300_ERR_NONE) { + return ARM_DRIVER_ERROR; + } + + return ARM_DRIVER_OK; +} + +static void PPC_SSE300_PERIPH_EXP3_DisableInterrupt(void) +{ + ppc_sse300_irq_disable(PERIPH_EXP3_PPC_DEV.dev); +} + +static void PPC_SSE300_PERIPH_EXP3_ClearInterrupt(void) +{ + ppc_sse300_clear_irq(PERIPH_EXP3_PPC_DEV.dev); +} + +static bool PPC_SSE300_PERIPH_EXP3_InterruptState(void) +{ + return ppc_sse300_irq_state(PERIPH_EXP3_PPC_DEV.dev); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +/* PPC SSE-300 PERIPH EXP3 Driver CMSIS access structure */ +DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP3 = { + .GetVersion = PPC_SSE300_GetVersion, + .Initialize = PPC_SSE300_PERIPH_EXP3_Initialize, + .Uninitialize = PPC_SSE300_PERIPH_EXP3_Uninitialize, + .ConfigPrivilege = PPC_SSE300_PERIPH_EXP3_ConfigPrivilege, + .IsPeriphPrivOnly = PPC_SSE300_PERIPH_EXP3_IsPeriphPrivOnly, +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + .ConfigSecurity = PPC_SSE300_PERIPH_EXP3_ConfigSecurity, + .IsPeriphSecure = PPC_SSE300_PERIPH_EXP3_IsPeriphSecure, + .EnableInterrupt = PPC_SSE300_PERIPH_EXP3_EnableInterrupt, + .DisableInterrupt = PPC_SSE300_PERIPH_EXP3_DisableInterrupt, + .ClearInterrupt = PPC_SSE300_PERIPH_EXP3_ClearInterrupt, + .InterruptState = PPC_SSE300_PERIPH_EXP3_InterruptState +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +}; +#endif /* RTE_PPC_SSE300_PERIPH_EXP3 */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.h b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.h new file mode 100644 index 0000000..c07fed0 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_SSE300_PPC.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PPC_SSE300_DRIVER_H__ +#define __PPC_SSE300_DRIVER_H__ + +#include "Driver_Common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* API version */ +#define ARM_PPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) + +/* Security attribute used to configure the peripheral */ +typedef enum _PPC_SSE300_SecAttr { + PPC_SSE300_SECURE_CONFIG = 0, /*!< Secure access */ + PPC_SSE300_NONSECURE_CONFIG, /*!< Non-secure access */ +} PPC_SSE300_SecAttr; + +/* Privilege attribute used to configure the peripheral */ +typedef enum _PPC_SSE300_PrivAttr { + PPC_SSE300_PRIV_AND_NONPRIV_CONFIG = 0, /*!< Privilege and non-privilege + * access */ + PPC_SSE300_PRIV_CONFIG, /*!< Privilege only access */ +} PPC_SSE300_PrivAttr; + +/* Function descriptions */ +/** + SACFG - Secure Privilege Control Block + NSACFG - Non-Secure Privilege Control Block + + \fn ARM_DRIVER_VERSION PPC_SSE300_GetVersion(void) + \brief Get driver version. + \return \ref ARM_DRIVER_VERSION + + \fn int32_t PPC_SSE300_Initialize(void) + \brief Initializes PPC Interface. + \return Returns SSE-300 PPC error code. + + \fn int32_t PPC_SSE300_Uninitialize(void) + \brief De-initializes PPC Interface. + \return Returns SSE-300 PPC error code. + + \fn int32_t PPC_SSE300_ConfigPrivilege(uint32_t periph, + PPC_SSE300_SecAttr sec_attr, + PPC_SSE300_PrivAttr priv_attr) + \brief Configures privilege level with privileged and unprivileged + access or privileged access only in the given security domain + for a peripheral controlled by the given PPC. + \param[in] periph: Peripheral mask for SACFG and NSACFG registers. + \param[in] sec_attr: Specifies Secure or Non Secure domain. + \param[in] priv_attr: Privilege attribute value to set. + \return Returns SSE-300 PPC error code. + + \fn bool PPC_SSE300_IsPeriphPrivOnly (uint32_t periph) + \brief Checks if the peripheral is configured to be privilege only + - with non-secure caller in the non-secure domain + - with secure caller in the configured security domain + \param[in] periph: Peripheral mask for SACFG and NSACFG registers. + \return Returns true if the peripheral is configured as privilege access + only, false for privilege and unprivilege access mode. + + Secure only functions: + + \fn int32_t PPC_SSE300_ConfigSecurity(uint32_t periph, + PPC_SSE300_SecAttr sec_attr) + \brief Configures security level for a peripheral controlled by the + given PPC with secure or non-secure access only. + \param[in] periph: Peripheral mask for SACFG and NSACFG registers. + \param[in] sec_attr: Secure attribute value to set. + \return Returns SSE-300 PPC error code. + + \fn bool PPC_SSE300_IsPeriphSecure (uint32_t periph) + \brief Checks if the peripheral is configured to be secure. + \param[in] periph: Peripheral mask for SACFG and NSACFG registers. + \return Returns true if the peripheral is configured as secure, + false for non-secure. + + \fn int32_t PPC_SSE300_EnableInterrupt (void) + \brief Enables PPC interrupt. + \return Returns SSE-300 PPC error code. + + \fn void PPC_SSE300_DisableInterrupt (void) + \brief Disables PPC interrupt. + + \fn void PPC_SSE300_ClearInterrupt (void) + \brief Clears PPC interrupt. + + \fn bool PPC_SSE300_InterruptState (void) + \brief Gets PPC interrupt state. + \return Returns true if the interrupt is active, false otherwise. +*/ + +/** + * \brief Access structure of the PPC Driver. + */ +typedef struct _DRIVER_PPC_SSE300 { + ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_PPC_GetVersion : Get driver version. + int32_t (*Initialize) (void); ///< Pointer to \ref ARM_PPC_Initialize : Initialize the PPC Interface. + int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_PPC_Uninitialize : De-initialize the PPC Interface. + int32_t (*ConfigPrivilege) (uint32_t periph, PPC_SSE300_SecAttr sec_attr, PPC_SSE300_PrivAttr priv_attr); ///< Pointer to \ref ARM_PPC_ConfigPeriph : Configure a peripheral controlled by the PPC. + bool (*IsPeriphPrivOnly) (uint32_t periph); ///< Pointer to \ref IsPeriphPrivOnly : Check if the peripheral is configured to be privilege only. +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + int32_t (*ConfigSecurity) (uint32_t periph, PPC_SSE300_SecAttr sec_attr); ///< Pointer to \ref ARM_PPC_ConfigPeriph : Configure a peripheral controlled by the PPC. + bool (*IsPeriphSecure) (uint32_t periph); ///< Pointer to \ref IsPeriphSecure : Check if the peripheral is configured to be secure. + int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_PPC_EnableInterrupt : Enable PPC interrupt. + void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_PPC_DisableInterrupt : Disable PPC interrupt. + void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_PPC_ClearInterrupt : Clear PPC interrupt. + bool (*InterruptState) (void); ///< Pointer to \ref ARM_PPC_InterruptState : PPC interrupt State. +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ +} const DRIVER_PPC_SSE300; + +#ifdef __cplusplus +} +#endif +#endif /* __PPC_SSE300_DRIVER_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_USART.c b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_USART.c new file mode 100644 index 0000000..cb3a14a --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/Driver_USART.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Driver_USART.h" + +#include "cmsis_driver_config.h" +#include "RTE_Device.h" + +#ifndef ARG_UNUSED +#define ARG_UNUSED(arg) (void)arg +#endif + +/* Driver version */ +#define ARM_USART_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 2) + +/* Driver Version */ +static const ARM_DRIVER_VERSION DriverVersion = { + ARM_USART_API_VERSION, + ARM_USART_DRV_VERSION +}; + +/* Driver Capabilities */ +static const ARM_USART_CAPABILITIES DriverCapabilities = { + 1, /* supports UART (Asynchronous) mode */ + 0, /* supports Synchronous Master mode */ + 0, /* supports Synchronous Slave mode */ + 0, /* supports UART Single-wire mode */ + 0, /* supports UART IrDA mode */ + 0, /* supports UART Smart Card mode */ + 0, /* Smart Card Clock generator available */ + 0, /* RTS Flow Control available */ + 0, /* CTS Flow Control available */ + 0, /* Transmit completed event: \ref ARM_USARTx_EVENT_TX_COMPLETE */ + 0, /* Signal receive character timeout event: \ref ARM_USARTx_EVENT_RX_TIMEOUT */ + 0, /* RTS Line: 0=not available, 1=available */ + 0, /* CTS Line: 0=not available, 1=available */ + 0, /* DTR Line: 0=not available, 1=available */ + 0, /* DSR Line: 0=not available, 1=available */ + 0, /* DCD Line: 0=not available, 1=available */ + 0, /* RI Line: 0=not available, 1=available */ + 0, /* Signal CTS change event: \ref ARM_USARTx_EVENT_CTS */ + 0, /* Signal DSR change event: \ref ARM_USARTx_EVENT_DSR */ + 0, /* Signal DCD change event: \ref ARM_USARTx_EVENT_DCD */ + 0, /* Signal RI change event: \ref ARM_USARTx_EVENT_RI */ + 0 /* Reserved */ +}; + +static ARM_DRIVER_VERSION ARM_USART_GetVersion(void) +{ + return DriverVersion; +} + +static ARM_USART_CAPABILITIES ARM_USART_GetCapabilities(void) +{ + return DriverCapabilities; +} + +typedef struct { + struct uart_cmsdk_dev_t *dev; /* UART device structure */ + uint32_t tx_nbr_bytes; /* Number of bytes transfered */ + uint32_t rx_nbr_bytes; /* Number of bytes recevied */ + ARM_USART_SignalEvent_t cb_event; /* Callback function for events */ +} UARTx_Resources; + +static int32_t ARM_USARTx_Initialize(UARTx_Resources *uart_dev) +{ + /* Initializes generic UART driver */ + uart_cmsdk_init(uart_dev->dev, PeripheralClock); + + return ARM_DRIVER_OK; +} + +static int32_t ARM_USARTx_PowerControl(UARTx_Resources *uart_dev, + ARM_POWER_STATE state) +{ + ARG_UNUSED(uart_dev); + + switch (state) { + case ARM_POWER_OFF: + case ARM_POWER_LOW: + return ARM_DRIVER_ERROR_UNSUPPORTED; + case ARM_POWER_FULL: + /* Nothing to be done */ + return ARM_DRIVER_OK; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch.*/ + } +} + +static int32_t ARM_USARTx_Send(UARTx_Resources *uart_dev, const void *data, + uint32_t num) +{ + const uint8_t *p_data = (const uint8_t *)data; + + if ((data == NULL) || (num == 0U)) { + /* Invalid parameters */ + return ARM_DRIVER_ERROR_PARAMETER; + } + + /* Resets previous TX counter */ + uart_dev->tx_nbr_bytes = 0; + + while (uart_dev->tx_nbr_bytes != num) { + /* Waits until UART is ready to transmit */ + while (!uart_cmsdk_tx_ready(uart_dev->dev)) { + }; + + /* As UART is ready to transmit at this point, the write function can + * not return any transmit error */ + (void)uart_cmsdk_write(uart_dev->dev, *p_data); + + uart_dev->tx_nbr_bytes++; + p_data++; + } + + /* Waits until character is transmited */ + while (!uart_cmsdk_tx_ready(uart_dev->dev)) { + }; + + return ARM_DRIVER_OK; +} + +static int32_t ARM_USARTx_Receive(UARTx_Resources *uart_dev, + void *data, uint32_t num) +{ + uint8_t *p_data = (uint8_t *)data; + + if ((data == NULL) || (num == 0U)) { + // Invalid parameters + return ARM_DRIVER_ERROR_PARAMETER; + } + + /* Resets previous RX counter */ + uart_dev->rx_nbr_bytes = 0; + + while (uart_dev->rx_nbr_bytes != num) { + /* Waits until one character is received */ + while (!uart_cmsdk_rx_ready(uart_dev->dev)){}; + + /* As UART has received one byte, the read can not + * return any receive error at this point */ + (void)uart_cmsdk_read(uart_dev->dev, p_data); + + uart_dev->rx_nbr_bytes++; + p_data++; + } + + return ARM_DRIVER_OK; +} + +static uint32_t ARM_USARTx_GetTxCount(UARTx_Resources *uart_dev) +{ + return uart_dev->tx_nbr_bytes; +} + +static uint32_t ARM_USARTx_GetRxCount(UARTx_Resources *uart_dev) +{ + return uart_dev->rx_nbr_bytes; +} + +static int32_t ARM_USARTx_Control(UARTx_Resources *uart_dev, uint32_t control, + uint32_t arg) +{ + switch (control & ARM_USART_CONTROL_Msk) { + case ARM_USART_MODE_ASYNCHRONOUS: + if (uart_cmsdk_set_baudrate(uart_dev->dev, arg) != UART_CMSDK_ERR_NONE) { + return ARM_USART_ERROR_BAUDRATE; + } + break; + /* Unsupported command */ + default: + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + /* UART Data bits */ + if (control & ARM_USART_DATA_BITS_Msk) { + /* Data bit is not configurable */ + return ARM_DRIVER_ERROR_UNSUPPORTED; + } + + /* UART Parity */ + if (control & ARM_USART_PARITY_Msk) { + /* Parity is not configurable */ + return ARM_USART_ERROR_PARITY; + } + + /* USART Stop bits */ + if (control & ARM_USART_STOP_BITS_Msk) { + /* Stop bit is not configurable */ + return ARM_USART_ERROR_STOP_BITS; + } + + return ARM_DRIVER_OK; +} + +#if (RTE_USART0) +/* USART0 Driver wrapper functions */ +static UARTx_Resources USART0_DEV = { + .dev = &UART0_CMSDK_DEV, + .tx_nbr_bytes = 0, + .rx_nbr_bytes = 0, + .cb_event = NULL, +}; + +static int32_t ARM_USART0_Initialize(ARM_USART_SignalEvent_t cb_event) +{ + USART0_DEV.cb_event = cb_event; + + return ARM_USARTx_Initialize(&USART0_DEV); +} + +static int32_t ARM_USART0_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_USART0_PowerControl(ARM_POWER_STATE state) +{ + return ARM_USARTx_PowerControl(&USART0_DEV, state); +} + +static int32_t ARM_USART0_Send(const void *data, uint32_t num) +{ + return ARM_USARTx_Send(&USART0_DEV, data, num); +} + +static int32_t ARM_USART0_Receive(void *data, uint32_t num) +{ + return ARM_USARTx_Receive(&USART0_DEV, data, num); +} + +static int32_t ARM_USART0_Transfer(const void *data_out, void *data_in, + uint32_t num) +{ + ARG_UNUSED(data_out); + ARG_UNUSED(data_in); + ARG_UNUSED(num); + + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static uint32_t ARM_USART0_GetTxCount(void) +{ + return ARM_USARTx_GetTxCount(&USART0_DEV); +} + +static uint32_t ARM_USART0_GetRxCount(void) +{ + return ARM_USARTx_GetRxCount(&USART0_DEV); +} +static int32_t ARM_USART0_Control(uint32_t control, uint32_t arg) +{ + return ARM_USARTx_Control(&USART0_DEV, control, arg); +} + +static ARM_USART_STATUS ARM_USART0_GetStatus(void) +{ + ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; + return status; +} + +static int32_t ARM_USART0_SetModemControl(ARM_USART_MODEM_CONTROL control) +{ + ARG_UNUSED(control); + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static ARM_USART_MODEM_STATUS ARM_USART0_GetModemStatus(void) +{ + ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; + return modem_status; +} + +extern ARM_DRIVER_USART Driver_USART0; +ARM_DRIVER_USART Driver_USART0 = { + ARM_USART_GetVersion, + ARM_USART_GetCapabilities, + ARM_USART0_Initialize, + ARM_USART0_Uninitialize, + ARM_USART0_PowerControl, + ARM_USART0_Send, + ARM_USART0_Receive, + ARM_USART0_Transfer, + ARM_USART0_GetTxCount, + ARM_USART0_GetRxCount, + ARM_USART0_Control, + ARM_USART0_GetStatus, + ARM_USART0_SetModemControl, + ARM_USART0_GetModemStatus +}; +#endif /* RTE_USART0 */ + +#if (RTE_USART1) +/* USART1 Driver wrapper functions */ +static UARTx_Resources USART1_DEV = { + .dev = &UART1_CMSDK_DEV, + .tx_nbr_bytes = 0, + .rx_nbr_bytes = 0, + .cb_event = NULL, +}; + +static int32_t ARM_USART1_Initialize(ARM_USART_SignalEvent_t cb_event) +{ + USART1_DEV.cb_event = cb_event; + + return ARM_USARTx_Initialize(&USART1_DEV); +} + +static int32_t ARM_USART1_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_USART1_PowerControl(ARM_POWER_STATE state) +{ + return ARM_USARTx_PowerControl(&USART1_DEV, state); +} + +static int32_t ARM_USART1_Send(const void *data, uint32_t num) +{ + return ARM_USARTx_Send(&USART1_DEV, data, num); +} + +static int32_t ARM_USART1_Receive(void *data, uint32_t num) +{ + return ARM_USARTx_Receive(&USART1_DEV, data, num); +} + +static int32_t ARM_USART1_Transfer(const void *data_out, void *data_in, + uint32_t num) +{ + ARG_UNUSED(data_out); + ARG_UNUSED(data_in); + ARG_UNUSED(num); + + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static uint32_t ARM_USART1_GetTxCount(void) +{ + return ARM_USARTx_GetTxCount(&USART1_DEV); +} + +static uint32_t ARM_USART1_GetRxCount(void) +{ + return ARM_USARTx_GetRxCount(&USART1_DEV); +} +static int32_t ARM_USART1_Control(uint32_t control, uint32_t arg) +{ + return ARM_USARTx_Control(&USART1_DEV, control, arg); +} + +static ARM_USART_STATUS ARM_USART1_GetStatus(void) +{ + ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; + return status; +} + +static int32_t ARM_USART1_SetModemControl(ARM_USART_MODEM_CONTROL control) +{ + ARG_UNUSED(control); + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static ARM_USART_MODEM_STATUS ARM_USART1_GetModemStatus(void) +{ + ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; + return modem_status; +} + +extern ARM_DRIVER_USART Driver_USART1; +ARM_DRIVER_USART Driver_USART1 = { + ARM_USART_GetVersion, + ARM_USART_GetCapabilities, + ARM_USART1_Initialize, + ARM_USART1_Uninitialize, + ARM_USART1_PowerControl, + ARM_USART1_Send, + ARM_USART1_Receive, + ARM_USART1_Transfer, + ARM_USART1_GetTxCount, + ARM_USART1_GetRxCount, + ARM_USART1_Control, + ARM_USART1_GetStatus, + ARM_USART1_SetModemControl, + ARM_USART1_GetModemStatus +}; +#endif /* RTE_USART1 */ + +#if (RTE_USART2) +/* USART2 Driver wrapper functions */ +static UARTx_Resources USART2_DEV = { + .dev = &UART2_CMSDK_DEV, + .tx_nbr_bytes = 0, + .rx_nbr_bytes = 0, + .cb_event = NULL, +}; + +static int32_t ARM_USART2_Initialize(ARM_USART_SignalEvent_t cb_event) +{ + USART2_DEV.cb_event = cb_event; + + return ARM_USARTx_Initialize(&USART2_DEV); +} + +static int32_t ARM_USART2_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_USART2_PowerControl(ARM_POWER_STATE state) +{ + return ARM_USARTx_PowerControl(&USART2_DEV, state); +} + +static int32_t ARM_USART2_Send(const void *data, uint32_t num) +{ + return ARM_USARTx_Send(&USART2_DEV, data, num); +} + +static int32_t ARM_USART2_Receive(void *data, uint32_t num) +{ + return ARM_USARTx_Receive(&USART2_DEV, data, num); +} + +static int32_t ARM_USART2_Transfer(const void *data_out, void *data_in, + uint32_t num) +{ + ARG_UNUSED(data_out); + ARG_UNUSED(data_in); + ARG_UNUSED(num); + + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static uint32_t ARM_USART2_GetTxCount(void) +{ + return ARM_USARTx_GetTxCount(&USART2_DEV); +} + +static uint32_t ARM_USART2_GetRxCount(void) +{ + return ARM_USARTx_GetRxCount(&USART2_DEV); +} +static int32_t ARM_USART2_Control(uint32_t control, uint32_t arg) +{ + return ARM_USARTx_Control(&USART2_DEV, control, arg); +} + +static ARM_USART_STATUS ARM_USART2_GetStatus(void) +{ + ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; + return status; +} + +static int32_t ARM_USART2_SetModemControl(ARM_USART_MODEM_CONTROL control) +{ + ARG_UNUSED(control); + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static ARM_USART_MODEM_STATUS ARM_USART2_GetModemStatus(void) +{ + ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; + return modem_status; +} + +extern ARM_DRIVER_USART Driver_USART2; +ARM_DRIVER_USART Driver_USART2 = { + ARM_USART_GetVersion, + ARM_USART_GetCapabilities, + ARM_USART2_Initialize, + ARM_USART2_Uninitialize, + ARM_USART2_PowerControl, + ARM_USART2_Send, + ARM_USART2_Receive, + ARM_USART2_Transfer, + ARM_USART2_GetTxCount, + ARM_USART2_GetRxCount, + ARM_USART2_Control, + ARM_USART2_GetStatus, + ARM_USART2_SetModemControl, + ARM_USART2_GetModemStatus +}; +#endif /* RTE_USART2 */ + +#if (RTE_USART3) +/* USART3 Driver wrapper functions */ +static UARTx_Resources USART3_DEV = { + .dev = &UART3_CMSDK_DEV, + .tx_nbr_bytes = 0, + .rx_nbr_bytes = 0, + .cb_event = NULL, +}; + +static int32_t ARM_USART3_Initialize(ARM_USART_SignalEvent_t cb_event) +{ + USART3_DEV.cb_event = cb_event; + + return ARM_USARTx_Initialize(&USART3_DEV); +} + +static int32_t ARM_USART3_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_USART3_PowerControl(ARM_POWER_STATE state) +{ + return ARM_USARTx_PowerControl(&USART3_DEV, state); +} + +static int32_t ARM_USART3_Send(const void *data, uint32_t num) +{ + return ARM_USARTx_Send(&USART3_DEV, data, num); +} + +static int32_t ARM_USART3_Receive(void *data, uint32_t num) +{ + return ARM_USARTx_Receive(&USART3_DEV, data, num); +} + +static int32_t ARM_USART3_Transfer(const void *data_out, void *data_in, + uint32_t num) +{ + ARG_UNUSED(data_out); + ARG_UNUSED(data_in); + ARG_UNUSED(num); + + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static uint32_t ARM_USART3_GetTxCount(void) +{ + return ARM_USARTx_GetTxCount(&USART3_DEV); +} + +static uint32_t ARM_USART3_GetRxCount(void) +{ + return ARM_USARTx_GetRxCount(&USART3_DEV); +} +static int32_t ARM_USART3_Control(uint32_t control, uint32_t arg) +{ + return ARM_USARTx_Control(&USART3_DEV, control, arg); +} + +static ARM_USART_STATUS ARM_USART3_GetStatus(void) +{ + ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; + return status; +} + +static int32_t ARM_USART3_SetModemControl(ARM_USART_MODEM_CONTROL control) +{ + ARG_UNUSED(control); + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static ARM_USART_MODEM_STATUS ARM_USART3_GetModemStatus(void) +{ + ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; + return modem_status; +} + +extern ARM_DRIVER_USART Driver_USART3; +ARM_DRIVER_USART Driver_USART3 = { + ARM_USART_GetVersion, + ARM_USART_GetCapabilities, + ARM_USART3_Initialize, + ARM_USART3_Uninitialize, + ARM_USART3_PowerControl, + ARM_USART3_Send, + ARM_USART3_Receive, + ARM_USART3_Transfer, + ARM_USART3_GetTxCount, + ARM_USART3_GetRxCount, + ARM_USART3_Control, + ARM_USART3_GetStatus, + ARM_USART3_SetModemControl, + ARM_USART3_GetModemStatus +}; +#endif /* RTE_USART3 */ + +#if (RTE_USART4) +/* USART4 Driver wrapper functions */ +static UARTx_Resources USART4_DEV = { + .dev = &UART4_CMSDK_DEV, + .tx_nbr_bytes = 0, + .rx_nbr_bytes = 0, + .cb_event = NULL, +}; + +static int32_t ARM_USART4_Initialize(ARM_USART_SignalEvent_t cb_event) +{ + USART4_DEV.cb_event = cb_event; + + return ARM_USARTx_Initialize(&USART4_DEV); +} + +static int32_t ARM_USART4_Uninitialize(void) +{ + /* Nothing to be done */ + return ARM_DRIVER_OK; +} + +static int32_t ARM_USART4_PowerControl(ARM_POWER_STATE state) +{ + return ARM_USARTx_PowerControl(&USART4_DEV, state); +} + +static int32_t ARM_USART4_Send(const void *data, uint32_t num) +{ + return ARM_USARTx_Send(&USART4_DEV, data, num); +} + +static int32_t ARM_USART4_Receive(void *data, uint32_t num) +{ + return ARM_USARTx_Receive(&USART4_DEV, data, num); +} + +static int32_t ARM_USART4_Transfer(const void *data_out, void *data_in, + uint32_t num) +{ + ARG_UNUSED(data_out); + ARG_UNUSED(data_in); + ARG_UNUSED(num); + + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static uint32_t ARM_USART4_GetTxCount(void) +{ + return ARM_USARTx_GetTxCount(&USART4_DEV); +} + +static uint32_t ARM_USART4_GetRxCount(void) +{ + return ARM_USARTx_GetRxCount(&USART4_DEV); +} +static int32_t ARM_USART4_Control(uint32_t control, uint32_t arg) +{ + return ARM_USARTx_Control(&USART4_DEV, control, arg); +} + +static ARM_USART_STATUS ARM_USART4_GetStatus(void) +{ + ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; + return status; +} + +static int32_t ARM_USART4_SetModemControl(ARM_USART_MODEM_CONTROL control) +{ + ARG_UNUSED(control); + return ARM_DRIVER_ERROR_UNSUPPORTED; +} + +static ARM_USART_MODEM_STATUS ARM_USART4_GetModemStatus(void) +{ + ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; + return modem_status; +} + +extern ARM_DRIVER_USART Driver_USART4; +ARM_DRIVER_USART Driver_USART4 = { + ARM_USART_GetVersion, + ARM_USART_GetCapabilities, + ARM_USART4_Initialize, + ARM_USART4_Uninitialize, + ARM_USART4_PowerControl, + ARM_USART4_Send, + ARM_USART4_Receive, + ARM_USART4_Transfer, + ARM_USART4_GetTxCount, + ARM_USART4_GetRxCount, + ARM_USART4_Control, + ARM_USART4_GetStatus, + ARM_USART4_SetModemControl, + ARM_USART4_GetModemStatus +}; +#endif /* RTE_USART4 */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/RTE_Device.h b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/RTE_Device.h new file mode 100644 index 0000000..1437941 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/RTE_Device.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RTE_DEVICE_H +#define __RTE_DEVICE_H + +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0] +// Configuration settings for Driver_USART0 in component ::Drivers:USART +#define RTE_USART0 1 +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0] + +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1] +// Configuration settings for Driver_USART1 in component ::Drivers:USART +#define RTE_USART1 0 +// USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1] + +// MPC (Memory Protection Controller) [Driver_ISRAM0_MPC] +// Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC +#define RTE_ISRAM0_MPC 1 +// MPC (Memory Protection Controller) [Driver_ISRAM0_MPC] + +// MPC (Memory Protection Controller) [Driver_ISRAM1_MPC] +// Configuration settings for Driver_ISRAM1_MPC in component ::Drivers:MPC +#define RTE_ISRAM1_MPC 1 +// MPC (Memory Protection Controller) [Driver_ISRAM1_MPC] + +// MPC (Memory Protection Controller) [Driver_SRAM_MPC] +// Configuration settings for Driver_SRAM_MPC in component ::Drivers:MPC +#define RTE_SRAM_MPC 1 +// MPC (Memory Protection Controller) [Driver_SRAM_MPC] + +// MPC (Memory Protection Controller) [Driver_QSPI_MPC] +// Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC +#define RTE_QSPI_MPC 1 +// MPC (Memory Protection Controller) [Driver_QSPI_MPC] + +// MPC (Memory Protection Controller) [Driver_DDR4_MPC] +// Configuration settings for Driver_DDR4_MPC in component ::Drivers:MPC +#define RTE_DDR4_MPC 1 +// MPC (Memory Protection Controller) [Driver_DDR4_MPC] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_MAIN0] +// Configuration settings for Driver_PPC_SSE300_MAIN0 in component ::Drivers:PPC +#define RTE_PPC_SSE300_MAIN0 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_MAIN0] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_MAIN_EXP0] +// Configuration settings for Driver_PPC_SSE300_MAIN_EXP0 in component ::Drivers:PPC +#define RTE_PPC_SSE300_MAIN_EXP0 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_MAIN_EXP0] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_MAIN_EXP1] +// Configuration settings for Driver_PPC_SSE300_MAIN_EXP1 in component ::Drivers:PPC +#define RTE_PPC_SSE300_MAIN_EXP1 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_MAIN_EXP1] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_MAIN_EXP2] +// Configuration settings for Driver_PPC_SSE300_MAIN_EXP2 in component ::Drivers:PPC +#define RTE_PPC_SSE300_MAIN_EXP2 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_MAIN_EXP2] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_MAIN_EXP3] +// Configuration settings for Driver_PPC_SSE300_MAIN_EXP3 in component ::Drivers:PPC +#define RTE_PPC_SSE300_MAIN_EXP3 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_MAIN_EXP3] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_PERIPH0] +// Configuration settings for Driver_PPC_SSE300_PERIPH0 in component ::Drivers:PPC +#define RTE_PPC_SSE300_PERIPH0 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_PERIPH0] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_PERIPH1] +// Configuration settings for Driver_PPC_SSE300_PERIPH1 in component ::Drivers:PPC +#define RTE_PPC_SSE300_PERIPH1 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_PERIPH1] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_PERIPH_EXP0] +// Configuration settings for Driver_PPC_SSE300_PERIPH_EXP0 in component ::Drivers:PPC +#define RTE_PPC_SSE300_PERIPH_EXP0 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_PERIPH_EXP0] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_PERIPH_EXP1] +// Configuration settings for Driver_PPC_SSE300_PERIPH_EXP1 in component ::Drivers:PPC +#define RTE_PPC_SSE300_PERIPH_EXP1 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_PERIPH_EXP1] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_PERIPH_EXP2] +// Configuration settings for Driver_PPC_SSE300_PERIPH_EXP2 in component ::Drivers:PPC +#define RTE_PPC_SSE300_PERIPH_EXP2 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_PERIPH_EXP2] + +// PPC (Peripheral Protection Controller) [PPC_SSE300_PERIPH_EXP3] +// Configuration settings for Driver_PPC_SSE300_PERIPH_EXP3 in component ::Drivers:PPC +#define RTE_PPC_SSE300_PERIPH_EXP3 1 +// PPC (Peripheral Protection Controller) [Driver_PPC_SSE300_PERIPH_EXP3] +// Flash device emulated by SRAM [Driver_Flash0] +// Configuration settings for Driver_Flash0 in component ::Drivers:Flash +#define RTE_FLASH0 1 +// Flash device emulated by SRAM [Driver_Flash0] + +#endif /* __RTE_DEVICE_H */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/cmsis_driver_config.h b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/cmsis_driver_config.h new file mode 100644 index 0000000..edc4633 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/cmsis_drivers/config/cmsis_driver_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2020 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_DRIVER_CONFIG_H__ +#define __CMSIS_DRIVER_CONFIG_H__ + +#include "platform_description.h" +#include "device_definition.h" +#include "RTE_Device.h" + +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_NS + +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#define MPC_ISRAM1_DEV MPC_ISRAM1_DEV_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S + +#define PPC_SSE300_MAIN0_DEV PPC_SSE300_MAIN0_DEV_S +#define PPC_SSE300_MAIN_EXP0_DEV PPC_SSE300_MAIN_EXP0_DEV_S +#define PPC_SSE300_MAIN_EXP1_DEV PPC_SSE300_MAIN_EXP1_DEV_S +#define PPC_SSE300_MAIN_EXP2_DEV PPC_SSE300_MAIN_EXP2_DEV_S +#define PPC_SSE300_MAIN_EXP3_DEV PPC_SSE300_MAIN_EXP3_DEV_S +#define PPC_SSE300_PERIPH0_DEV PPC_SSE300_PERIPH0_DEV_S +#define PPC_SSE300_PERIPH1_DEV PPC_SSE300_PERIPH1_DEV_S +#define PPC_SSE300_PERIPH_EXP0_DEV PPC_SSE300_PERIPH_EXP0_DEV_S +#define PPC_SSE300_PERIPH_EXP1_DEV PPC_SSE300_PERIPH_EXP1_DEV_S +#define PPC_SSE300_PERIPH_EXP2_DEV PPC_SSE300_PERIPH_EXP2_DEV_S +#define PPC_SSE300_PERIPH_EXP3_DEV PPC_SSE300_PERIPH_EXP3_DEV_S + +#endif /* __CMSIS_DRIVER_CONFIG_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/config.cmake b/bsp/tf_m_targets/arm/mps3/an547/config.cmake new file mode 100644 index 0000000..a81c8a1 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/config.cmake @@ -0,0 +1,6 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/config/device_cfg.h b/bsp/tf_m_targets/arm/mps3/an547/device/config/device_cfg.h new file mode 100644 index 0000000..f8e5307 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/config/device_cfg.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019-2020 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +/** + * \file device_cfg.h + * \brief + * This is the device configuration file with only used peripherals + * defined and configured via the secure and/or non-secure base address. + */ + +/* ARM Memory Protection Controller (MPC) */ +#define MPC_ISRAM0_S +#define MPC_ISRAM1_S +#define MPC_SRAM_S +#define MPC_QSPI_S +#define MPC_DDR4_S + +#define MPC_DDR4_DEV MPC_DDR4_DEV_S + +/* ARM Peripheral Protection Controllers (PPC) */ +#define PPC_SSE300_MAIN0_S +#define PPC_SSE300_MAIN_EXP0_S +#define PPC_SSE300_MAIN_EXP1_S +#define PPC_SSE300_MAIN_EXP2_S +#define PPC_SSE300_MAIN_EXP3_S +#define PPC_SSE300_PERIPH0_S +#define PPC_SSE300_PERIPH1_S +#define PPC_SSE300_PERIPH_EXP0_S +#define PPC_SSE300_PERIPH_EXP1_S +#define PPC_SSE300_PERIPH_EXP2_S +#define PPC_SSE300_PERIPH_EXP3_S + +/* ARM UART CMSDK */ +#define DEFAULT_UART_BAUDRATE 115200 +#define UART0_CMSDK_NS + +/** System Counter Armv8-M */ +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u + + +/* System Timer Armv8-M */ +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_NS + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) + +#endif /* __DEVICE_CFG_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/cmsis.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/cmsis.h new file mode 100644 index 0000000..dbd93f4 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/cmsis.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_H__ +#define __CMSIS_H__ + +/* ====================== Start of section using anonymous unions ============== */ +#if defined (__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined (__ICCARM__) + #pragma language=extended +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wc11-extensions" + #pragma clang diagnostic ignored "-Wreserved-id-macro" +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning 586 +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +/* ======== Configuration of Core Peripherals ================================== */ +#define __SAUREGION_PRESENT 1U /* SAU regions present */ +#define __MPU_PRESENT 1U /* MPU present */ +#define __VTOR_PRESENT 1U /* VTOR present */ +#define __NVIC_PRIO_BITS 3U /* Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1U /* FPU present */ +#define __FPU_DP 1U /* double precision FPU */ +#define __DSP_PRESENT 1U /* DSP extension present */ +#define __MVE_PRESENT 1U /* MVE extensions present */ +#define __MVE_FP 1U /* MVE floating point present */ + +#include "platform_description.h" +#include "platform_irq.h" +#include "core_armv81mml.h" /* Processor and core peripherals */ + +/* ===================== End of section using anonymous unions ================ */ +#if defined (__CC_ARM) + #pragma pop +#elif defined (__ICCARM__) + /* leave anonymous unions enabled */ +#elif (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic pop +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning restore +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + +#endif /* __CMSIS_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/device_definition.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/device_definition.h new file mode 100644 index 0000000..754f8dd --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/device_definition.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file device_definition.h + * \brief The structure definitions in this file are exported based on the + * peripheral definitions from device_cfg.h. + * This file is meant to be used as a helper for baremetal + * applications and/or as an example of how to configure the generic + * driver structures. + */ + +#ifndef __DEVICE_DEFINITION_H__ +#define __DEVICE_DEFINITION_H__ + +#include "device_cfg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ======= Defines peripheral configuration structures ======= */ +/* UART CMSDK driver structures */ +#ifdef UART0_CMSDK_S +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S; +#endif +#ifdef UART0_CMSDK_NS +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_NS; +#endif + +#ifdef UART1_CMSDK_S +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART1_CMSDK_DEV_S; +#endif +#ifdef UART1_CMSDK_NS +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART1_CMSDK_DEV_NS; +#endif + +#ifdef UART2_CMSDK_S +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART2_CMSDK_DEV_S; +#endif +#ifdef UART2_CMSDK_NS +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART2_CMSDK_DEV_NS; +#endif + +#ifdef UART3_CMSDK_S +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART3_CMSDK_DEV_S; +#endif +#ifdef UART3_CMSDK_NS +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART3_CMSDK_DEV_NS; +#endif + +#ifdef UART4_CMSDK_S +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART4_CMSDK_DEV_S; +#endif +#ifdef UART4_CMSDK_NS +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART4_CMSDK_DEV_NS; +#endif + +#ifdef UART5_CMSDK_S +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART5_CMSDK_DEV_S; +#endif +#ifdef UART5_CMSDK_NS +#include "uart_cmsdk_drv.h" +extern struct uart_cmsdk_dev_t UART5_CMSDK_DEV_NS; +#endif + +/* ARM PPC driver structures */ +#ifdef PPC_SSE300_MAIN0_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_MAIN0_DEV_S; +#endif + +#ifdef PPC_SSE300_MAIN_EXP0_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP0_DEV_S; +#endif + +#ifdef PPC_SSE300_MAIN_EXP1_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP1_DEV_S; +#endif + +#ifdef PPC_SSE300_MAIN_EXP2_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP2_DEV_S; +#endif + +#ifdef PPC_SSE300_MAIN_EXP3_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP3_DEV_S; +#endif + +#ifdef PPC_SSE300_PERIPH0_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_PERIPH0_DEV_S; +#endif + +#ifdef PPC_SSE300_PERIPH1_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_PERIPH1_DEV_S; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP0_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP0_DEV_S; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP1_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP1_DEV_S; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP2_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP2_DEV_S; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP3_S +#include "ppc_sse300_drv.h" +extern struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP3_DEV_S; +#endif + +/* System counters */ +#ifdef SYSCOUNTER_CNTRL_ARMV8_M_S +#include "syscounter_armv8-m_cntrl_drv.h" +extern struct syscounter_armv8_m_cntrl_dev_t SYSCOUNTER_CNTRL_ARMV8_M_DEV_S; +#endif + +#ifdef SYSCOUNTER_READ_ARMV8_M_S +#include "syscounter_armv8-m_read_drv.h" +extern struct syscounter_armv8_m_read_dev_t SYSCOUNTER_READ_ARMV8_M_DEV_S; +#endif +#ifdef SYSCOUNTER_READ_ARMV8_M_NS +#include "syscounter_armv8-m_read_drv.h" +extern struct syscounter_armv8_m_read_dev_t SYSCOUNTER_READ_ARMV8_M_DEV_NS; +#endif + +/* System timers */ +#ifdef SYSTIMER0_ARMV8_M_S +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER0_ARMV8_M_DEV_S; +#endif +#ifdef SYSTIMER0_ARMV8_M_NS +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER0_ARMV8_M_DEV_NS; +#endif + +#ifdef SYSTIMER1_ARMV8_M_S +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER1_ARMV8_M_DEV_S; +#endif +#ifdef SYSTIMER1_ARMV8_M_NS +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER1_ARMV8_M_DEV_NS; +#endif + +#ifdef SYSTIMER2_ARMV8_M_S +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER2_ARMV8_M_DEV_S; +#endif +#ifdef SYSTIMER2_ARMV8_M_NS +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER2_ARMV8_M_DEV_NS; +#endif + +#ifdef SYSTIMER3_ARMV8_M_S +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER3_ARMV8_M_DEV_S; +#endif +#ifdef SYSTIMER3_ARMV8_M_NS +#include "systimer_armv8-m_drv.h" +extern struct systimer_armv8_m_dev_t SYSTIMER3_ARMV8_M_DEV_NS; +#endif + +/* System Watchdogs */ +#ifdef SYSWDOG_ARMV8_M_S +#include "syswdog_armv8-m_drv.h" +extern struct syswdog_armv8_m_dev_t SYSWDOG_ARMV8_M_DEV_S; +#endif +#ifdef SYSWDOG_ARMV8_M_NS +#include "syswdog_armv8-m_drv.h" +extern struct syswdog_armv8_m_dev_t SYSWDOG_ARMV8_M_DEV_NS; +#endif + +/* ARM MPC SIE 300 driver structures */ +#ifdef MPC_SRAM_S +#include "mpc_sie_drv.h" +extern struct mpc_sie_dev_t MPC_SRAM_DEV_S; +#endif + +#ifdef MPC_QSPI_S +#include "mpc_sie_drv.h" +extern struct mpc_sie_dev_t MPC_QSPI_DEV_S; +#endif + +#ifdef MPC_DDR4_S +#include "mpc_sie_drv.h" +extern struct mpc_sie_dev_t MPC_DDR4_DEV_S; +#endif + +#ifdef MPC_ISRAM0_S +#include "mpc_sie_drv.h" +extern struct mpc_sie_dev_t MPC_ISRAM0_DEV_S; +#endif + +#ifdef MPC_ISRAM1_S +#include "mpc_sie_drv.h" +extern struct mpc_sie_dev_t MPC_ISRAM1_DEV_S; +#endif + +#ifdef MPS3_IO_S +#include "arm_mps3_io_drv.h" +extern struct arm_mps3_io_dev_t MPS3_IO_DEV_S; +#endif + +#ifdef MPS3_IO_NS +#include "arm_mps3_io_drv.h" +extern struct arm_mps3_io_dev_t MPS3_IO_DEV_NS; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __DEVICE_DEFINITION_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_description.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_description.h new file mode 100644 index 0000000..6800c05 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_description.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019-2021 Arm Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PLATFORM_DESCRIPTION_H__ +#define __PLATFORM_DESCRIPTION_H__ + +#include "cmsis.h" +#include "platform_base_address.h" +#include "platform_regs.h" +#include "platform_pins.h" +#include "system_core_init.h" + +#endif /* __PLATFORM_DESCRIPTION_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_irq.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_irq.h new file mode 100644 index 0000000..ae706ba --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_irq.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PLATFORM_IRQ_H__ +#define __PLATFORM_IRQ_H__ + +typedef enum _IRQn_Type { + NonMaskableInt_IRQn = -14, /* Non Maskable Interrupt */ + HardFault_IRQn = -13, /* HardFault Interrupt */ + MemoryManagement_IRQn = -12, /* Memory Management Interrupt */ + BusFault_IRQn = -11, /* Bus Fault Interrupt */ + UsageFault_IRQn = -10, /* Usage Fault Interrupt */ + SecureFault_IRQn = -9, /* Secure Fault Interrupt */ + SVCall_IRQn = -5, /* SV Call Interrupt */ + DebugMonitor_IRQn = -4, /* Debug Monitor Interrupt */ + PendSV_IRQn = -2, /* Pend SV Interrupt */ + SysTick_IRQn = -1, /* System Tick Interrupt */ + NONSEC_WATCHDOG_RESET_REQ_IRQn = 0, /* Non-Secure Watchdog Reset + * Request Interrupt + */ + NONSEC_WATCHDOG_IRQn = 1, /* Non-Secure Watchdog Interrupt */ + SLOWCLK_TIMER_IRQn = 2, /* SLOWCLK Timer Interrupt */ + TIMER0_IRQn = 3, /* TIMER 0 Interrupt */ + TIMER1_IRQn = 4, /* TIMER 1 Interrupt */ + TIMER2_IRQn = 5, /* TIMER 2 Interrupt */ + /* Reserved = 6, Reserved */ + /* Reserved = 7, Reserved */ + /* Reserved = 8, Reserved */ + MPC_IRQn = 9, /* MPC Combined (Secure) Interrupt */ + PPC_IRQn = 10, /* PPC Combined (Secure) Interrupt */ + MSC_IRQn = 11, /* MSC Combined (Secure) Interrput */ + BRIDGE_ERROR_IRQn = 12, /* Bridge Error Combined + * (Secure) Interrupt + */ + /* Reserved = 13, Reserved */ + MGMT_PPU_IRQn = 14, /* MGMT PPU */ + SYS_PPU_IRQn = 15, /* SYS PPU */ + CPU0_PPU_IRQn = 16, /* CPU0 PPU */ + /* Reserved = 17, Reserved */ + /* Reserved = 18, Reserved */ + /* Reserved = 19, Reserved */ + /* Reserved = 20, Reserved */ + /* Reserved = 21, Reserved */ + /* Reserved = 22, Reserved */ + /* Reserved = 23, Reserved */ + /* Reserved = 24, Reserved */ + /* Reserved = 25, Reserved */ + DEBUG_PPU_IRQn = 26, /* DEBUG PPU */ + TIMER3_AON_IRQn = 27, /* TIMER 3 AON Interrupt */ + CPU0_CTI_0_IRQn = 28, /* CPU0 CTI IRQ 0 */ + CPU0_CTI_1_IRQn = 29, /* CPU0 CTI IRQ 1 */ + /* Reserved = 30, Reserved */ + /* Reserved = 31, Reserved */ + System_Timestamp_Counter_IRQn = 32, /* System timestamp counter Interrupt */ + UARTRX0_IRQn = 33, /* UART 0 RX Interrupt */ + UARTTX0_IRQn = 34, /* UART 0 TX Interrupt */ + UARTRX1_IRQn = 35, /* UART 1 RX Interrupt */ + UARTTX1_IRQn = 36, /* UART 1 TX Interrupt */ + UARTRX2_IRQn = 37, /* UART 2 RX Interrupt */ + UARTTX2_IRQn = 38, /* UART 2 TX Interrupt */ + UARTRX3_IRQn = 39, /* UART 3 RX Interrupt */ + UARTTX3_IRQn = 40, /* UART 3 TX Interrupt */ + UARTRX4_IRQn = 41, /* UART 4 RX Interrupt */ + UARTTX4_IRQn = 42, /* UART 4 TX Interrupt */ + UART0_Combined_IRQn = 43, /* UART 0 Combined Interrupt */ + UART1_Combined_IRQn = 44, /* UART 1 Combined Interrupt */ + UART2_Combined_IRQn = 45, /* UART 2 Combined Interrupt */ + UART3_Combined_IRQn = 46, /* UART 3 Combined Interrupt */ + UART4_Combined_IRQn = 47, /* UART 4 Combined Interrupt */ + UARTOVF_IRQn = 48, /* UART 0, 1, 2, 3, 4 & 5 Overflow Interrupt */ + ETHERNET_IRQn = 49, /* Ethernet Interrupt */ + I2S_IRQn = 50, /* Audio I2S Interrupt */ + TOUCH_SCREEN_IRQn = 51, /* Touch Screen Interrupt */ + USB_IRQn = 52, /* USB Interrupt */ + SPI_ADC_IRQn = 53, /* SPI ADC Interrupt */ + SPI_SHIELD0_IRQn = 54, /* SPI (Shield 0) Interrupt */ + SPI_SHIELD1_IRQn = 55, /* SPI (Shield 1) Interrupt */ + ETHOS_U55_IRQn = 56, /* Ethos-U55 Interrupt */ + /* Reserved = 57:68 Reserved */ + GPIO0_Combined_IRQn = 69, /* GPIO 0 Combined Interrupt */ + GPIO1_Combined_IRQn = 70, /* GPIO 1 Combined Interrupt */ + GPIO2_Combined_IRQn = 71, /* GPIO 2 Combined Interrupt */ + GPIO3_Combined_IRQn = 72, /* GPIO 3 Combined Interrupt */ + GPIO0_0_IRQn = 73, /* GPIO0 has 16 pins with IRQs */ + GPIO0_1_IRQn = 74, + GPIO0_2_IRQn = 75, + GPIO0_3_IRQn = 76, + GPIO0_4_IRQn = 77, + GPIO0_5_IRQn = 78, + GPIO0_6_IRQn = 79, + GPIO0_7_IRQn = 80, + GPIO0_8_IRQn = 81, + GPIO0_9_IRQn = 82, + GPIO0_10_IRQn = 83, + GPIO0_11_IRQn = 84, + GPIO0_12_IRQn = 85, + GPIO0_13_IRQn = 86, + GPIO0_14_IRQn = 87, + GPIO0_15_IRQn = 88, + GPIO1_0_IRQn = 89, /* GPIO1 has 16 pins with IRQs */ + GPIO1_1_IRQn = 90, + GPIO1_2_IRQn = 91, + GPIO1_3_IRQn = 92, + GPIO1_4_IRQn = 93, + GPIO1_5_IRQn = 94, + GPIO1_6_IRQn = 95, + GPIO1_7_IRQn = 96, + GPIO1_8_IRQn = 97, + GPIO1_9_IRQn = 98, + GPIO1_10_IRQn = 99, + GPIO1_11_IRQn = 100, + GPIO1_12_IRQn = 101, + GPIO1_13_IRQn = 102, + GPIO1_14_IRQn = 103, + GPIO1_15_IRQn = 104, + GPIO2_0_IRQn = 105, /* GPIO2 has 16 pins with IRQs */ + GPIO2_1_IRQn = 106, + GPIO2_2_IRQn = 107, + GPIO2_3_IRQn = 108, + GPIO2_4_IRQn = 109, + GPIO2_5_IRQn = 110, + GPIO2_6_IRQn = 111, + GPIO2_7_IRQn = 112, + GPIO2_8_IRQn = 113, + GPIO2_9_IRQn = 114, + GPIO2_10_IRQn = 115, + GPIO2_11_IRQn = 116, + GPIO2_12_IRQn = 117, + GPIO2_13_IRQn = 118, + GPIO2_14_IRQn = 119, + GPIO2_15_IRQn = 120, + GPIO3_0_IRQn = 121, /* GPIO3 has 4 pins with IRQs */ + GPIO3_1_IRQn = 122, + GPIO3_2_IRQn = 123, + GPIO3_3_IRQn = 124, + UARTRX5_IRQn = 125, /* UART 5 RX Interrupt */ + UARTTX5_IRQn = 126, /* UART 5 TX Interrupt */ + UART5_IRQn = 127, /* UART 5 combined Interrupt */ + /* Reserved = 128:130 Reserved */ +} IRQn_Type; + +#endif /* __PLATFORM_IRQ_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_pins.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_pins.h new file mode 100644 index 0000000..f5eda8c --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_pins.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file platform_pins.h + * \brief This file defines all the pins for this platform. + */ + +#ifndef __PLATFORM_PINS_H__ +#define __PLATFORM_PINS_H__ + +/* AHB GPIO pin names */ +enum arm_gpio_pin_name_t { + AHB_GPIO0_0 = 0U, + AHB_GPIO0_1, + AHB_GPIO0_2, + AHB_GPIO0_3, + AHB_GPIO0_4, + AHB_GPIO0_5, + AHB_GPIO0_6, + AHB_GPIO0_7, + AHB_GPIO0_8, + AHB_GPIO0_9, + AHB_GPIO0_10, + AHB_GPIO0_11, + AHB_GPIO0_12, + AHB_GPIO0_13, + AHB_GPIO0_14, + AHB_GPIO0_15, + AHB_GPIO1_0 = 0U, + AHB_GPIO1_1, + AHB_GPIO1_2, + AHB_GPIO1_3, + AHB_GPIO1_4, + AHB_GPIO1_5, + AHB_GPIO1_6, + AHB_GPIO1_7, + AHB_GPIO1_8, + AHB_GPIO1_9, + AHB_GPIO1_10, + AHB_GPIO1_11, + AHB_GPIO1_12, + AHB_GPIO1_13, + AHB_GPIO1_14, + AHB_GPIO1_15, + AHB_GPIO2_0 = 0U, + AHB_GPIO2_1, + AHB_GPIO2_2, + AHB_GPIO2_3, + AHB_GPIO2_4, + AHB_GPIO2_5, + AHB_GPIO2_6, + AHB_GPIO2_7, + AHB_GPIO2_8, + AHB_GPIO2_9, + AHB_GPIO2_10, + AHB_GPIO2_11, + AHB_GPIO2_12, + AHB_GPIO2_13, + AHB_GPIO2_14, + AHB_GPIO2_15, + AHB_GPIO3_0 = 0U, + AHB_GPIO3_1, + AHB_GPIO3_2, + AHB_GPIO3_3, + AHB_GPIO3_4, + AHB_GPIO3_5, + AHB_GPIO3_6, + AHB_GPIO3_7, + AHB_GPIO3_8, + AHB_GPIO3_9, + AHB_GPIO3_10, + AHB_GPIO3_11, + AHB_GPIO3_12, + AHB_GPIO3_13, + AHB_GPIO3_14, + AHB_GPIO3_15, +}; + +/* GPIO shield 0 definition */ +#define SH0_UART_RX AHB_GPIO0_0 +#define SH0_UART_TX AHB_GPIO0_1 +#define SH0_SPI_SS AHB_GPIO0_10 +#define SH0_SPI_MOSI AHB_GPIO0_11 +#define SH0_SPI_MISO AHB_GPIO0_12 +#define SH0_SPI_SCK AHB_GPIO0_13 +#define SH0_I2C_SDA AHB_GPIO0_14 +#define SH0_I2C_SCL AHB_GPIO0_15 + +/* GPIO shield 1 definition */ +#define SH1_UART_RX AHB_GPIO1_0 +#define SH1_UART_TX AHB_GPIO1_1 + +#define SH1_SPI_SS AHB_GPIO1_10 +#define SH1_SPI_MOSI AHB_GPIO1_11 +#define SH1_SPI_MISO AHB_GPIO1_12 +#define SH1_SPI_SCK AHB_GPIO1_13 +#define SH1_I2C_SDA AHB_GPIO1_14 +#define SH1_I2C_SCL AHB_GPIO1_15 + +#endif /* __PLATFORM_PINS_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_regs.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_regs.h new file mode 100644 index 0000000..1ce6eb9 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/platform_regs.h @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2019-2021 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PLATFORM_REGS_H__ +#define __PLATFORM_REGS_H__ + +#include + +/* Secure Access Configuration Register Block */ +struct sse300_sacfg_t { + volatile uint32_t spcsecctrl; /* 0x000 (R/W) Secure Privilege Controller + Secure Configuration Control + register */ + volatile uint32_t buswait; /* 0x004 (R/W) Bus Access wait control */ + volatile uint32_t reserved0[2]; + volatile uint32_t secrespcfg; /* 0x010 (R/W) Security Violation Response + * Configuration register */ + volatile uint32_t nsccfg; /* 0x014 (R/W) Non Secure Callable + * Configuration for IDAU */ + volatile uint32_t reserved1; + volatile uint32_t secmpcintstat; /* 0x01C (R/ ) Secure MPC IRQ Status */ + volatile uint32_t secppcintstat; /* 0x020 (R/ ) Secure PPC IRQ Status */ + volatile uint32_t secppcintclr; /* 0x024 (R/W) Secure PPC IRQ Clear */ + volatile uint32_t secppcinten; /* 0x028 (R/W) Secure PPC IRQ Enable */ + volatile uint32_t reserved2; + volatile uint32_t secmscintstat; /* 0x030 (R/ ) Secure MSC IRQ Status */ + volatile uint32_t secmscintclr; /* 0x034 (R/W) Secure MSC IRQ Clear */ + volatile uint32_t secmscinten; /* 0x038 (R/W) Secure MSC IRQ Enable */ + volatile uint32_t reserved3; + volatile uint32_t brgintstat; /* 0x040 (R/ ) Bridge Buffer Error IRQ + * Status */ + volatile uint32_t brgintclr; /* 0x044 (R/W) Bridge Buffer Error IRQ + * Clear */ + volatile uint32_t brginten; /* 0x048 (R/W) Bridge Buffer Error IRQ + * Enable */ + volatile uint32_t reserved4; + volatile uint32_t mainnsppc0; /* 0x050 (R/W) Non-secure Access + * Peripheral Protection + * Control 0 on the Main + * Interconnect */ + volatile uint32_t reserved5[3]; + volatile uint32_t mainnsppcexp0; /* 0x060 (R/W) Expansion 0 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t mainnsppcexp1; /* 0x064 (R/W) Expansion 1 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t mainnsppcexp2; /* 0x068 (R/W) Expansion 2 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t mainnsppcexp3; /* 0x06C (R/W) Expansion 3 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t periphnsppc0; /* 0x070 (R/W) Non-secure Access + * Peripheral Protection + * Control 0 on the Peripheral + * Interconnect */ + volatile uint32_t periphnsppc1; /* 0x074 (R/W) Non-secure Access + * Peripheral Protection + * Control 1 on the Peripheral + * Interconnect */ + volatile uint32_t reserved6[2]; + volatile uint32_t periphnsppcexp0;/* 0x080 (R/W) Expansion 0 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t periphnsppcexp1;/* 0x084 (R/W) Expansion 1 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t periphnsppcexp2;/* 0x088 (R/W) Expansion 2 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t periphnsppcexp3;/* 0x08C (R/W) Expansion 3 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t mainspppc0; /* 0x090 (R/W) Secure Unprivileged Access + * Peripheral Protection + * Control 0 on Main + * Interconnect */ + volatile uint32_t reserved7[3]; + volatile uint32_t mainspppcexp0; /* 0x0A0 (R/W) Expansion 0 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainspppcexp1; /* 0x0A4 (R/W) Expansion 1 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainspppcexp2; /* 0x0A8 (R/W) Expansion 2 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainspppcexp3; /* 0x0AC (R/W) Expansion 3 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t periphspppc0; /* 0x0B0 (R/W) Secure Unprivileged Access + * Peripheral Protection + * Control 0 on + * Peripheral Interconnect */ + volatile uint32_t periphspppc1; /* 0x0B4 (R/W) Secure Unprivileged Access + * Peripheral Protection + * Control 1 on + * Peripheral Interconnect */ + volatile uint32_t reserved8[2]; + volatile uint32_t periphspppcexp0;/* 0x0C0 (R/W) Expansion 0 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphspppcexp1;/* 0x0C4 (R/W) Expansion 1 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphspppcexp2;/* 0x0C8 (R/W) Expansion 2 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphspppcexp3;/* 0x0CC (R/W) Expansion 3 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t nsmscexp; /* 0x0D0 (R/W) Expansion MSC Non-Secure + * Configuration */ + volatile uint32_t reserved9[959]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved10[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +/* PPC interrupt position mask */ +#define PERIPH_PPC0_INT_POS_MASK (1UL << 0) +#define PERIPH_PPC1_INT_POS_MASK (1UL << 1) +#define PERIPH_PPCEXP0_INT_POS_MASK (1UL << 4) +#define PERIPH_PPCEXP1_INT_POS_MASK (1UL << 5) +#define PERIPH_PPCEXP2_INT_POS_MASK (1UL << 6) +#define PERIPH_PPCEXP3_INT_POS_MASK (1UL << 7) +#define MAIN_PPC0_INT_POS_MASK (1UL << 16) +#define MAIN_PPCEXP0_INT_POS_MASK (1UL << 20) +#define MAIN_PPCEXP1_INT_POS_MASK (1UL << 21) +#define MAIN_PPCEXP2_INT_POS_MASK (1UL << 22) +#define MAIN_PPCEXP3_INT_POS_MASK (1UL << 23) + +/* Non-secure Access Configuration Register Block */ +struct sse300_nsacfg_t { + volatile uint32_t reserved0[36]; + volatile uint32_t mainnspppc0; /* 0x090 (R/W) Non-secure Unprivileged + * Access Peripheral + * Protection Control 0 on + * Main Interconnect */ + volatile uint32_t reserved1[3]; + + volatile uint32_t mainnspppcexp0; /* 0x0A0 (R/W) Expansion 0 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainnspppcexp1; /* 0x0A4 (R/W) Expansion 1 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainnspppcexp2; /* 0x0A8 (R/W) Expansion 2 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainnspppcexp3; /* 0x0AC (R/W) Expansion 3 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t periphnspppc0; /* 0x0B0 (R/W) Non-secure Unprivileged + * Access Peripheral + * Protection Control 0 on + * Peripheral Interconnect */ + volatile uint32_t periphnspppc1; /* 0x0B4 (R/W) Non-secure Unprivileged + * Access Peripheral + * Protection Control 1 on + * Peripheral Interconnect */ + volatile uint32_t reserved2[2]; + volatile uint32_t periphnspppcexp0;/* 0x0C0 (R/W) Expansion 0 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphnspppcexp1;/* 0x0C4 (R/W) Expansion 1 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphnspppcexp2;/* 0x0C8 (R/W) Expansion 2 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphnspppcexp3;/* 0x0CC (R/W) Expansion 3 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t reserved3[960]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved4[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +/* MAIN PPC0 peripherals definition */ +/* End MAIN PPC0 peripherals definition */ + +/* MAIN PPCEXP0 peripherals definition */ +#define GPIO0_MAIN_PPCEXP0_POS_MASK (1UL << 0) +#define GPIO1_MAIN_PPCEXP0_POS_MASK (1UL << 1) +#define GPIO2_MAIN_PPCEXP0_POS_MASK (1UL << 2) +#define GPIO3_MAIN_PPCEXP0_POS_MASK (1UL << 3) +#define USER_AHB0_MAIN_PPCEXP0_POS_MASK (1UL << 4) +#define USER_AHB1_MAIN_PPCEXP0_POS_MASK (1UL << 5) +#define USER_AHB2_MAIN_PPCEXP0_POS_MASK (1UL << 6) +#define USER_AHB3_MAIN_PPCEXP0_POS_MASK (1UL << 7) +#define USB_AND_ETHERNET_MAIN_PPCEXP0_POS_MASK (1UL << 8) +/* End MAIN PPCEXP0 peripherals definition */ + +/* MAIN PPCEXP1 peripherals definition */ +#define DMA1_MAIN_PPCEXP1_POS_MASK (1UL << 1) +#define DMA2_MAIN_PPCEXP1_POS_MASK (1UL << 2) +#define DMA3_MAIN_PPCEXP1_POS_MASK (1UL << 3) +/* End MAIN PPCEXP1 peripherals definition */ + +/* MAIN PPCEXP2 peripherals definition */ +/* End MAIN PPCEXP2 peripherals definition */ + +/* MAIN PPCEXP3 peripherals definition */ +/* End MAIN PPCEXP3 peripherals definition */ + +/* PERIPH PPC0 peripherals definition */ +#define SYSTEM_TIMER0_PERIPH_PPC0_POS_MASK (1UL << 0) +#define SYSTEM_TIMER1_PERIPH_PPC0_POS_MASK (1UL << 1) +#define SYSTEM_TIMER2_PERIPH_PPC0_POS_MASK (1UL << 2) +#define SYSTEM_TIMER3_PERIPH_PPC0_POS_MASK (1UL << 5) +#define WATCHDOG_PERIPH_PPC0_POS_MASK (1UL << 6) +/* There are separate secure and non-secure watchdog peripherals, so this bit + * can only be used in the unprivileged access registers. */ +/* End PERIPH PPC0 peripherals definition */ + +/* PERIPH PPC1 peripherals definition */ +#define SLOWCLK_TIMER_PERIPH_PPC1_POS_MASK (1UL << 0) +/* End PERIPH PPC1 peripherals definition */ + +/* PERIPH PPCEXP0 peripherals definition */ +#define USER_MEM_APB0_PERIPH_PPCEXP0_POS_MASK (1UL << 0) +#define USER_MEM_APB1_PERIPH_PPCEXP0_POS_MASK (1UL << 1) +#define NPU_APB0_PERIPH_PPCEXP0_POS_MASK (1UL << 4) +#define NPU_APB1_PERIPH_PPCEXP0_POS_MASK (1UL << 5) +#define MPC_SRAM_PERIPH_PPCEXP0_POS_MASK (1UL << 13) +#define MPC_QSPI_PERIPH_PPCEXP0_POS_MASK (1UL << 14) +#define MPC_DDR4_PERIPH_PPCEXP0_POS_MASK (1UL << 15) +/* End PERIPH PPCEXP0 peripherals definition */ + +/* PERIPH PPCEXP1 peripherals definition */ +#define FPGA_I2C_TOUCH_PERIPH_PPCEXP1_POS_MASK (1UL << 0) +#define FPGA_I2C_AUDIO_PERIPH_PPCEXP1_POS_MASK (1UL << 1) +#define FPGA_SPI_ADC_PERIPH_PPCEXP1_POS_MASK (1UL << 2) +#define FPGA_SPI_SHIELD0_PERIPH_PPCEXP1_POS_MASK (1UL << 3) +#define FPGA_SPI_SHIELD1_PERIPH_PPCEXP1_POS_MASK (1UL << 4) +#define SBCon_I2C_SHIELD0_PERIPH_PPCEXP1_POS_MASK (1UL << 5) +#define SBCon_I2C_SHIELD1_PERIPH_PPCEXP1_POS_MASK (1UL << 6) +#define FPGA_SBCon_I2C_PERIPH_PPCEXP1_POS_MASK (1UL << 8) +/* End PERIPH PPCEXP1 peripherals definition */ + +/* PERIPH PPCEXP2 peripherals definition */ +#define FPGA_SCC_PERIPH_PPCEXP2_POS_MASK (1UL << 0) +#define FPGA_I2S_PERIPH_PPCEXP2_POS_MASK (1UL << 1) +#define FPGA_IO_PERIPH_PPCEXP2_POS_MASK (1UL << 2) +#define UART0_PERIPH_PPCEXP2_POS_MASK (1UL << 3) +#define UART1_PERIPH_PPCEXP2_POS_MASK (1UL << 4) +#define UART2_PERIPH_PPCEXP2_POS_MASK (1UL << 5) +#define UART3_PERIPH_PPCEXP2_POS_MASK (1UL << 6) +#define UART4_PERIPH_PPCEXP2_POS_MASK (1UL << 7) +#define UART5_PERIPH_PPCEXP2_POS_MASK (1UL << 8) +#define CLCD_PERIPH_PPCEXP2_POS_MASK (1UL << 10) +#define RTC_PERIPH_PPCEXP2_POS_MASK (1UL << 11) +#define VSI_PERIPH_PPCEXP2_POS_MASK (1UL << 12) +/* End PERIPH PPCEXP2 peripherals definition */ + +/* PERIPH PPCEXP3 peripherals definition */ +/* End PERIPH PPCEXP3 peripherals definition */ + +struct cpu0_pwrctrl_t { + volatile uint32_t cpupwrcfg; /* 0x000 (R/W) CPU 0 Local Power + * Configuration */ + volatile uint32_t reserved0[1011]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved1[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +struct cpu0_identity_t { + volatile uint32_t cpuid; /* 0x000 (R/ ) Unique CPU 0 Identity + * Number */ + volatile uint32_t reserved0[1011]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved1[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +struct cpu0_secctrl_t { + volatile uint32_t cpuseccfg; /* 0x000 (R/W) CPU Local Security + * Configuration */ + volatile uint32_t reserved0[1011]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved1[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +struct sse300_sysinfo_t { + volatile uint32_t soc_identity; /* 0x000 (R/ ) SoC Identity Register */ + volatile uint32_t sys_config0; /* 0x004 (R/ ) System Hardware + * Configuration 0 */ + volatile uint32_t sys_config1; /* 0x008 (R/ ) System Hardware + * Configuration 1 */ + volatile uint32_t reserved0[1006]; + volatile uint32_t iidr; /* 0xFC8 (R/ ) Subsystem Implementation + * Identity */ + volatile uint32_t reserved1; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved2[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +struct sse300_sysctrl_t { + volatile uint32_t secdbgstat; /* 0x000 (R/ ) Secure Debug + * Configuration Status */ + volatile uint32_t secdbgset; /* 0x004 (R/W) Secure Debug + * Configuration Set */ + volatile uint32_t secdbgclr; /* 0x008 ( /W) Secure Debug + * Configuration Clear */ + volatile uint32_t scsecctrl; /* 0x00C (R/W) System Control Security + * Controls */ + volatile uint32_t clk_cfg0; /* 0x010 (R/W) Clock Configuration 0 */ + volatile uint32_t clk_cfg1; /* 0x014 (R/W) Clock Configuration 1 */ + volatile uint32_t clock_force; /* 0x018 (R/W) Clock Forces */ + volatile uint32_t reserved0[57]; + volatile uint32_t reset_syndrome; /* 0x100 (R/W) Reset syndrome */ + volatile uint32_t reset_mask; /* 0x104 (R/W) Reset mask */ + volatile uint32_t swreset; /* 0x108 ( /W) Software Reset */ + volatile uint32_t gretreg; /* 0x10C (R/W) General Purpose + * Retention */ + volatile uint32_t initsvtor0; /* 0x110 (R/W) CPU 0 Initial Secure + * Reset Vector Register */ + volatile uint32_t reserved1[3]; + volatile uint32_t cpuwait; /* 0x120 (R/W) CPU Boot Wait Control */ + volatile uint32_t nmi_enable; /* 0x124 (R/W) Non Maskable Interrupts + * Enable */ + volatile uint32_t reserved2[53]; + volatile uint32_t pwrctrl; /* 0x1FC (R/W) Power Configuration and + * Control */ + volatile uint32_t pdcm_pd_sys_sense; /* 0x200 (R/W) PDCM PD_SYS + * Sensitivity */ + volatile uint32_t pdcm_pd_cpu0_sense;/* 0x204 (R/ ) PDCM PD_CPU0 + * Sensitivity */ + volatile uint32_t reserved3[3]; + volatile uint32_t pdcm_pd_vmr0_sense;/* 0x214 (R/W) PDCM PD_VMR0 + * Sensitivity */ + volatile uint32_t pdcm_pd_vmr1_sense;/* 0x218 (R/W) PDCM PD_VMR1 + * Sensitivity */ + volatile uint32_t reserved4[877]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved5[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +struct sse300_ewic_t { + volatile uint32_t ewic_cr; /* 0x000 (R/W) EWIC Control */ + volatile uint32_t ewic_ascr; /* 0x004 (R/W) Automatic Sequence + * Control */ + volatile uint32_t ewic_clrmask; /* 0x008 ( /W) Clear All Mask */ + volatile uint32_t ewic_numid; /* 0x00C (R/ ) ID Register for the number + * of events supported */ + volatile uint32_t reserved0[124]; + volatile uint32_t ewic_maska; /* 0x200 (R/W) Set which internal events + * cause wakeup */ + volatile uint32_t ewic_mask[15]; /* 0x204 (R/W) Set which external + * interrupts cause wakeup + * Only the first (total + * system IRQ number)/32 + * registers are implemented + * in array */ + volatile uint32_t reserved1[112]; + volatile uint32_t ewic_penda; /* 0x400 (R/ ) Shows which internal + * interrupts were pended + * while the EWIC was + * enabled */ + + volatile uint32_t ewic_pend[15]; /* 0x404 (R/W) Shows which external + * interrupts were pended + * while the EWIC was + * enabled + * Only the first (total + * system IRQ number)/32 + * registers are implemented + * in array */ + volatile uint32_t reserved2[112]; + volatile uint32_t ewic_psr; /* 0x600 (R/ ) Pending Summary */ + volatile uint32_t reserved3[575]; + volatile uint32_t itctrl; /* 0xF00 (R/ ) Integration Mode Control */ + volatile uint32_t reserved4[39]; + volatile uint32_t claimset; /* 0xFA0 (R/W) Claim Tag Set */ + volatile uint32_t claimclr; /* 0xFA4 (R/W) Claim Tag Clear */ + volatile uint32_t devaff0; /* 0xFA8 (R/ ) Device Affinity 0 */ + volatile uint32_t devaff1; /* 0xFAC (R/ ) Device Affinity 1 */ + volatile uint32_t lar; /* 0xFB0 ( /W) Lock Access */ + volatile uint32_t lsr; /* 0xFB4 (R/ ) Lock Status */ + volatile uint32_t authstatus; /* 0xFB8 (R/ ) Authentication Status */ + volatile uint32_t devarch; /* 0xFBC (R/ ) Device Architecture */ + volatile uint32_t devid2; /* 0xFC0 (R/ ) Device Configuration 2 */ + volatile uint32_t devid1; /* 0xFC4 (R/ ) Device Configuration 1 */ + volatile uint32_t devid; /* 0xFC8 (R/ ) Device Configuration */ + volatile uint32_t devtype; /* 0xFCC (R/ ) Device Type */ + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved5[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; +#endif /* __PLATFORM_REGS_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/include/system_core_init.h b/bsp/tf_m_targets/arm/mps3/an547/device/include/system_core_init.h new file mode 100644 index 0000000..feba5e9 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/include/system_core_init.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.6.0 system_ARMv81MML.h + * Git SHA: b5f0603d6a584d1724d952fd8b0737458b90d62b + */ + +#ifndef __SYSTEM_CORE_INIT_H__ +#define __SYSTEM_CORE_INIT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ +extern uint32_t PeripheralClock; /*!< Peripheral Clock Frequency */ + +/** + * \brief Initializes the system + */ +extern void SystemInit(void); + +/** + * \brief Restores system core clock + */ +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_CORE_INIT_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_bl2.sct b/bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_bl2.sct new file mode 100644 index 0000000..1f6a34a --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_bl2.sct @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2020 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "region_defs.h" + +LR_CODE BL2_CODE_START { + ER_CODE BL2_CODE_START BL2_CODE_SIZE { + *.o (RESET +First) + * (+RO) + } + + TFM_SHARED_DATA BOOT_TFM_SHARED_DATA_BASE ALIGN 32 EMPTY BOOT_TFM_SHARED_DATA_SIZE { + } + + ER_DATA +0 { + * (+ZI +RW) + } + + /* MSP */ + ARM_LIB_STACK +0 ALIGN 32 EMPTY BL2_MSP_STACK_SIZE { + } + + ARM_LIB_HEAP +0 ALIGN 8 EMPTY BL2_HEAP_SIZE { + } + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + SRAM_WATERMARK +0 EMPTY 0x0 { + } + + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(SRAM_WATERMARK) <= BL2_DATA_START + BL2_DATA_SIZE) +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_ns.sct b/bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_ns.sct new file mode 100644 index 0000000..92707b9 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/armclang/an547_ns.sct @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2020 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "region_defs.h" + +LR_CODE NS_CODE_START { + ER_CODE NS_CODE_START NS_CODE_SIZE { + *.o (RESET +First) + * (+RO) + } + + ER_DATA NS_DATA_START { + * (+ZI +RW) + } + + /* MSP */ + ARM_LIB_STACK_MSP +0 ALIGN 32 EMPTY NS_MSP_STACK_SIZE { + } + + /* PSP */ + ARM_LIB_STACK +0 ALIGN 32 EMPTY NS_PSP_STACK_SIZE { + } + + ARM_LIB_HEAP +0 ALIGN 8 EMPTY NS_HEAP_SIZE { + } + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + SRAM_WATERMARK +0 EMPTY 0x0 { + } + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(SRAM_WATERMARK) <= NS_DATA_START + NS_DATA_SIZE) +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/device_definition.c b/bsp/tf_m_targets/arm/mps3/an547/device/source/device_definition.c new file mode 100644 index 0000000..4a18c1c --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/device_definition.c @@ -0,0 +1,677 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file device_definition.c + * \brief This file defines exports the structures based on the peripheral + * definitions from device_cfg.h. + * This file is meant to be used as a helper for baremetal + * applications and/or as an example of how to configure the generic + * driver structures. + */ + +#include "device_definition.h" +#include "platform_base_address.h" + +/* UART CMSDK driver structures */ +#ifdef UART0_CMSDK_S +static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_S = { + .base = UART0_BASE_S, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_S = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S = { + &(UART0_CMSDK_DEV_CFG_S), + &(UART0_CMSDK_DEV_DATA_S) +}; +#endif +#ifdef UART0_CMSDK_NS +static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_NS = { + .base = UART0_BASE_NS, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_NS = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART0_CMSDK_DEV_NS = { + &(UART0_CMSDK_DEV_CFG_NS), + &(UART0_CMSDK_DEV_DATA_NS) +}; +#endif + +#ifdef UART1_CMSDK_S +static const struct uart_cmsdk_dev_cfg_t UART1_CMSDK_DEV_CFG_S = { + .base = UART1_BASE_S, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART1_CMSDK_DEV_DATA_S = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART1_CMSDK_DEV_S = { + &(UART1_CMSDK_DEV_CFG_S), + &(UART1_CMSDK_DEV_DATA_S) +}; +#endif +#ifdef UART1_CMSDK_NS +static const struct uart_cmsdk_dev_cfg_t UART1_CMSDK_DEV_CFG_NS = { + .base = UART1_BASE_NS, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART1_CMSDK_DEV_DATA_NS = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART1_CMSDK_DEV_NS = { + &(UART1_CMSDK_DEV_CFG_NS), + &(UART1_CMSDK_DEV_DATA_NS) +}; +#endif + +#ifdef UART2_CMSDK_S +static const struct uart_cmsdk_dev_cfg_t UART2_CMSDK_DEV_CFG_S = { + .base = UART2_BASE_S, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART2_CMSDK_DEV_DATA_S = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART2_CMSDK_DEV_S = { + &(UART2_CMSDK_DEV_CFG_S), + &(UART2_CMSDK_DEV_DATA_S) +}; +#endif +#ifdef UART2_CMSDK_NS +static const struct uart_cmsdk_dev_cfg_t UART2_CMSDK_DEV_CFG_NS = { + .base = UART2_BASE_NS, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART2_CMSDK_DEV_DATA_NS = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART2_CMSDK_DEV_NS = { + &(UART2_CMSDK_DEV_CFG_NS), + &(UART2_CMSDK_DEV_DATA_NS) +}; +#endif + +#ifdef UART3_CMSDK_S +static const struct uart_cmsdk_dev_cfg_t UART3_CMSDK_DEV_CFG_S = { + .base = UART3_BASE_S, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART3_CMSDK_DEV_DATA_S = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART3_CMSDK_DEV_S = { + &(UART3_CMSDK_DEV_CFG_S), + &(UART3_CMSDK_DEV_DATA_S) +}; +#endif +#ifdef UART3_CMSDK_NS +static const struct uart_cmsdk_dev_cfg_t UART3_CMSDK_DEV_CFG_NS = { + .base = UART3_BASE_NS, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART3_CMSDK_DEV_DATA_NS = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART3_CMSDK_DEV_NS = { + &(UART3_CMSDK_DEV_CFG_NS), + &(UART3_CMSDK_DEV_DATA_NS) +}; +#endif + +#ifdef UART4_CMSDK_S +static const struct uart_cmsdk_dev_cfg_t UART4_CMSDK_DEV_CFG_S = { + .base = UART4_BASE_S, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART4_CMSDK_DEV_DATA_S = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART4_CMSDK_DEV_S = { + &(UART4_CMSDK_DEV_CFG_S), + &(UART4_CMSDK_DEV_DATA_S) +}; +#endif +#ifdef UART4_CMSDK_NS +static const struct uart_cmsdk_dev_cfg_t UART4_CMSDK_DEV_CFG_NS = { + .base = UART4_BASE_NS, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART4_CMSDK_DEV_DATA_NS = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART4_CMSDK_DEV_NS = { + &(UART4_CMSDK_DEV_CFG_NS), + &(UART4_CMSDK_DEV_DATA_NS) +}; +#endif + +#ifdef UART5_CMSDK_S +static const struct uart_cmsdk_dev_cfg_t UART5_CMSDK_DEV_CFG_S = { + .base = UART5_BASE_S, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART5_CMSDK_DEV_DATA_S = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART5_CMSDK_DEV_S = { + &(UART5_CMSDK_DEV_CFG_S), + &(UART5_CMSDK_DEV_DATA_S) +}; +#endif +#ifdef UART5_CMSDK_NS +static const struct uart_cmsdk_dev_cfg_t UART5_CMSDK_DEV_CFG_NS = { + .base = UART5_BASE_NS, + .default_baudrate = DEFAULT_UART_BAUDRATE +}; +static struct uart_cmsdk_dev_data_t UART5_CMSDK_DEV_DATA_NS = { + .state = 0, + .system_clk = 0, + .baudrate = 0 +}; +struct uart_cmsdk_dev_t UART5_CMSDK_DEV_NS = { + &(UART5_CMSDK_DEV_CFG_NS), + &(UART5_CMSDK_DEV_DATA_NS) +}; +#endif + +/* SSE-300 PPC driver structures */ +#ifdef PPC_SSE300_MAIN0_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_MAIN0_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_MAIN0}; +static struct ppc_sse300_dev_data_t PPC_SSE300_MAIN0_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_MAIN0_DEV_S = { + &PPC_SSE300_MAIN0_CFG_S, + &PPC_SSE300_MAIN0_DATA_S }; +#endif + +#ifdef PPC_SSE300_MAIN_EXP0_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_MAIN_EXP0_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_MAIN_EXP0}; +static struct ppc_sse300_dev_data_t PPC_SSE300_MAIN_EXP0_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP0_DEV_S = { + &PPC_SSE300_MAIN_EXP0_CFG_S, + &PPC_SSE300_MAIN_EXP0_DATA_S }; +#endif + +#ifdef PPC_SSE300_MAIN_EXP1_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_MAIN_EXP1_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_MAIN_EXP1}; +static struct ppc_sse300_dev_data_t PPC_SSE300_MAIN_EXP1_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP1_DEV_S = { + &PPC_SSE300_MAIN_EXP1_CFG_S, + &PPC_SSE300_MAIN_EXP1_DATA_S }; +#endif + +#ifdef PPC_SSE300_MAIN_EXP2_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_MAIN_EXP2_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_MAIN_EXP2}; +static struct ppc_sse300_dev_data_t PPC_SSE300_MAIN_EXP2_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP2_DEV_S = { + &PPC_SSE300_MAIN_EXP2_CFG_S, + &PPC_SSE300_MAIN_EXP2_DATA_S }; +#endif + +#ifdef PPC_SSE300_MAIN_EXP3_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_MAIN_EXP3_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_MAIN_EXP3}; +static struct ppc_sse300_dev_data_t PPC_SSE300_MAIN_EXP3_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_MAIN_EXP3_DEV_S = { + &PPC_SSE300_MAIN_EXP3_CFG_S, + &PPC_SSE300_MAIN_EXP3_DATA_S }; +#endif + +#ifdef PPC_SSE300_PERIPH0_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_PERIPH0_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_PERIPH0}; +static struct ppc_sse300_dev_data_t PPC_SSE300_PERIPH0_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_PERIPH0_DEV_S = { + &PPC_SSE300_PERIPH0_CFG_S, + &PPC_SSE300_PERIPH0_DATA_S }; +#endif + +#ifdef PPC_SSE300_PERIPH1_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_PERIPH1_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_PERIPH1}; +static struct ppc_sse300_dev_data_t PPC_SSE300_PERIPH1_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_PERIPH1_DEV_S = { + &PPC_SSE300_PERIPH1_CFG_S, + &PPC_SSE300_PERIPH1_DATA_S }; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP0_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_PERIPH_EXP0_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_PERIPH_EXP0}; +static struct ppc_sse300_dev_data_t PPC_SSE300_PERIPH_EXP0_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP0_DEV_S = { + &PPC_SSE300_PERIPH_EXP0_CFG_S, + &PPC_SSE300_PERIPH_EXP0_DATA_S }; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP1_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_PERIPH_EXP1_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_PERIPH_EXP1}; +static struct ppc_sse300_dev_data_t PPC_SSE300_PERIPH_EXP1_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP1_DEV_S = { + &PPC_SSE300_PERIPH_EXP1_CFG_S, + &PPC_SSE300_PERIPH_EXP1_DATA_S }; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP2_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_PERIPH_EXP2_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_PERIPH_EXP2}; +static struct ppc_sse300_dev_data_t PPC_SSE300_PERIPH_EXP2_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP2_DEV_S = { + &PPC_SSE300_PERIPH_EXP2_CFG_S, + &PPC_SSE300_PERIPH_EXP2_DATA_S }; +#endif + +#ifdef PPC_SSE300_PERIPH_EXP3_S +static struct ppc_sse300_dev_cfg_t PPC_SSE300_PERIPH_EXP3_CFG_S = { + .sacfg_base = SSE300_SACFG_BASE_S, + .nsacfg_base = SSE300_NSACFG_BASE_NS, + .ppc_name = PPC_SSE300_PERIPH_EXP3}; +static struct ppc_sse300_dev_data_t PPC_SSE300_PERIPH_EXP3_DATA_S = { + .sacfg_ns_ppc = 0, + .sacfg_sp_ppc = 0, + .nsacfg_nsp_ppc = 0, + .int_bit_mask = 0, + .is_initialized = false }; +struct ppc_sse300_dev_t PPC_SSE300_PERIPH_EXP3_DEV_S = { + &PPC_SSE300_PERIPH_EXP3_CFG_S, + &PPC_SSE300_PERIPH_EXP3_DATA_S }; +#endif + +/* System counters */ +#ifdef SYSCOUNTER_CNTRL_ARMV8_M_S + +#if SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT > \ + SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_MAX +#error SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT is invalid. +#endif +#if SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT > \ + SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX +#error SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT is invalid. +#endif +#if SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT > \ + SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_MAX +#error SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT is invalid. +#endif +#if SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT > \ + SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX +#error SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT is invalid. +#endif + +static const struct syscounter_armv8_m_cntrl_dev_cfg_t +SYSCOUNTER_CNTRL_ARMV8_M_DEV_CFG_S = { + .base = SYSCNTR_CNTRL_BASE_S, + .scale0.integer = SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT, + .scale0.fixed_point_fraction = SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT, + .scale1.integer = SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT, + .scale1.fixed_point_fraction = SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT +}; +static struct syscounter_armv8_m_cntrl_dev_data_t +SYSCOUNTER_CNTRL_ARMV8_M_DEV_DATA_S = { + .is_initialized = false +}; +struct syscounter_armv8_m_cntrl_dev_t SYSCOUNTER_CNTRL_ARMV8_M_DEV_S = { + &(SYSCOUNTER_CNTRL_ARMV8_M_DEV_CFG_S), + &(SYSCOUNTER_CNTRL_ARMV8_M_DEV_DATA_S) +}; +#endif + +#ifdef SYSCOUNTER_READ_ARMV8_M_S +static const struct syscounter_armv8_m_read_dev_cfg_t +SYSCOUNTER_READ_ARMV8_M_DEV_CFG_S = { + .base = SYSCNTR_READ_BASE_S, +}; +struct syscounter_armv8_m_read_dev_t SYSCOUNTER_READ_ARMV8_M_DEV_S = { + &(SYSCOUNTER_READ_ARMV8_M_DEV_CFG_S), +}; +#endif +#ifdef SYSCOUNTER_READ_ARMV8_M_NS +static const struct syscounter_armv8_m_read_dev_cfg_t +SYSCOUNTER_READ_ARMV8_M_DEV_CFG_NS = { + .base = SYSCNTR_READ_BASE_NS, +}; +struct syscounter_armv8_m_read_dev_t SYSCOUNTER_READ_ARMV8_M_DEV_NS = { + &(SYSCOUNTER_CNTRL_ARMV8_M_DEV_CFG_NS), +}; +#endif + +/* System timers */ +#ifdef SYSTIMER0_ARMV8_M_S +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER0_ARMV8_M_DEV_CFG_S = { + .base = SYSTIMER0_ARMV8_M_BASE_S, + .default_freq_hz = SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER0_ARMV8_M_DEV_DATA_S = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER0_ARMV8_M_DEV_S = { + &(SYSTIMER0_ARMV8_M_DEV_CFG_S), + &(SYSTIMER0_ARMV8_M_DEV_DATA_S) +}; +#endif + +#ifdef SYSTIMER0_ARMV8_M_NS +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER0_ARMV8_M_DEV_CFG_NS = { + .base = SYSTIMER0_ARMV8_M_BASE_NS, + .default_freq_hz = SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER0_ARMV8_M_DEV_DATA_NS = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER0_ARMV8_M_DEV_NS = { + &(SYSTIMER0_ARMV8_M_DEV_CFG_NS), + &(SYSTIMER0_ARMV8_M_DEV_DATA_NS) +}; +#endif + +#ifdef SYSTIMER1_ARMV8_M_S +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER1_ARMV8_M_DEV_CFG_S = { + .base = SYSTIMER1_ARMV8_M_BASE_S, + .default_freq_hz = SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER1_ARMV8_M_DEV_DATA_S = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER1_ARMV8_M_DEV_S = { + &(SYSTIMER1_ARMV8_M_DEV_CFG_S), + &(SYSTIMER1_ARMV8_M_DEV_DATA_S) +}; +#endif + +#ifdef SYSTIMER1_ARMV8_M_NS +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER1_ARMV8_M_DEV_CFG_NS = { + .base = SYSTIMER1_ARMV8_M_BASE_NS, + .default_freq_hz = SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER1_ARMV8_M_DEV_DATA_NS = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER1_ARMV8_M_DEV_NS = { + &(SYSTIMER1_ARMV8_M_DEV_CFG_NS), + &(SYSTIMER1_ARMV8_M_DEV_DATA_NS) +}; +#endif + +#ifdef SYSTIMER2_ARMV8_M_S +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER2_ARMV8_M_DEV_CFG_S = { + .base = SYSTIMER2_ARMV8_M_BASE_S, + .default_freq_hz = SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER2_ARMV8_M_DEV_DATA_S = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER2_ARMV8_M_DEV_S = { + &(SYSTIMER2_ARMV8_M_DEV_CFG_S), + &(SYSTIMER2_ARMV8_M_DEV_DATA_S) +}; +#endif + +#ifdef SYSTIMER2_ARMV8_M_NS +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER2_ARMV8_M_DEV_CFG_NS = { + .base = SYSTIMER2_ARMV8_M_BASE_NS, + .default_freq_hz = SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER2_ARMV8_M_DEV_DATA_NS = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER2_ARMV8_M_DEV_NS = { + &(SYSTIMER2_ARMV8_M_DEV_CFG_NS), + &(SYSTIMER2_ARMV8_M_DEV_DATA_NS) +}; +#endif + +#ifdef SYSTIMER3_ARMV8_M_S +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER3_ARMV8_M_DEV_CFG_S = { + .base = SYSTIMER3_ARMV8_M_BASE_S, + .default_freq_hz = SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER3_ARMV8_M_DEV_DATA_S = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER3_ARMV8_M_DEV_S = { + &(SYSTIMER3_ARMV8_M_DEV_CFG_S), + &(SYSTIMER3_ARMV8_M_DEV_DATA_S) +}; +#endif + +#ifdef SYSTIMER3_ARMV8_M_NS +static const struct systimer_armv8_m_dev_cfg_t +SYSTIMER3_ARMV8_M_DEV_CFG_NS = { + .base = SYSTIMER3_ARMV8_M_BASE_NS, + .default_freq_hz = SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ +}; +static struct systimer_armv8_m_dev_data_t +SYSTIMER3_ARMV8_M_DEV_DATA_NS = { + .is_initialized = false +}; +struct systimer_armv8_m_dev_t SYSTIMER3_ARMV8_M_DEV_NS = { + &(SYSTIMER3_ARMV8_M_DEV_CFG_NS), + &(SYSTIMER3_ARMV8_M_DEV_DATA_NS) +}; +#endif + +/* System Watchdogs */ +#ifdef SYSWDOG_ARMV8_M_S +static const struct syswdog_armv8_m_dev_cfg_t +SYSWDOG_ARMV8_M_DEV_CFG_S = { + .base = SYSWDOG_ARMV8_M_CNTRL_BASE_S +}; +struct syswdog_armv8_m_dev_t SYSWDOG_ARMV8_M_DEV_S = { + &(SYSWDOG_ARMV8_M_DEV_CFG_S) +}; +#endif + +#ifdef SYSWDOG_ARMV8_M_NS +static const struct syswdog_armv8_m_dev_cfg_t +SYSWDOG_ARMV8_M_DEV_CFG_NS = { + .base = SYSWDOG_ARMV8_M_CNTRL_BASE_NS +}; +struct syswdog_armv8_m_dev_t SYSWDOG_ARMV8_M_DEV_NS = { + &(SYSWDOG_ARMV8_M_DEV_CFG_NS) +}; +#endif + +/* ARM MPC SSE 300 driver structures */ +#ifdef MPC_SRAM_S +static const struct mpc_sie_dev_cfg_t MPC_SRAM_DEV_CFG_S = { + .base = MPC_SRAM_BASE_S}; +static struct mpc_sie_dev_data_t MPC_SRAM_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .is_initialized = false }; +struct mpc_sie_dev_t MPC_SRAM_DEV_S = { + &(MPC_SRAM_DEV_CFG_S), + &(MPC_SRAM_DEV_DATA_S)}; +#endif + +#ifdef MPC_QSPI_S +static const struct mpc_sie_dev_cfg_t MPC_QSPI_DEV_CFG_S = { + .base = MPC_QSPI_BASE_S}; +static struct mpc_sie_dev_data_t MPC_QSPI_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .is_initialized = false }; +struct mpc_sie_dev_t MPC_QSPI_DEV_S = { + &(MPC_QSPI_DEV_CFG_S), + &(MPC_QSPI_DEV_DATA_S)}; +#endif + +#ifdef MPC_DDR4_S +static const struct mpc_sie_dev_cfg_t MPC_DDR4_DEV_CFG_S = { + .base = MPC_DDR4_BASE_S}; +static struct mpc_sie_dev_data_t MPC_DDR4_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .is_initialized = false }; +struct mpc_sie_dev_t MPC_DDR4_DEV_S = { + &(MPC_DDR4_DEV_CFG_S), + &(MPC_DDR4_DEV_DATA_S)}; +#endif + +#ifdef MPC_ISRAM0_S +static const struct mpc_sie_dev_cfg_t MPC_ISRAM0_DEV_CFG_S = { + .base = MPC_ISRAM0_BASE_S}; +static struct mpc_sie_dev_data_t MPC_ISRAM0_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .is_initialized = false }; +struct mpc_sie_dev_t MPC_ISRAM0_DEV_S = { + &(MPC_ISRAM0_DEV_CFG_S), + &(MPC_ISRAM0_DEV_DATA_S)}; +#endif + +#ifdef MPC_ISRAM1_S +static const struct mpc_sie_dev_cfg_t MPC_ISRAM1_DEV_CFG_S = { + .base = MPC_ISRAM1_BASE_S}; +static struct mpc_sie_dev_data_t MPC_ISRAM1_DEV_DATA_S = { + .range_list = 0, + .nbr_of_ranges = 0, + .is_initialized = false }; +struct mpc_sie_dev_t MPC_ISRAM1_DEV_S = { + &(MPC_ISRAM1_DEV_CFG_S), + &(MPC_ISRAM1_DEV_DATA_S)}; +#endif + +#ifdef MPS3_IO_S +static struct arm_mps3_io_dev_cfg_t MPS3_IO_DEV_CFG_S = { + .base = FPGA_IO_BASE_S +}; +struct arm_mps3_io_dev_t MPS3_IO_DEV_S = { + .cfg = &(MPS3_IO_DEV_CFG_S) +}; +#endif + +#ifdef MPS3_IO_NS +static struct arm_mps3_io_dev_cfg_t MPS3_IO_DEV_CFG_NS = { + .base = FPGA_IO_BASE_NS +}; +struct arm_mps3_io_dev_t MPS3_IO_DEV_NS = { + .cfg = &(MPS3_IO_DEV_CFG_NS) +}; +#endif diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_bl2.ld b/bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_bl2.ld new file mode 100644 index 0000000..fac1656 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_bl2.ld @@ -0,0 +1,191 @@ +;/* +; * Copyright (c) 2021 Arm Limited. All rights reserved. +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; * +; * This file is derivative of CMSIS V5.00 gcc_arm.ld +; */ + +/* Linker script to configure memory regions. */ +/* This file will be run trough the pre-processor. */ + +#include "region_defs.h" + +MEMORY +{ + FLASH (rx) : ORIGIN = BL2_CODE_START, LENGTH = BL2_CODE_SIZE + RAM (rwx) : ORIGIN = BL2_DATA_START, LENGTH = BL2_DATA_SIZE +} + +__heap_size__ = BL2_HEAP_SIZE; +__msp_stack_size__ = BL2_MSP_STACK_SIZE; + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * define etext2/data2_start/data2_end and + * define __STARTUP_COPY_MULTIPLE in startup_cmsdk_mps3_an524_bl2.S */ + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (DEFINED(__etext2) ? __etext2 : 0) + LONG (DEFINED(__data2_start__) ? __data2_start__ : 0) + LONG (DEFINED(__data2_start__) ? __data2_end__ - __data2_start__ : 0) + __copy_table_end__ = .; + } > FLASH + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_cmsdk_mps3_an524_bl2.S */ + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (DEFINED(__bss2_start__) ? __bss2_start__ : 0) + LONG (DEFINED(__bss2_start__) ? __bss2_end__ - __bss2_start__ : 0) + __zero_table_end__ = .; + } > FLASH + + __etext = .; + + .tfm_bl2_shared_data : ALIGN(32) + { + . += BOOT_TFM_SHARED_DATA_SIZE; + } > RAM + Image$$SHARED_DATA$$RW$$Base = ADDR(.tfm_bl2_shared_data); + Image$$SHARED_DATA$$RW$$Limit = ADDR(.tfm_bl2_shared_data) + SIZEOF(.tfm_bl2_shared_data); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + Image$$ER_DATA$$Base = ADDR(.data); + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + bss_size = __bss_end__ - __bss_start__; + + .msp_stack : ALIGN(32) + { + . += __msp_stack_size__; + } > RAM + Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack); + Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack); + + .heap : ALIGN(8) + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += __heap_size__; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > RAM + Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap); + + PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit); +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_ns.ld b/bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_ns.ld new file mode 100644 index 0000000..66887d5 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/gcc/an547_ns.ld @@ -0,0 +1,190 @@ +;/* +; * Copyright (c) 2021 Arm Limited. All rights reserved. +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; * +; * This file is derivative of CMSIS V5.00 gcc_arm.ld +; */ + +/* Linker script to configure memory regions. */ +/* This file will be run trough the pre-processor. */ + +#include "region_defs.h" + +MEMORY +{ + FLASH (rx) : ORIGIN = NS_CODE_START, LENGTH = NS_CODE_SIZE + RAM (rwx) : ORIGIN = NS_DATA_START, LENGTH = NS_DATA_SIZE +} + +__heap_size__ = NS_HEAP_SIZE; +__psp_stack_size__ = NS_PSP_STACK_SIZE; +__msp_stack_size__ = NS_MSP_STACK_SIZE; + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * define etext2/data2_start/data2_end and + * define __STARTUP_COPY_MULTIPLE in startup_cmsdk_mps3_an524_ns.S */ + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (DEFINED(__etext2) ? __etext2 : 0) + LONG (DEFINED(__data2_start__) ? __data2_start__ : 0) + LONG (DEFINED(__data2_start__) ? __data2_end__ - __data2_start__ : 0) + __copy_table_end__ = .; + } > FLASH + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_cmsdk_mps3_an524_ns.S */ + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (DEFINED(__bss2_start__) ? __bss2_start__ : 0) + LONG (DEFINED(__bss2_start__) ? __bss2_end__ - __bss2_start__ : 0) + __zero_table_end__ = .; + } > FLASH + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + bss_size = __bss_end__ - __bss_start__; + + .msp_stack : ALIGN(32) + { + . += __msp_stack_size__; + } > RAM + Image$$ARM_LIB_STACK_MSP$$ZI$$Base = ADDR(.msp_stack); + Image$$ARM_LIB_STACK_MSP$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack); + + .psp_stack : ALIGN(32) + { + . += __psp_stack_size__; + } > RAM + Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.psp_stack); + Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.psp_stack) + SIZEOF(.psp_stack); + + .heap : ALIGN(8) + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += __heap_size__; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > RAM + + PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit); +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_bl2.c b/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_bl2.c new file mode 100644 index 0000000..b64ffa0 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_bl2.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.6.0 startup_ARMv81MML.c + * Git SHA: b5f0603d6a584d1724d952fd8b0737458b90d62b + */ + +#include "cmsis.h" + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler Function Prototype + *----------------------------------------------------------------------------*/ +typedef void( *pFunc )( void ); + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; + +extern void __PROGRAM_START(void) __NO_RETURN; + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void Reset_Handler (void) __NO_RETURN; + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TIMER0_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(MGMT_PPU_Handler) +DEFAULT_IRQ_HANDLER(SYS_PPU_Handler) +DEFAULT_IRQ_HANDLER(CPU0_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +DEFAULT_IRQ_HANDLER(ETHOS_U55_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const pFunc __VECTOR_TABLE[496]; + const pFunc __VECTOR_TABLE[496] __VECTOR_TABLE_ATTRIBUTE = { + (pFunc)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TIMER0_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + MGMT_PPU_Handler, /* 14: MGMT PPU Handler */ + SYS_PPU_Handler, /* 15: SYS PPU Handler */ + CPU0_PPU_Handler, /* 16: CPU0 PPU Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + DEBUG_PPU_Handler, /* 26: DEBUG PPU Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + ETHOS_U55_Handler, /* 56: Ethos-U55 Handler */ + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Handler, /* 127: UART 5 combined Interrupt */ + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_ns.c b/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_ns.c new file mode 100644 index 0000000..227fca9 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_ns.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.6.0 startup_ARMv81MML.c + * Git SHA: b5f0603d6a584d1724d952fd8b0737458b90d62b + */ + +#include "cmsis.h" +#include "region.h" + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler Function Prototype + *----------------------------------------------------------------------------*/ +typedef void( *pFunc )( void ); + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ + +#define __MSP_INITIAL_SP REGION_NAME(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Limit) +#define __MSP_STACK_LIMIT REGION_NAME(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Base) + +extern uint32_t __MSP_INITIAL_SP; +extern uint32_t __MSP_STACK_LIMIT; + +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; + +extern void __PROGRAM_START(void) __NO_RETURN; + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void Reset_Handler (void) __NO_RETURN; + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(MGMT_PPU_Handler) +DEFAULT_IRQ_HANDLER(SYS_PPU_Handler) +DEFAULT_IRQ_HANDLER(CPU0_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +DEFAULT_IRQ_HANDLER(ETHOS_U55_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(arm_npu_irq_handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const pFunc __VECTOR_TABLE[496]; + const pFunc __VECTOR_TABLE[496] __VECTOR_TABLE_ATTRIBUTE = { + (pFunc)(&__MSP_INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + MGMT_PPU_Handler, /* 14: MGMT PPU Handler */ + SYS_PPU_Handler, /* 15: SYS PPU Handler */ + CPU0_PPU_Handler, /* 16: CPU0 PPU Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + DEBUG_PPU_Handler, /* 26: DEBUG PPU Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + arm_npu_irq_handler, /* 56: Ethos-U55 Handler */ + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Handler, /* 127: UART 5 combined Interrupt */ + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + 0, /* 132: Reserved */ + 0, /* 133: Reserved */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_MSPLIM((uint32_t)(&__MSP_STACK_LIMIT)); + + SystemInit(); /* CMSIS System Initialization */ + __ASM volatile("MRS R0, control\n" /* Get control value */ + "ORR R0, R0, #2\n" /* Select switch to PSP */ + "MSR control, R0\n" /* Load control register */ + : + : + : "r0"); + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_s.c b/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_s.c new file mode 100644 index 0000000..afb5df2 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/startup_an547_s.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.6.0 startup_ARMv81MML.c + * Git SHA: b5f0603d6a584d1724d952fd8b0737458b90d62b + */ + +#include "cmsis.h" +#include "region.h" + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler Function Prototype + *----------------------------------------------------------------------------*/ +typedef void( *pFunc )( void ); + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ + +#define __MSP_INITIAL_SP REGION_NAME(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Limit) +#define __MSP_STACK_LIMIT REGION_NAME(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Base) + +extern uint32_t __MSP_INITIAL_SP; +extern uint32_t __MSP_STACK_LIMIT; + +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; + +extern void __PROGRAM_START(void) __NO_RETURN; + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void Reset_Handler (void) __NO_RETURN; + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(MGMT_PPU_Handler) +DEFAULT_IRQ_HANDLER(SYS_PPU_Handler) +DEFAULT_IRQ_HANDLER(CPU0_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +DEFAULT_IRQ_HANDLER(ETHOS_U55_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const pFunc __VECTOR_TABLE[496]; + const pFunc __VECTOR_TABLE[496] __VECTOR_TABLE_ATTRIBUTE = { + (pFunc)(&__MSP_INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + MGMT_PPU_Handler, /* 14: MGMT PPU Handler */ + SYS_PPU_Handler, /* 15: SYS PPU Handler */ + CPU0_PPU_Handler, /* 16: CPU0 PPU Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + DEBUG_PPU_Handler, /* 26: DEBUG PPU Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + ETHOS_U55_Handler, /* 56: Ethos-U55 Handler */ + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Handler, /* 127: UART 5 combined Interrupt */ + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_MSPLIM((uint32_t)(&__MSP_STACK_LIMIT)); + __set_MSP((uint32_t)(&__MSP_INITIAL_SP)); + + SystemInit(); /* CMSIS System Initialization */ + __ASM volatile("MRS R0, control\n" /* Get control value */ + "ORR R0, R0, #2\n" /* Select switch to PSP */ + "MSR control, R0\n" /* Load control register */ + : + : + : "r0"); + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/device/source/system_core_init.c b/bsp/tf_m_targets/arm/mps3/an547/device/source/system_core_init.c new file mode 100644 index 0000000..abeb294 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/device/source/system_core_init.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.6.0 system_ARMv81MML.c + * Git SHA: b5f0603d6a584d1724d952fd8b0737458b90d62b + */ + +#include "cmsis.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (32000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Externals + *----------------------------------------------------------------------------*/ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + extern uint32_t __VECTOR_TABLE; +#endif + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE); +#endif + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE == 1U)) +#if (TFM_SYSTEM_FP >= 1) || (TFM_SYSTEM_FP_NS >= 1) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + +#if defined(TFM_LAZY_STACK_NS) || defined(TFM_LAZY_STACK) + /* Enable Lazy FP */ + FPU->FPCCR |= FPU_FPCCR_LSPEN_Msk; +#else + /* Disable Lazy FP */ + FPU->FPCCR &= ~FPU_FPCCR_LSPEN_Msk; +#endif /* TFM_LAZY_FP_NS */ + +#endif /* TFM_SYSTEM_FP >= 1 || (TFM_SYSTEM_FP_NS >= 1) */ +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.c new file mode 100644 index 0000000..828b90a --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "arm_mps3_io_drv.h" + +/* There is at most 10 LEDs 8 switches and 2 buttons on MPS3 FPGA IO */ +#define MAX_PIN_FPGAIO_LED 10UL +#define MAX_PIN_FPGAIO_BUTTON 2UL +#define MAX_PIN_FPGAIO_SWITCH 8UL + +/* Mask to 1 the first X bits */ +#define MASK(X) ((1UL << (X)) - 1) + +/* MPS3 IO register map structure */ +struct arm_mps3_io_reg_map_t { + volatile uint32_t fpgaio_leds; /* Offset: 0x000 (R/W) LED connections + * [31:10] : Reserved + * [9:0] : FPGAIO LEDs */ + volatile uint32_t reserved[1]; + volatile uint32_t fpgaio_buttons; /* Offset: 0x008 (R/ ) Buttons + * [31:2] : Reserved + * [1:0] : Buttons */ + volatile uint32_t reserved2[7]; + volatile uint32_t fpgaio_switches; /* Offset: 0x028 (R/ ) Denotes the + * state of the FPGAIO + * user switches + * [31:8] : Reserved + * [7:0] : FPGAIO switches */ +}; + +void arm_mps3_io_write_leds(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num, + uint32_t value) +{ + struct arm_mps3_io_reg_map_t* p_mps3_io_port = + (struct arm_mps3_io_reg_map_t*)dev->cfg->base; + /* Mask of involved bits */ + uint32_t write_mask = 0; + + if (pin_num >= MAX_PIN_FPGAIO_LED) { + return; + } + + switch (access) { + case ARM_MPS3_IO_ACCESS_PIN: + write_mask = (1UL << pin_num); + break; + case ARM_MPS3_IO_ACCESS_PORT: + write_mask = MASK(MAX_PIN_FPGAIO_LED); + break; + /* + * default: explicitely not used to force to cover all enumeration + * cases + */ + } + + if (value) { + p_mps3_io_port->fpgaio_leds |= write_mask; + } else { + p_mps3_io_port->fpgaio_leds &= ~write_mask; + } + +} + +uint32_t arm_mps3_io_read_buttons(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num) +{ + struct arm_mps3_io_reg_map_t* p_mps3_io_port = + (struct arm_mps3_io_reg_map_t*)dev->cfg->base; + uint32_t value = 0; + + if (pin_num >= MAX_PIN_FPGAIO_BUTTON) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps3_io_port->fpgaio_buttons & + MASK(MAX_PIN_FPGAIO_BUTTON); + + if (access == ARM_MPS3_IO_ACCESS_PIN) { + value = ((value >> pin_num) & 1UL); + } + + return value; +} + +uint32_t arm_mps3_io_read_switches(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num) +{ + struct arm_mps3_io_reg_map_t* p_mps3_io_port = + (struct arm_mps3_io_reg_map_t*)dev->cfg->base; + uint32_t value = 0; + + if (pin_num >= MAX_PIN_FPGAIO_SWITCH) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps3_io_port->fpgaio_switches & + MASK(MAX_PIN_FPGAIO_SWITCH); + + + if (access == ARM_MPS3_IO_ACCESS_PIN) { + value = ((value >> pin_num) & 1UL); + } + + return value; +} + +uint32_t arm_mps3_io_read_leds(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num) +{ + struct arm_mps3_io_reg_map_t* p_mps3_io_port = + (struct arm_mps3_io_reg_map_t*)dev->cfg->base; + uint32_t value = 0; + + if (pin_num >= MAX_PIN_FPGAIO_LED) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps3_io_port->fpgaio_leds & MASK(MAX_PIN_FPGAIO_LED); + + if (access == ARM_MPS3_IO_ACCESS_PIN) { + value = ((value >> pin_num) & 1UL); + } + + return value; +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.h new file mode 100644 index 0000000..c3c4bb8 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/arm_mps3_io_drv.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file arm_mps3_io_drv.h + * \brief Generic driver for ARM MPS3 FPGAIO. + */ + +#ifndef __ARM_MPS3_IO_DRV_H__ +#define __ARM_MPS3_IO_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ARM MPS3 IO enumeration types */ +enum arm_mps3_io_access_t { + ARM_MPS3_IO_ACCESS_PIN = 0, /*!< Pin access to MPS3 IO */ + ARM_MPS3_IO_ACCESS_PORT /*!< Port access to MPS3 IO */ +}; + +/* ARM MPS3 IO device configuration structure */ +struct arm_mps3_io_dev_cfg_t { + const uint32_t base; /*!< MPS3 IO base address */ +}; + +/* ARM MPS3 IO device structure */ +struct arm_mps3_io_dev_t { + const struct arm_mps3_io_dev_cfg_t* const cfg; /*!< MPS3 IO configuration */ +}; + +/** + * \brief Writes to output LEDs. + * + * \param[in] dev MPS3 IO device where to write \ref arm_mps3_io_dev_t + * \param[in] access Access type \ref arm_mps3_io_access_t + * \param[in] pin_num Pin number. + * \param[in] value Value(s) to set. + * + * \note This function doesn't check if dev is NULL. + */ +void arm_mps3_io_write_leds(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num, + uint32_t value); + +/** + * \brief Reads the buttons status. + * + * \param[in] dev MPS3 IO device where to read \ref arm_mps3_io_dev_t + * \param[in] access Access type \ref arm_mps3_io_access_t + * \param[in] pin_num Pin number. + * + * \return Returns bit value for Pin access or port value for port access. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_mps3_io_read_buttons(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num); + +/** + * \brief Reads the switches status. + * + * \param[in] dev MPS3 IO device where to read \ref arm_mps3_io_dev_t + * \param[in] access Access type \ref arm_mps3_io_access_t + * \param[in] pin_num Pin number. + * + * \return Returns bit value for Pin access or port value for port access. + * + * \note This function doesn't check if dev is NULL. + */ + uint32_t arm_mps3_io_read_switches(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num); + +/** + * \brief Reads the LED status. + * + * \param[in] dev MPS3 IO device where to read \ref arm_mps3_io_dev_t + * \param[in] access Access type \ref arm_mps3_io_access_t + * \param[in] pin_num Pin number. + * + * \return Returns bit value for Pin access or port value for port access. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_mps3_io_read_leds(struct arm_mps3_io_dev_t* dev, + enum arm_mps3_io_access_t access, + uint8_t pin_num); + +#ifdef __cplusplus +} +#endif + +#endif /* __ARM_MPS3_IO_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.c new file mode 100644 index 0000000..23dbf50 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.c @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2016-2020 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mpc_sie_drv.h" + +#include +#include + +#include "cmsis_compiler.h" + +/* Values for hardware version in PIDR0 reg */ +#define SIE200 0x60 +#define SIE300 0x65 + +#define MPC_SIE_BLK_CFG_OFFSET 5U + +/* Defines with numbering (eg: SIE300) are only relevant to the given SIE + * version. Defines without the numbering are applicable to all SIE versions. + */ + +/* CTRL register bit indexes */ +#define MPC_SIE200_CTRL_SEC_RESP (1UL << 4UL) /* MPC fault triggers a + * bus error + */ +#define MPC_SIE300_CTRL_GATE_REQ (1UL << 6UL) /* Request for gating + * incoming transfers + */ +#define MPC_SIE300_CTRL_GATE_ACK (1UL << 7UL) /* Acknowledge for gating + * incoming transfers + */ +#define MPC_SIE_CTRL_AUTOINCREMENT (1UL << 8UL) /* BLK_IDX auto increment */ +#define MPC_SIE300_CTRL_SEC_RESP (1UL << 16UL) /* Response type when SW + * asks to gate the transfer + */ +#define MPC_SIE300_CTRL_GATE_PRESENT (1UL << 23UL) /* Gating feature present */ +#define MPC_SIE_CTRL_SEC_LOCK_DOWN (1UL << 31UL) /* MPC Security lock down */ + +/* PIDR register bit masks */ +#define MPC_PIDR0_SIE_VERSION_MASK ((1UL << 8UL) - 1UL) + +/* ARM MPC interrupt */ +#define MPC_SIE_INT_BIT (1UL) + +/* Error code returned by the internal driver functions */ +enum mpc_sie_intern_error_t { + MPC_SIE_INTERN_ERR_NONE = MPC_SIE_ERR_NONE, + MPC_SIE_INTERN_ERR_NOT_IN_RANGE = MPC_SIE_ERR_NOT_IN_RANGE, + MPC_SIE_INTERN_ERR_NOT_ALIGNED = MPC_SIE_ERR_NOT_ALIGNED, + MPC_SIE_INTERN_ERR_INVALID_RANGE = MPC_SIE_ERR_INVALID_RANGE, + MPC_INTERN_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE = + MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, + /* Calculated block index + * is higher than the maximum allowed by the MPC. It should never + * happen unless the controlled ranges of the MPC are misconfigured + * in the driver or if the IP has not enough LUTs to cover the + * range, due to wrong reported block size for example. + */ + MPC_SIE_INTERN_ERR_BLK_IDX_TOO_HIGH = -1, + +}; + +/* ARM MPC memory mapped register access structure */ +struct mpc_sie_reg_map_t { + volatile uint32_t ctrl; /* (R/W) MPC Control */ + volatile uint32_t reserved[3];/* Reserved */ + volatile uint32_t blk_max; /* (R/ ) Maximum value of block based index */ + volatile uint32_t blk_cfg; /* (R/ ) Block configuration */ + volatile uint32_t blk_idx; /* (R/W) Index value for accessing block + * based look up table + */ + volatile uint32_t blk_lutn; /* (R/W) Block based gating + * Look Up Table (LUT) + */ + volatile uint32_t int_stat; /* (R/ ) Interrupt state */ + volatile uint32_t int_clear; /* ( /W) Interrupt clear */ + volatile uint32_t int_en; /* (R/W) Interrupt enable */ + volatile uint32_t int_info1; /* (R/ ) Interrupt information 1 */ + volatile uint32_t int_info2; /* (R/ ) Interrupt information 2 */ + volatile uint32_t int_set; /* ( /W) Interrupt set. Debug purpose only */ + volatile uint32_t reserved2[998]; /* Reserved */ + volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */ + volatile uint32_t pidr5; /* (R/ ) Peripheral ID 5 */ + volatile uint32_t pidr6; /* (R/ ) Peripheral ID 6 */ + volatile uint32_t pidr7; /* (R/ ) Peripheral ID 7 */ + volatile uint32_t pidr0; /* (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* (R/ ) Component ID 3 */ +}; + +/* + * Checks if the address is controlled by the MPC and returns + * the range index in which it is contained. + * + * \param[in] dev MPC device to initialize \ref mpc_sie_dev_t + * \param[in] addr Address to check if it is controlled by MPC. + * \param[out] addr_range Range index in which it is contained. + * + * \return True if the base is controller by the range list, false otherwise. + */ +static uint32_t is_ctrl_by_range_list( + struct mpc_sie_dev_t* dev, + uint32_t addr, + const struct mpc_sie_memory_range_t** addr_range) +{ + uint32_t i; + const struct mpc_sie_memory_range_t* range; + + for(i = 0; i < dev->data->nbr_of_ranges; i++) { + range = dev->data->range_list[i]; + if(addr >= range->base && addr <= range->limit) { + *addr_range = range; + return 1; + } + } + return 0; +} + +/* + * Gets the masks selecting the bits in the LUT of the MPC corresponding + * to the base address (included) up to the limit address (included) + * + * \param[in] mpc_dev The MPC device. + * \param[in] base Address in a range controlled by this MPC + * (included), aligned on block size. + * \param[in] limit Address in a range controlled by this MPC + * (included), aligned on block size. + * \param[out] range Memory range in which the base address and + * limit are. + * \param[out] first_word_idx Index of the first touched word in the LUT. + * \param[out] nr_words Number of words used in the LUT. If 1, only + * first_word_mask is valid and limit_word_mask + * must not be used. + * \param[out] first_word_mask First word mask in the LUT will be stored here. + * \param[out] limit_word_mask Limit word mask in the LUT will be stored here. + * + * \return Returns error code as specified in \ref mpc_sie_intern_error_t + */ +static enum mpc_sie_intern_error_t get_lut_masks( + struct mpc_sie_dev_t* dev, + const uint32_t base, const uint32_t limit, + const struct mpc_sie_memory_range_t** range, + uint32_t *first_word_idx, + uint32_t *nr_words, + uint32_t *first_word_mask, + uint32_t *limit_word_mask) +{ + const struct mpc_sie_memory_range_t* base_range; + uint32_t block_size; + uint32_t base_block_idx; + uint32_t base_word_idx; + uint32_t blk_max; + const struct mpc_sie_memory_range_t* limit_range; + uint32_t limit_block_idx; + uint32_t limit_word_idx; + uint32_t mask; + uint32_t norm_base; + uint32_t norm_limit; + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + /* + * Check that the addresses are within the controlled regions + * of this MPC + */ + if(!is_ctrl_by_range_list(dev, base, &base_range) || + !is_ctrl_by_range_list(dev, limit, &limit_range)) { + return MPC_SIE_INTERN_ERR_NOT_IN_RANGE; + } + + /* Base and limit should be part of the same range */ + if(base_range != limit_range) { + return MPC_SIE_INTERN_ERR_INVALID_RANGE; + } + *range = base_range; + + block_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET)); + + /* Base and limit+1 addresses must be aligned on the MPC block size */ + if(base % block_size || (limit+1) % block_size) { + return MPC_SIE_INTERN_ERR_NOT_ALIGNED; + } + + /* + * Get a normalized address that is an offset from the beginning + * of the lowest range controlled by the MPC + */ + norm_base = (base - base_range->base) + base_range->range_offset; + norm_limit = (limit - base_range->base) + base_range->range_offset; + + /* + * Calculate block index and to which 32 bits word it belongs + */ + limit_block_idx = norm_limit/block_size; + limit_word_idx = limit_block_idx/32; + + base_block_idx = norm_base/block_size; + base_word_idx = base_block_idx/32; + + if(base_block_idx > limit_block_idx) { + return MPC_SIE_INTERN_ERR_INVALID_RANGE; + } + + /* Transmit the information to the caller */ + *nr_words = limit_word_idx - base_word_idx + 1; + *first_word_idx = base_word_idx; + + /* Limit to the highest block that can be configured */ + blk_max = p_mpc->blk_max; + + if((limit_word_idx > blk_max) || (base_word_idx > blk_max)) { + return MPC_SIE_INTERN_ERR_BLK_IDX_TOO_HIGH; + } + + /* + * Create the mask for the first word to only select the limit N bits + */ + *first_word_mask = ~((1 << (base_block_idx % 32)) - 1); + + /* + * Create the mask for the limit word to select only the first M bits. + */ + *limit_word_mask = (1 << ((limit_block_idx+1) % 32)) - 1; + /* + * If limit_word_mask is 0, it means that the limit touched block index is + * the limit in its word, so the limit word mask has all its bits selected + */ + if(*limit_word_mask == 0) { + *limit_word_mask = 0xFFFFFFFF; + } + + /* + * If the blocks to configure are all packed in one word, only + * touch this word. + * Code using the computed masks should test if this mask + * is non-zero, and if so, only use this one instead of the limit_word_mask + * and first_word_mask. + * As the only bits that are the same in both masks are the 1 that we want + * to select, just use XOR to extract them. + */ + if(base_word_idx == limit_word_idx) { + mask = ~(*first_word_mask ^ *limit_word_mask); + *first_word_mask = mask; + *limit_word_mask = mask; + } + + return MPC_SIE_INTERN_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev, + const struct mpc_sie_memory_range_t** range_list, + uint8_t nbr_of_ranges) +{ + if((range_list == NULL) || (nbr_of_ranges == 0)) { + return MPC_SIE_INVALID_ARG; + } + + dev->data->sie_version = get_sie_version(dev); + + if ((dev->data->sie_version != SIE200) && + (dev->data->sie_version != SIE300)) { + return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION; + } + + dev->data->range_list = range_list; + dev->data->nbr_of_ranges = nbr_of_ranges; + dev->data->is_initialized = true; + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev, + uint32_t* blk_size) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + if(blk_size == 0) { + return MPC_SIE_INVALID_ARG; + } + + /* Calculate the block size in byte according to the manual */ + *blk_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET)); + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev, + const uint32_t base, + const uint32_t limit, + enum mpc_sie_sec_attr_t attr) +{ + enum mpc_sie_intern_error_t error; + uint32_t first_word_idx; + uint32_t first_word_mask; + uint32_t i; + uint32_t limit_word_mask; + uint32_t limit_word_idx; + uint32_t nr_words; + const struct mpc_sie_memory_range_t* range; + uint32_t word_value; + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + /* Get the bitmasks used to select the bits in the LUT */ + error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words, + &first_word_mask, &limit_word_mask); + + limit_word_idx = first_word_idx + nr_words - 1; + + if(error != MPC_SIE_INTERN_ERR_NONE) { + /* Map internal error code lower than 0 to a generic errpr */ + if(error < 0) { + return MPC_SIE_ERR_INVALID_RANGE; + } + return (enum mpc_sie_error_t)error; + } + + /* + * The memory range should allow accesses in with the wanted security + * attribute if it requires special attribute for successful accesses + */ + if(range->attr != attr) { + return MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE; + } + + /* + * Starts changing actual configuration so issue DMB to ensure every + * transaction has completed by now + */ + __DMB(); + + /* Set the block index to the first word that will be updated */ + p_mpc->blk_idx = first_word_idx; + + /* If only one word needs to be touched in the LUT */ + if(nr_words == 1) { + word_value = p_mpc->blk_lutn; + if(attr == MPC_SIE_SEC_ATTR_NONSECURE) { + word_value |= first_word_mask; + } else { + word_value &= ~first_word_mask; + } + + /* + * Set the index again because full word read or write could have + * incremented it + */ + p_mpc->blk_idx = first_word_idx; + p_mpc->blk_lutn = word_value; + + /* Commit the configuration change */ + __DSB(); + __ISB(); + + return MPC_SIE_ERR_NONE; + } + + /* First word */ + word_value = p_mpc->blk_lutn; + if(attr == MPC_SIE_SEC_ATTR_NONSECURE) { + word_value |= first_word_mask; + } else { + word_value &= ~first_word_mask; + } + /* + * Set the index again because full word read or write could have + * incremented it + */ + p_mpc->blk_idx = first_word_idx; + /* Partially configure the first word */ + p_mpc->blk_lutn = word_value; + + /* Fully configure the intermediate words if there are any */ + for(i=first_word_idx+1; iblk_idx = i; + if(attr == MPC_SIE_SEC_ATTR_NONSECURE) { + p_mpc->blk_lutn = 0xFFFFFFFF; + } else { + p_mpc->blk_lutn = 0x00000000; + } + } + + /* Partially configure the limit word */ + p_mpc->blk_idx = limit_word_idx; + word_value = p_mpc->blk_lutn; + if(attr == MPC_SIE_SEC_ATTR_NONSECURE) { + word_value |= limit_word_mask; + } else { + word_value &= ~limit_word_mask; + } + p_mpc->blk_idx = limit_word_idx; + p_mpc->blk_lutn = word_value; + + /* Commit the configuration change */ + __DSB(); + __ISB(); + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_get_region_config( + struct mpc_sie_dev_t* dev, + uint32_t base, uint32_t limit, + enum mpc_sie_sec_attr_t* attr) +{ + enum mpc_sie_sec_attr_t attr_prev; + uint32_t block_size; + uint32_t block_size_mask; + enum mpc_sie_intern_error_t error; + uint32_t first_word_idx; + uint32_t first_word_mask; + uint32_t i; + uint32_t limit_word_idx; + uint32_t limit_word_mask; + uint32_t nr_words; + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + const struct mpc_sie_memory_range_t* range; + uint32_t word_value; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + if(attr == 0) { + return MPC_SIE_INVALID_ARG; + } + + /* + * Initialize the security attribute to mixed in case of early + * termination of this function. A caller that does not check the + * returned error will act as if it does not know anything about the + * region queried, which is the safest bet + */ + *attr = MPC_SIE_SEC_ATTR_MIXED; + + /* + * If the base and limit are not aligned, align them and make sure + * that the resulting region fully includes the original region + */ + block_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET)); + + block_size_mask = block_size - 1; + base &= ~(block_size_mask); + limit &= ~(block_size_mask); + limit += block_size - 1; /* Round to the upper block address, + * and then remove one to get the preceding + * address. + */ + + /* Get the bitmasks used to select the bits in the LUT */ + error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words, + &first_word_mask, &limit_word_mask); + + limit_word_idx = first_word_idx+nr_words - 1; + + if(error != MPC_SIE_INTERN_ERR_NONE) { + /* Map internal error code lower than 0 to generic error */ + if(error < 0) { + return MPC_SIE_ERR_INVALID_RANGE; + } + return (enum mpc_sie_error_t)error; + } + + /* Set the block index to the first word that will be updated */ + p_mpc->blk_idx = first_word_idx; + + /* If only one word needs to be touched in the LUT */ + if(nr_words == 1) { + word_value = p_mpc->blk_lutn; + word_value &= first_word_mask; + if(word_value == 0) { + *attr = MPC_SIE_SEC_ATTR_SECURE; + /* + * If there are differences between the mask and the word value, + * it means that the security attributes of blocks are mixed + */ + } else if(word_value ^ first_word_mask) { + *attr = MPC_SIE_SEC_ATTR_MIXED; + } else { + *attr = MPC_SIE_SEC_ATTR_NONSECURE; + } + return MPC_SIE_ERR_NONE; + } + + /* Get the partial configuration of the first word */ + word_value = p_mpc->blk_lutn & first_word_mask; + if(word_value == 0x00000000) { + *attr = MPC_SIE_SEC_ATTR_SECURE; + } else if(word_value ^ first_word_mask) { + *attr = MPC_SIE_SEC_ATTR_MIXED; + /* + * Bail out as the security attribute will be the same regardless + * of the configuration of other blocks + */ + return MPC_SIE_ERR_NONE; + } else { + *attr = MPC_SIE_SEC_ATTR_NONSECURE; + } + /* + * Store the current found attribute, to check that all the blocks indeed + * have the same security attribute. + */ + attr_prev = *attr; + + /* Get the configuration of the intermediate words if there are any */ + for(i=first_word_idx+1; iblk_idx = i; + word_value = p_mpc->blk_lutn; + if(word_value == 0x00000000) { + *attr = MPC_SIE_SEC_ATTR_SECURE; + } else if(word_value == 0xFFFFFFFF) { + *attr = MPC_SIE_SEC_ATTR_NONSECURE; + } else { + *attr = MPC_SIE_SEC_ATTR_MIXED; + return MPC_SIE_ERR_NONE; + } + + /* If the attribute is different than the one found before, bail out */ + if(*attr != attr_prev) { + *attr = MPC_SIE_SEC_ATTR_MIXED; + return MPC_SIE_ERR_NONE; + } + attr_prev = *attr; + } + + /* Get the partial configuration of the limit word */ + p_mpc->blk_idx = limit_word_idx; + word_value = p_mpc->blk_lutn & limit_word_mask; + if(word_value == 0x00000000) { + *attr = MPC_SIE_SEC_ATTR_SECURE; + } else if(word_value ^ first_word_mask) { + *attr = MPC_SIE_SEC_ATTR_MIXED; + return MPC_SIE_ERR_NONE; + } else { + *attr = MPC_SIE_SEC_ATTR_NONSECURE; + } + + if(*attr != attr_prev) { + *attr = MPC_SIE_SEC_ATTR_MIXED; + return MPC_SIE_ERR_NONE; + } + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev, + uint32_t* ctrl_val) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + if(ctrl_val == 0) { + return MPC_SIE_INVALID_ARG; + } + + *ctrl_val = p_mpc->ctrl; + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev, + uint32_t mpc_ctrl) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + p_mpc->ctrl = mpc_ctrl; + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev, + enum mpc_sie_sec_resp_t* sec_rep) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + bool gating_present = false; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + if(sec_rep == NULL) { + return MPC_SIE_INVALID_ARG; + } + + if (dev->data->sie_version == SIE200) { + if(p_mpc->ctrl & MPC_SIE200_CTRL_SEC_RESP) { + *sec_rep = MPC_SIE_RESP_BUS_ERROR; + } else { + *sec_rep = MPC_SIE_RESP_RAZ_WI; + } + + } else if (dev->data->sie_version == SIE300) { + mpc_sie_is_gating_present(dev, &gating_present); + if (!gating_present) { + return MPC_SIE_ERR_GATING_NOT_PRESENT; + } + + if(p_mpc->ctrl & MPC_SIE300_CTRL_SEC_RESP) { + /* MPC returns a BUS ERROR response */ + *sec_rep = MPC_SIE_RESP_BUS_ERROR; + } else { + /* MPC sets the ready signals LOW, which stalls any transactions */ + *sec_rep = MPC_SIE_RESP_WAIT_GATING_DISABLED; + } + } else { + return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION; + } + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev, + enum mpc_sie_sec_resp_t sec_rep) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + bool gating_present = false; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + if (dev->data->sie_version == SIE200) { + if (sec_rep == MPC_SIE_RESP_BUS_ERROR) { + p_mpc->ctrl |= MPC_SIE200_CTRL_SEC_RESP; + } else if (sec_rep == MPC_SIE_RESP_RAZ_WI) { + p_mpc->ctrl &= ~MPC_SIE200_CTRL_SEC_RESP; + } else { + return MPC_SIE_INVALID_ARG; + } + + } else if (dev->data->sie_version == SIE300) { + mpc_sie_is_gating_present(dev, &gating_present); + if (!gating_present) { + return MPC_SIE_ERR_GATING_NOT_PRESENT; + } + + if (sec_rep == MPC_SIE_RESP_BUS_ERROR) { + p_mpc->ctrl |= MPC_SIE300_CTRL_SEC_RESP; + } else if (sec_rep == MPC_SIE_RESP_WAIT_GATING_DISABLED) { + p_mpc->ctrl &= ~MPC_SIE300_CTRL_SEC_RESP; + } else { + return MPC_SIE_INVALID_ARG; + } + + } else { + return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION; + } + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + p_mpc->int_en |= MPC_SIE_INT_BIT; + + return MPC_SIE_ERR_NONE; +} + +void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + p_mpc->int_en &= ~MPC_SIE_INT_BIT; +} + +void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + p_mpc->int_clear = MPC_SIE_INT_BIT; +} + +uint32_t mpc_sie_irq_state(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + return (p_mpc->int_stat & MPC_SIE_INT_BIT); +} + +enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + p_mpc->ctrl |= (MPC_SIE_CTRL_AUTOINCREMENT + | MPC_SIE_CTRL_SEC_LOCK_DOWN); + + return MPC_SIE_ERR_NONE; +} + +enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev, + bool* gating_present) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + if(dev->data->is_initialized != true) { + return MPC_SIE_NOT_INIT; + } + + if (dev->data->sie_version != SIE300) { + return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION; + } + + *gating_present = (bool)(p_mpc->ctrl & MPC_SIE300_CTRL_GATE_PRESENT); + + return MPC_SIE_ERR_NONE; +} + +uint32_t get_sie_version(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + return p_mpc->pidr0 & MPC_PIDR0_SIE_VERSION_MASK; +} + +bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + return (bool)(p_mpc->ctrl & MPC_SIE300_CTRL_GATE_ACK); +} + +void mpc_sie_request_gating(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + p_mpc->ctrl |= MPC_SIE300_CTRL_GATE_REQ; +} + +void mpc_sie_release_gating(struct mpc_sie_dev_t* dev) +{ + struct mpc_sie_reg_map_t* p_mpc = + (struct mpc_sie_reg_map_t*)dev->cfg->base; + + p_mpc->ctrl &= ~MPC_SIE300_CTRL_GATE_REQ; +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.h new file mode 100644 index 0000000..927d0a8 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpc_sie_drv.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2016-2019 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file mpc_sie_drv.h + * \brief Generic driver for ARM SIE Memory Protection + * Controllers (MPC). + */ + +#ifndef __MPC_SIE__DRV_H__ +#define __MPC_SIE__DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error code returned by the driver functions */ +enum mpc_sie_error_t { + MPC_SIE_ERR_NONE, /*!< No error */ + MPC_SIE_INVALID_ARG, /*!< MPC invalid input arguments */ + MPC_SIE_NOT_INIT, /*!< MPC not initialized */ + MPC_SIE_ERR_NOT_IN_RANGE, /*!< Address does not belong to a range + * controlled by the MPC */ + MPC_SIE_ERR_NOT_ALIGNED, /*!< Address is not aligned on the block size + * of this MPC + */ + MPC_SIE_ERR_INVALID_RANGE, /*!< The given address range to configure + * is invalid. This could be because: + * - The base and limit swapped + * - The base and limit addresses + * are in different ranges + */ + MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, /*!< The given range cannot be + * accessed with the wanted + * security attributes + */ + MPC_SIE_UNSUPPORTED_HARDWARE_VERSION, /*!< MPC hardware version read from + * PIDR0 is not supported + */ + MPC_SIE_ERR_GATING_NOT_PRESENT /*!< MPC gating not present in HW */ +}; + +/* Security attribute used in various place of the API */ +enum mpc_sie_sec_attr_t { + MPC_SIE_SEC_ATTR_SECURE, /*!< Secure attribute */ + MPC_SIE_SEC_ATTR_NONSECURE, /*!< Non-secure attribute */ + /*!< Used when getting the configuration of a memory range and some blocks + * are secure whereas some other are non secure + */ + MPC_SIE_SEC_ATTR_MIXED, +}; + +/* What can happen when trying to do an illegal memory access */ +enum mpc_sie_sec_resp_t { + MPC_SIE_RESP_RAZ_WI, /*!< Read As Zero, Write Ignored */ + MPC_SIE_RESP_BUS_ERROR, /*!< Bus error */ + MPC_SIE_RESP_WAIT_GATING_DISABLED /*!< Wait until gating is disabled */ +}; + +/* Description of a memory range controlled by the MPC */ +struct mpc_sie_memory_range_t { + const uint32_t base; /*!< Base address (included in the range) */ + const uint32_t limit; /*!< Limit address (included in the range) */ + const uint32_t range_offset; /*!< Offset of current range area to the 0 + * point of the whole area (the sum of the + * sizes of the previous memory ranges + * covered by the same MPC) + */ + const enum mpc_sie_sec_attr_t attr; /*!< Optional security attribute + * needed to be matched when + * accessing this range. + * For example, the non-secure + * alias of a memory region can not + * be accessed using secure access, + * and configuring the MPC to + * secure using that range will not + * be permitted by the driver. + */ +}; + +/* ARM MPC SIE device configuration structure */ +struct mpc_sie_dev_cfg_t { + const uint32_t base; /*!< MPC base address */ +}; + +/* ARM MPC SIE device data structure */ +struct mpc_sie_dev_data_t { + /*!< Array of pointers to memory ranges controlled by the MPC */ + const struct mpc_sie_memory_range_t** range_list; + uint8_t nbr_of_ranges; /*!< Number of memory ranges in the list */ + bool is_initialized; /*!< Indicates if the MPC driver + * is initialized and enabled + */ + uint32_t sie_version; /*!< SIE version */ +}; + +/* ARM MPC SIE device structure */ +struct mpc_sie_dev_t { + const struct mpc_sie_dev_cfg_t* const cfg; /*!< MPC configuration */ + struct mpc_sie_dev_data_t* const data; /*!< MPC data */ +}; + +/** + * \brief Initializes a MPC device. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[in] range_list List of memory ranges controller by the MPC + * (\ref mpc_sie_memory_range_t). This list can not + * freed after the initializations. + * \param[in] nbr_of_ranges Number of memory ranges + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev, + const struct mpc_sie_memory_range_t** range_list, + uint8_t nbr_of_ranges); + +/** + * \brief Gets MPC block size. All regions must be aligned on this block + * size (base address and limit+1 address). + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[out] blk_size MPC block size + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev, + uint32_t* blk_size); + +/** + * \brief Configures a memory region (base and limit included). + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[in] base Base address of the region to poll. This bound is + * included. It does not need to be aligned in any way. + * + * \param[in] limit Limit address of the region to poll. This bound is + * included. (limit+1) does not need to be aligned + * in any way. + * \param[in] attr Security attribute of the region. If the region has mixed + * secure/non-secure, a special value is returned + * (\ref mpc_sie_sec_attr_t). + * + * In case base and limit+1 addresses are not aligned on + * the block size, the enclosing region with base and + * limit+1 aligned on block size will be queried. + * In case of early termination of the function (error), the + * security attribute will be set to MPC_SIE_ATTR_MIXED. + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev, + const uint32_t base, + const uint32_t limit, + enum mpc_sie_sec_attr_t attr); + +/** + * \brief Gets a memory region configuration(base and limit included). + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[in] base Base address of the region to get the configuration. + * \param[in] limit Limit address of the region to get the configuration. + * \param[out] attr Security attribute of the region + * \ref mpc_sie_sec_attr_t + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_get_region_config(struct mpc_sie_dev_t* dev, + uint32_t base, + uint32_t limit, + enum mpc_sie_sec_attr_t* attr); + +/** + * \brief Gets the MPC control value. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[out] ctrl_val Current MPC control value. + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev, + uint32_t* ctrl_val); + +/** + * \brief Sets the MPC control value. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[in] mpc_ctrl New MPC control value + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev, + uint32_t mpc_ctrl); + +/** + * \brief Gets the configured secure response. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[out] sec_rep Configured secure response (\ref mpc_sie_sec_resp_t). + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev, + enum mpc_sie_sec_resp_t* sec_rep); + +/** + * \brief Sets the response type when SW asks to gate the incoming transfers. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[in] sec_rep Secure response to configure (\ref mpc_sie_sec_resp_t). + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev, + enum mpc_sie_sec_resp_t sec_rep); + +/** + * \brief Enables MPC interrupt. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev); + +/** + * \brief Disables MPC interrupt + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev); + +/** + * \brief Clears MPC interrupt. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev); + +/** + * \brief Returns the MPC interrupt state. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \return Returns 1 if the interrupt is active, 0 otherwise. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t mpc_sie_irq_state(struct mpc_sie_dev_t* dev); + +/** + * \brief Locks down the MPC configuration. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev); + +/** + * \brief Returns if gating is present in hardware. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * \param[out] gating_present Returns if gating is present in hardware. + * + * \return Returns error code as specified in \ref mpc_sie_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev, + bool* gating_present); + +/** + * \brief Returns the value of Peripheral ID 0 register. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \return Returns the value of Peripheral ID 0 register. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t get_sie_version(struct mpc_sie_dev_t* dev); + +/** + * \brief Reads bit indicating acknowledge for gating incoming transfers. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \return True if acknowledge is set. + * + * \note This function doesn't check if dev is NULL. + */ +bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev); + +/** + * \brief Sets bit to request for gating incoming transfers. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void mpc_sie_request_gating(struct mpc_sie_dev_t* dev); + +/** + * \brief Clears bit to request for gating incoming transfers. + * + * \param[in] dev MPC device \ref mpc_sie_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void mpc_sie_release_gating(struct mpc_sie_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __MPC_SIE_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.c new file mode 100644 index 0000000..0caa024 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "mpu_armv8m_drv.h" +#include "cmsis.h" + +/* + * FixMe: + * This is a beta quality driver for MPU in v8M. To be finalized. + */ + +enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev, + uint32_t privdef_en, + uint32_t hfnmi_en) +{ + /*No error checking*/ + + MPU_Type *mpu = (MPU_Type *)dev->base; + + /* + * FixMe: Set 3 pre-defined MAIR_ATTR for memory. The attributes come + * from default memory map, need to check if fine-tune is necessary. + * + * MAIR0_0: Peripheral, Device-nGnRE. + * MAIR0_1: Code, WT RA. Same attr for Outer and Inner. + * MAIR0_2: SRAM, WBWA RA. Same attr for Outer and Inner. + */ + mpu->MAIR0 = (MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL << MPU_MAIR0_Attr0_Pos) | + (MPU_ARMV8M_MAIR_ATTR_CODE_VAL << MPU_MAIR0_Attr1_Pos) | + (MPU_ARMV8M_MAIR_ATTR_DATA_VAL << MPU_MAIR0_Attr2_Pos); + + mpu->CTRL = + (privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) | + (hfnmi_en ? MPU_CTRL_HFNMIENA_Msk : 0); + + /*Ensure all configuration is written before enable*/ + + mpu->CTRL |= MPU_CTRL_ENABLE_Msk; + + /* Enable MPU before next instruction */ + __DSB(); + __ISB(); + return MPU_ARMV8M_OK; +} + +enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev) +{ + MPU_Type *mpu = (MPU_Type *)dev->base; + + /* Reset all fields as enable does full setup */ + mpu->CTRL = 0; + + return MPU_ARMV8M_OK; +} + + +enum mpu_armv8m_error_t mpu_armv8m_region_enable( + struct mpu_armv8m_dev_t *dev, + struct mpu_armv8m_region_cfg_t *region_cfg) +{ + MPU_Type *mpu = (MPU_Type *)dev->base; + + enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK; + uint32_t ctrl_before; + uint32_t base_cfg; + uint32_t limit_cfg; + + /*FIXME : Add complete error checking*/ + if ((region_cfg->region_base & ~MPU_RBAR_BASE_Msk) != 0) { + return MPU_ARMV8M_ERROR; + } + /* region_limit doesn't need to be aligned but the scatter + * file needs to be setup to ensure that partitions do not overlap. + */ + + ctrl_before = mpu->CTRL; + mpu->CTRL = 0; + + mpu->RNR = region_cfg->region_nr & MPU_RNR_REGION_Msk; + + /* This 0s the lower bits of the base address */ + base_cfg = region_cfg->region_base & MPU_RBAR_BASE_Msk; + base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk; + base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk; + base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk; + + mpu->RBAR = base_cfg; + + /*This 0s the lower bits of base address but they are treated as 1 */ + limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk; + + limit_cfg |= (region_cfg->region_attridx << MPU_RLAR_AttrIndx_Pos) & + MPU_RLAR_AttrIndx_Msk; + +#ifdef TFM_PXN_ENABLE + limit_cfg |= (region_cfg->attr_pxn << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk; +#endif + + limit_cfg |= MPU_RLAR_EN_Msk; + + mpu->RLAR = limit_cfg; + + /*Restore main MPU control*/ + mpu->CTRL = ctrl_before; + + /* Enable MPU before the next instruction */ + __DSB(); + __ISB(); + + return ret_val; +} + + +enum mpu_armv8m_error_t mpu_armv8m_region_disable( + struct mpu_armv8m_dev_t *dev, + uint32_t region_nr) +{ + + MPU_Type *mpu = (MPU_Type *)dev->base; + + enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK; + uint32_t ctrl_before; + + /*FIXME : Add complete error checking*/ + + ctrl_before = mpu->CTRL; + mpu->CTRL = 0; + + mpu->RNR = region_nr & MPU_RNR_REGION_Msk; + + mpu->RBAR = 0; + mpu->RLAR = 0; + + /*Restore main MPU control*/ + mpu->CTRL = ctrl_before; + + return ret_val; +} + +enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev) +{ + MPU_Type *mpu = (MPU_Type *)dev->base; + uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; + + while (i > 0) { + mpu_armv8m_region_disable(dev, i-1); + i--; + } + + return MPU_ARMV8M_OK; + +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.h new file mode 100644 index 0000000..de51999 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/mpu_armv8m_drv.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2017-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __MPU_ARMV8M_DRV_H__ +#define __MPU_ARMV8M_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PRIVILEGED_DEFAULT_ENABLE 1 +#define HARDFAULT_NMI_ENABLE 1 + +/* MAIR_ATTR */ +#define MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL 0x04 +#define MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX 0 +#define MPU_ARMV8M_MAIR_ATTR_CODE_VAL 0xAA +#define MPU_ARMV8M_MAIR_ATTR_CODE_IDX 1 +#define MPU_ARMV8M_MAIR_ATTR_DATA_VAL 0xFF +#define MPU_ARMV8M_MAIR_ATTR_DATA_IDX 2 + +struct mpu_armv8m_dev_t { + const uint32_t base; +}; + +enum mpu_armv8m_error_t { + MPU_ARMV8M_OK, + MPU_ARMV8M_ERROR +}; + +enum mpu_armv8m_attr_exec_t { + MPU_ARMV8M_XN_EXEC_OK, + MPU_ARMV8M_XN_EXEC_NEVER +}; + +enum mpu_armv8m_attr_access_t { + MPU_ARMV8M_AP_RW_PRIV_ONLY, + MPU_ARMV8M_AP_RW_PRIV_UNPRIV, + MPU_ARMV8M_AP_RO_PRIV_ONLY, + MPU_ARMV8M_AP_RO_PRIV_UNPRIV +}; + +enum mpu_armv8m_attr_shared_t { + MPU_ARMV8M_SH_NONE, + MPU_ARMV8M_SH_UNUSED, + MPU_ARMV8M_SH_OUTER, + MPU_ARMV8M_SH_INNER +}; + +#ifdef TFM_PXN_ENABLE +enum mpu_armv8m_attr_priv_exec_t { + MPU_ARMV8M_PRIV_EXEC_OK, + MPU_ARMV8M_PRIV_EXEC_NEVER +}; +#endif + +struct mpu_armv8m_region_cfg_t { + uint32_t region_nr; + uint32_t region_base; + uint32_t region_limit; + uint32_t region_attridx; + enum mpu_armv8m_attr_exec_t attr_exec; + enum mpu_armv8m_attr_access_t attr_access; + enum mpu_armv8m_attr_shared_t attr_sh; +#ifdef TFM_PXN_ENABLE + enum mpu_armv8m_attr_priv_exec_t attr_pxn; +#endif +}; + +struct mpu_armv8m_region_cfg_raw_t { + uint32_t region_nr; + uint32_t region_base; + uint32_t region_limit; +}; + + +/** + * \brief Enable MPU + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * \param[in] privdef_en privilege default region 1:enable 0:disable + * \param[in] hfnmi_en mpu for hard fault & nmi 1:enable 0:disable + * + * \return Error code \ref mpu_armv8m_error_t + * + * \note This function doesn't check if dev is NULL. + */ + +enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev, + uint32_t privdef_en, + uint32_t hfnmi_en); + +/** + * \brief Disable MPU + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev); + +/** + * \brief Disable MPU and clean all regions + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev); + +/** + * \brief Enable MPU Region + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * \param[in] region_cfg MPU region config \ref mpu_armv8m_region_cfg_t + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_region_enable( + struct mpu_armv8m_dev_t *dev, + struct mpu_armv8m_region_cfg_t *region_cfg); + +/** + * \brief Disable MPU Region + * + * \param[in] dev MPU device \ref mpu_armv8m_dev_t + * \param[in] region_nr Region number + * + * \return Error code \ref arm_mpu_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum mpu_armv8m_error_t mpu_armv8m_region_disable( + struct mpu_armv8m_dev_t *dev, + uint32_t region_nr); + +#ifdef __cplusplus +} +#endif + +#endif /* __MPU_ARMV8M_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.c new file mode 100644 index 0000000..38d068d --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.c @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ppc_sse300_drv.h" +#include +#include + +/* Default peripheral states */ +#define SECURE_AS_DEFAULT_PERIPHERAL_STATE true +#define PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE true + +/* Secure Access Configuration Register Block */ +struct sse300_sacfg_block_t { + volatile uint32_t reserved0[8]; + volatile uint32_t secppcintstat; /* 0x020 (R/ ) Secure PPC IRQ Status */ + volatile uint32_t secppcintclr; /* 0x024 (R/W) Secure PPC IRQ Clear */ + volatile uint32_t secppcinten; /* 0x028 (R/W) Secure PPC IRQ Enable */ + volatile uint32_t reserved1[9]; + volatile uint32_t mainnsppc0; /* 0x050 (R/W) Non-secure Access + * Peripheral Protection + * Control 0 on the Main + * Interconnect */ + volatile uint32_t reserved2[3]; + volatile uint32_t mainnsppcexp0; /* 0x060 (R/W) Expansion 0 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t mainnsppcexp1; /* 0x064 (R/W) Expansion 1 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t mainnsppcexp2; /* 0x068 (R/W) Expansion 2 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t mainnsppcexp3; /* 0x06C (R/W) Expansion 3 Non-secure + * Access Peripheral + * Protection Control on the + * Main Interconnect */ + volatile uint32_t periphnsppc0; /* 0x070 (R/W) Non-secure Access + * Peripheral Protection + * Control 0 on the Peripheral + * Interconnect */ + volatile uint32_t periphnsppc1; /* 0x074 (R/W) Non-secure Access + * Peripheral Protection + * Control 1 on the Peripheral + * Interconnect */ + volatile uint32_t reserved3[2]; + volatile uint32_t periphnsppcexp0;/* 0x080 (R/W) Expansion 0 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t periphnsppcexp1;/* 0x084 (R/W) Expansion 1 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t periphnsppcexp2;/* 0x088 (R/W) Expansion 2 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t periphnsppcexp3;/* 0x08C (R/W) Expansion 3 Non-secure + * Access Peripheral + * Protection Control on + * Peripheral Bus */ + volatile uint32_t mainspppc0; /* 0x090 (R/W) Secure Unprivileged Access + * Peripheral Protection + * Control 0 on Main + * Interconnect */ + volatile uint32_t reserved4[3]; + volatile uint32_t mainspppcexp0; /* 0x0A0 (R/W) Expansion 0 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainspppcexp1; /* 0x0A4 (R/W) Expansion 1 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainspppcexp2; /* 0x0A8 (R/W) Expansion 2 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainspppcexp3; /* 0x0AC (R/W) Expansion 3 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t periphspppc0; /* 0x0B0 (R/W) Secure Unprivileged Access + * Peripheral Protection + * Control 0 on + * Peripheral Interconnect */ + volatile uint32_t periphspppc1; /* 0x0B4 (R/W) Secure Unprivileged Access + * Peripheral Protection + * Control 1 on + * Peripheral Interconnect */ + volatile uint32_t reserved5[2]; + volatile uint32_t periphspppcexp0;/* 0x0C0 (R/W) Expansion 0 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphspppcexp1;/* 0x0C4 (R/W) Expansion 1 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphspppcexp2;/* 0x0C8 (R/W) Expansion 2 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphspppcexp3;/* 0x0CC (R/W) Expansion 3 Secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t reserved6[960]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved7[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +/* PPC interrupt position mask */ +#define PERIPH_PPC0_INT_POS_MASK (1UL << 0) +#define PERIPH_PPC1_INT_POS_MASK (1UL << 1) +#define PERIPH_PPCEXP0_INT_POS_MASK (1UL << 4) +#define PERIPH_PPCEXP1_INT_POS_MASK (1UL << 5) +#define PERIPH_PPCEXP2_INT_POS_MASK (1UL << 6) +#define PERIPH_PPCEXP3_INT_POS_MASK (1UL << 7) +#define MAIN_PPC0_INT_POS_MASK (1UL << 16) +#define MAIN_PPCEXP0_INT_POS_MASK (1UL << 20) +#define MAIN_PPCEXP1_INT_POS_MASK (1UL << 21) +#define MAIN_PPCEXP2_INT_POS_MASK (1UL << 22) +#define MAIN_PPCEXP3_INT_POS_MASK (1UL << 23) + +/* Non-secure Access Configuration Register Block */ +struct sse300_nsacfg_block_t { + volatile uint32_t reserved0[36]; + volatile uint32_t mainnspppc0; /* 0x090 (R/W) Non-secure Unprivileged + * Access Peripheral + * Protection Control 0 on + * Main Interconnect */ + volatile uint32_t reserved1[3]; + + volatile uint32_t mainnspppcexp0; /* 0x0A0 (R/W) Expansion 0 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainnspppcexp1; /* 0x0A4 (R/W) Expansion 1 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainnspppcexp2; /* 0x0A8 (R/W) Expansion 2 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t mainnspppcexp3; /* 0x0AC (R/W) Expansion 3 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Main + * Interconnect */ + volatile uint32_t periphnspppc0; /* 0x0B0 (R/W) Non-secure Unprivileged + * Access Peripheral + * Protection Control 0 on + * Peripheral Interconnect */ + volatile uint32_t periphnspppc1; /* 0x0B4 (R/W) Non-secure Unprivileged + * Access Peripheral + * Protection Control 1 on + * Peripheral Interconnect */ + volatile uint32_t reserved2[2]; + volatile uint32_t periphnspppcexp0;/* 0x0C0 (R/W) Expansion 0 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphnspppcexp1;/* 0x0C4 (R/W) Expansion 1 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphnspppcexp2;/* 0x0C8 (R/W) Expansion 2 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t periphnspppcexp3;/* 0x0CC (R/W) Expansion 3 Non-secure + * Unprivileged Access + * Peripheral Protection + * Control on Peripheral + * Interconnect */ + volatile uint32_t reserved3[960]; + volatile uint32_t pidr4; /* 0xFD0 (R/ ) Peripheral ID 4 */ + volatile uint32_t reserved4[3]; + volatile uint32_t pidr0; /* 0xFE0 (R/ ) Peripheral ID 0 */ + volatile uint32_t pidr1; /* 0xFE4 (R/ ) Peripheral ID 1 */ + volatile uint32_t pidr2; /* 0xFE8 (R/ ) Peripheral ID 2 */ + volatile uint32_t pidr3; /* 0xFEC (R/ ) Peripheral ID 3 */ + volatile uint32_t cidr0; /* 0xFF0 (R/ ) Component ID 0 */ + volatile uint32_t cidr1; /* 0xFF4 (R/ ) Component ID 1 */ + volatile uint32_t cidr2; /* 0xFF8 (R/ ) Component ID 2 */ + volatile uint32_t cidr3; /* 0xFFC (R/ ) Component ID 3 */ +}; + +enum ppc_sse300_error_t ppc_sse300_init(struct ppc_sse300_dev_t* dev) +{ + struct sse300_sacfg_block_t* p_sacfg = + (struct sse300_sacfg_block_t*)dev->cfg->sacfg_base; + struct sse300_nsacfg_block_t* p_nsacfg = + (struct sse300_nsacfg_block_t*)dev->cfg->nsacfg_base; + + switch(dev->cfg->ppc_name) { + /* Case for MAIN0 */ + case PPC_SSE300_MAIN0: + dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppc0; + dev->data->sacfg_sp_ppc = &p_sacfg->mainspppc0; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppc0; + dev->data->int_bit_mask = MAIN_PPC0_INT_POS_MASK; + break; + + /* Case for MAIN EXPX */ + case PPC_SSE300_MAIN_EXP0: + dev->data->sacfg_ns_ppc = &p_sacfg-> mainnsppcexp0; + dev->data->sacfg_sp_ppc = &p_sacfg-> mainspppcexp0; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp0; + dev->data->int_bit_mask = MAIN_PPCEXP0_INT_POS_MASK; + break; + case PPC_SSE300_MAIN_EXP1: + dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppcexp1; + dev->data->sacfg_sp_ppc = &p_sacfg->mainspppcexp1; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp1; + dev->data->int_bit_mask = MAIN_PPCEXP1_INT_POS_MASK; + break; + case PPC_SSE300_MAIN_EXP2: + dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppcexp2; + dev->data->sacfg_sp_ppc = &p_sacfg->mainspppcexp2; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp2; + dev->data->int_bit_mask = MAIN_PPCEXP2_INT_POS_MASK; + break; + case PPC_SSE300_MAIN_EXP3: + dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppcexp3; + dev->data->sacfg_sp_ppc = &p_sacfg->mainspppcexp3; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp3; + dev->data->int_bit_mask = MAIN_PPCEXP3_INT_POS_MASK; + break; + + /* Case for PERIPHX */ + case PPC_SSE300_PERIPH0: + dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppc0; + dev->data->sacfg_sp_ppc = &p_sacfg->periphspppc0; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppc0; + dev->data->int_bit_mask = PERIPH_PPC0_INT_POS_MASK; + break; + case PPC_SSE300_PERIPH1: + dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppc1; + dev->data->sacfg_sp_ppc = &p_sacfg->periphspppc1; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppc1; + dev->data->int_bit_mask = PERIPH_PPC1_INT_POS_MASK; + break; + + /* Case for PERIPH EXPX */ + case PPC_SSE300_PERIPH_EXP0: + dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp0; + dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp0; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp0; + dev->data->int_bit_mask = PERIPH_PPCEXP0_INT_POS_MASK; + break; + case PPC_SSE300_PERIPH_EXP1: + dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp1; + dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp1; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp1; + dev->data->int_bit_mask = PERIPH_PPCEXP1_INT_POS_MASK; + break; + case PPC_SSE300_PERIPH_EXP2: + dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp2; + dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp2; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp2; + dev->data->int_bit_mask = PERIPH_PPCEXP2_INT_POS_MASK; + break; + case PPC_SSE300_PERIPH_EXP3: + dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp3; + dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp3; + dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp3; + dev->data->int_bit_mask = PERIPH_PPCEXP3_INT_POS_MASK; + break; + default: + return PPC_SSE300_ERR_INVALID_PARAM; + } + + dev->data->is_initialized = true; + + return PPC_SSE300_ERR_NONE; +} + +enum ppc_sse300_error_t +ppc_sse300_config_privilege(struct ppc_sse300_dev_t* dev, uint32_t mask, + enum ppc_sse300_sec_attr_t sec_attr, + enum ppc_sse300_priv_attr_t priv_attr) +{ + if(dev->data->is_initialized != true) { + return PPC_SSE300_ERR_NOT_INIT; + } + + if(sec_attr == PPC_SSE300_SECURE_ACCESS) { +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + /* Uses secure unprivileged access address (SACFG) to set privilege + * attribute + */ + if(priv_attr == PPC_SSE300_PRIV_ONLY_ACCESS) { + *(dev->data->sacfg_sp_ppc) &= ~mask; + } else { + *(dev->data->sacfg_sp_ppc) |= mask; + } +#else + /* Configuring security from Non-Secure application is not permitted. */ + return PPC_SSE300_ERR_NOT_PERMITTED; +#endif + } else { + /* Uses non-secure unprivileged access address (NSACFG) to set + * privilege attribute */ + if(priv_attr == PPC_SSE300_PRIV_ONLY_ACCESS) { + *(dev->data->nsacfg_nsp_ppc) &= ~mask; + } else { + *(dev->data->nsacfg_nsp_ppc) |= mask; + } + } + + return PPC_SSE300_ERR_NONE; +} + +bool ppc_sse300_is_periph_priv_only(struct ppc_sse300_dev_t* dev, + uint32_t mask) +{ + if(dev->data->is_initialized != true) { + /* Return true as the default configuration is privilege only */ + return true; + } + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + /* In secure domain either secure or non-secure privilege access is returned + * based on the configuration */ + if ((*(dev->data->sacfg_ns_ppc) & mask) == 0) { + /* Returns secure unprivileged access (SACFG) */ + return ((*(dev->data->sacfg_sp_ppc) & mask) == 0); + } else { + /* Returns non-secure unprivileged access (NSACFG) */ + return ((*(dev->data->nsacfg_nsp_ppc) & mask) == 0); + } +#else + /* Returns non-secure unprivileged access (NSACFG) */ + return ((*(dev->data->nsacfg_nsp_ppc) & mask) == 0); +#endif +} + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +enum ppc_sse300_error_t +ppc_sse300_config_security(struct ppc_sse300_dev_t* dev, uint32_t mask, + enum ppc_sse300_sec_attr_t sec_attr) +{ + if(dev->data->is_initialized != true) { + return PPC_SSE300_ERR_NOT_INIT; + } + + if(sec_attr == PPC_SSE300_SECURE_ACCESS) { + *(dev->data->sacfg_ns_ppc) &= ~mask; + } else { + *(dev->data->sacfg_ns_ppc) |= mask; + } + + return PPC_SSE300_ERR_NONE; +} + +bool ppc_sse300_is_periph_secure(struct ppc_sse300_dev_t* dev, + uint32_t mask) +{ + if(dev->data->is_initialized != true) { + /* Return true as the default configuration is secure */ + return true; + } + + return ((*(dev->data->sacfg_ns_ppc) & mask) == 0); +} + +enum ppc_sse300_error_t ppc_sse300_irq_enable(struct ppc_sse300_dev_t* dev) +{ + struct sse300_sacfg_block_t* p_sacfg = + (struct sse300_sacfg_block_t*)dev->cfg->sacfg_base; + + if(dev->data->is_initialized != true) { + return PPC_SSE300_ERR_NOT_INIT; + } + + p_sacfg->secppcinten |= dev->data->int_bit_mask; + + return PPC_SSE300_ERR_NONE; +} + +void ppc_sse300_irq_disable(struct ppc_sse300_dev_t* dev) +{ + struct sse300_sacfg_block_t* p_sacfg = + (struct sse300_sacfg_block_t*)dev->cfg->sacfg_base; + + if(dev->data->is_initialized == true) { + p_sacfg->secppcinten &= ~(dev->data->int_bit_mask); + } +} + +void ppc_sse300_clear_irq(struct ppc_sse300_dev_t* dev) +{ + struct sse300_sacfg_block_t* p_sacfg = + (struct sse300_sacfg_block_t*)dev->cfg->sacfg_base; + + if(dev->data->is_initialized == true) { + p_sacfg->secppcintclr = dev->data->int_bit_mask; + } +} + +bool ppc_sse300_irq_state(struct ppc_sse300_dev_t* dev) +{ + struct sse300_sacfg_block_t* p_sacfg = + (struct sse300_sacfg_block_t*)dev->cfg->sacfg_base; + + if(dev->data->is_initialized != true) { + return false; + } + + return ((p_sacfg->secppcintstat & dev->data->int_bit_mask) != 0); +} + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.h new file mode 100644 index 0000000..a3f7e1d --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/ppc_sse300_drv.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file ppc_sse300_drv.h + * \brief Generic driver for SSE-300 Peripheral Protection Controllers (PPC). + */ + +#ifndef __PPC_SSE_300_DRV_H__ +#define __PPC_SSE_300_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* SSE-300 PPC names */ +enum ppc_sse300_name_t { + PPC_SSE300_MAIN0 = 0, /*!< MAIN PPC 0 */ + PPC_SSE300_MAIN_EXP0, /*!< Expansion 0 MAIN PPC */ + PPC_SSE300_MAIN_EXP1, /*!< Expansion 1 MAIN PPC */ + PPC_SSE300_MAIN_EXP2, /*!< Expansion 2 MAIN PPC */ + PPC_SSE300_MAIN_EXP3, /*!< Expansion 3 MAIN PPC */ + PPC_SSE300_PERIPH0, /*!< PERIPH PPC0 */ + PPC_SSE300_PERIPH1, /*!< PERIPH PPC1 */ + PPC_SSE300_PERIPH_EXP0, /*!< Expansion 0 PERIPH PPC */ + PPC_SSE300_PERIPH_EXP1, /*!< Expansion 1 PERIPH PPC */ + PPC_SSE300_PERIPH_EXP2, /*!< Expansion 2 PERIPH PPC */ + PPC_SSE300_PERIPH_EXP3, /*!< Expansion 3 PERIPH PPC */ + SSE300_PPC_MAX_NUM +}; + +/* SSE-300 PPC device configuration structure */ +struct ppc_sse300_dev_cfg_t { + uint32_t const sacfg_base; /*!< Secure Privilege Control Block base */ + uint32_t const nsacfg_base; /*!< Non-Secure Privilege Control Block base */ + enum ppc_sse300_name_t ppc_name; +}; + +/* SSE-300 PPC device data structure */ +struct ppc_sse300_dev_data_t { + volatile uint32_t* sacfg_ns_ppc; /*!< Pointer to non-secure register */ + volatile uint32_t* sacfg_sp_ppc; /*!< Pointer to secure unprivileged + register */ + volatile uint32_t* nsacfg_nsp_ppc; /*!< Pointer to non-secure unprivileged + register */ + uint32_t int_bit_mask; /*!< Interrupt bit mask */ + bool is_initialized; /*!< Indicates if the PPC driver + is initialized */ +}; + +/* SSE-300 PPC device structure */ +struct ppc_sse300_dev_t { + const struct ppc_sse300_dev_cfg_t* const cfg; /*!< PPC configuration */ + struct ppc_sse300_dev_data_t* const data; /*!< PPC data */ +}; + +/* Security attribute used to configure the peripherals */ +enum ppc_sse300_sec_attr_t { + PPC_SSE300_SECURE_ACCESS = 0, /*! Secure access */ + PPC_SSE300_NONSECURE_ACCESS, /*! Non-secure access */ +}; + +/* Privilege attribute used to configure the peripherals */ +enum ppc_sse300_priv_attr_t { + PPC_SSE300_PRIV_AND_NONPRIV_ACCESS = 0, /*! Privilege and NonPrivilege + access */ + PPC_SSE300_PRIV_ONLY_ACCESS, /*! Privilege only access */ +}; + +/* ARM PPC error codes */ +enum ppc_sse300_error_t { + PPC_SSE300_ERR_NONE = 0, /*!< No error */ + PPC_SSE300_ERR_INVALID_PARAM, /*!< PPC invalid parameter error */ + PPC_SSE300_ERR_NOT_INIT, /*!< PPC not initialized */ + PPC_SSE300_ERR_NOT_PERMITTED /*!< PPC Operation not permitted */ +}; + +/** + * \brief Initialize the PPC device. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * + * \return Returns error code as specified in \ref ppc_sse300_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum ppc_sse300_error_t ppc_sse300_init(struct ppc_sse300_dev_t* dev); + +/** + * \brief Configures privilege attribute through the PPC device. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * \param[in] mask Peripheral mask for the PPC. + * \param[in] sec_attr Secure attribute value. + * \param[in] priv_attr Privilege attribute value. + * + * \return Returns error code as specified in \ref ppc_sse300_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum ppc_sse300_error_t +ppc_sse300_config_privilege(struct ppc_sse300_dev_t* dev, uint32_t mask, + enum ppc_sse300_sec_attr_t sec_attr, + enum ppc_sse300_priv_attr_t priv_attr); + +/** + * \brief Checks if the peripheral is configured as Privilege only or + * Privilege and non-Privilege access mode. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * \param[in] mask Peripheral mask for the PPC. + * + * \return Returns true for Privilege only configuration and false otherwise + * - with non-secure caller in the non-secure domain + * - with secure caller in the configured security domain + * If the driver is not initalized the return value of this function is + * true (Privilege only) as it is the default system configuration. + * + * \note This function doesn't check if dev is NULL. + */ +bool ppc_sse300_is_periph_priv_only(struct ppc_sse300_dev_t* dev, + uint32_t mask); + +/* Secure only functions */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) + +/** + * \brief Configures security attribute through the PPC device. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * \param[in] mask Peripheral mask for the PPC. + * \param[in] sec_attr Secure attribute value. + * + * \return Returns error code as specified in \ref ppc_sse300_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum ppc_sse300_error_t +ppc_sse300_config_security(struct ppc_sse300_dev_t* dev, uint32_t mask, + enum ppc_sse300_sec_attr_t sec_attr); + +/** + * \brief Checks if the peripheral is configured as secure or non-secure. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * \param[in] mask Peripheral mask for the PPC. + * + * \return Returns true for secure and false for non-secure. + * If the driver is not initalized the return value is true (secure) as + * it is the default system configuration. + * + * \note This function doesn't check if dev is NULL. + */ +bool ppc_sse300_is_periph_secure(struct ppc_sse300_dev_t* dev, + uint32_t mask); + +/** + * \brief Enables PPC interrupt. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * + * \return Returns error code as specified in \ref ppc_sse300_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum ppc_sse300_error_t ppc_sse300_irq_enable(struct ppc_sse300_dev_t* dev); + +/** + * \brief Disables PPC interrupt. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void ppc_sse300_irq_disable(struct ppc_sse300_dev_t* dev); + +/** + * \brief Clears PPC interrupt. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void ppc_sse300_clear_irq(struct ppc_sse300_dev_t* dev); + +/** + * \brief Returns the PPC interrupt state. + * + * \param[in] dev PPC device \ref ppc_sse300_dev_t + * + * \return Returns true if the interrupt is active and otherwise false. + * If the driver is not initalized the return value of this function is + * false (not active) as it is the default system configuration. + * + * \note This function doesn't check if dev is NULL. + */ +bool ppc_sse300_irq_state(struct ppc_sse300_dev_t* dev); + +#endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */ + +#ifdef __cplusplus +} +#endif +#endif /* __PPC_SSE_300_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.c new file mode 100644 index 0000000..5c929a7 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.c @@ -0,0 +1,1079 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cmsis.h" +#include "smsc9220_eth_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +/** Setter bit-field manipulation macro */ +#define SET_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET, VALUE) \ + (WORD |= ((VALUE & BIT_MASK) << BIT_OFFSET)) + +/** Clearing bit-field manipulation macro */ +#define CLR_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET, VALUE) \ + (WORD &= ~((VALUE & BIT_MASK) << BIT_OFFSET)) + +/** Getter bit-field manipulation macro */ +#define GET_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET) \ + ((WORD >> BIT_OFFSET) & BIT_MASK) + +/** Millisec timeout macros */ +#define RESET_TIME_OUT_MS 10U +#define REG_WRITE_TIME_OUT_MS 50U +#define PHY_RESET_TIME_OUT_MS 100U +#define INIT_FINISH_DELAY 2000U + +struct smsc9220_eth_reg_map_t { +__I uint32_t rx_data_port; /**< Receive FIFO Ports (offset 0x0) */ + uint32_t reserved1[0x7]; +__O uint32_t tx_data_port; /**< Transmit FIFO Ports (offset 0x20) */ + uint32_t reserved2[0x7]; + +__I uint32_t rx_status_port; /**< Receive FIFO status port (offset 0x40) */ +__I uint32_t rx_status_peek; /**< Receive FIFO status peek (offset 0x44) */ +__I uint32_t tx_status_port; /**< Transmit FIFO status port (offset 0x48) */ +__I uint32_t tx_status_peek; /**< Transmit FIFO status peek (offset 0x4C) */ + +__I uint32_t id_revision; /**< Chip ID and Revision (offset 0x50) */ +__IO uint32_t irq_cfg; /**< Main Interrupt Config (offset 0x54) */ +__IO uint32_t irq_status; /**< Interrupt Status (offset 0x58) */ +__IO uint32_t irq_enable; /**< Interrupt Enable Register (offset 0x5C) */ + uint32_t reserved3; /**< Reserved for future use (offset 0x60) */ +__I uint32_t byte_test; /**< Byte order test 87654321h (offset 0x64) */ +__IO uint32_t fifo_level_irq; /**< FIFO Level Interrupts (offset 0x68) */ +__IO uint32_t rx_cfg; /**< Receive Configuration (offset 0x6C) */ +__IO uint32_t tx_cfg; /**< Transmit Configuration (offset 0x70) */ +__IO uint32_t hw_cfg; /**< Hardware Configuration (offset 0x74) */ +__IO uint32_t rx_datapath_ctrl; /**< RX Datapath Control (offset 0x78) */ +__I uint32_t rx_fifo_inf; /**< Receive FIFO Information (offset 0x7C) */ +__I uint32_t tx_fifo_inf; /**< Transmit FIFO Information (offset 0x80) */ +__IO uint32_t pmt_ctrl; /**< Power Management Control (offset 0x84) */ +__IO uint32_t gpio_cfg; /**< GPIO Configuration (offset 0x88) */ +__IO uint32_t gptimer_cfg; /**< GP Timer Configuration (offset 0x8C) */ +__I uint32_t gptimer_count; /**< GP Timer Count (offset 0x90) */ + uint32_t reserved4; /**< Reserved for future use (offset 0x94) */ +__IO uint32_t word_swap; /**< WORD SWAP Register (offset 0x98) */ +__I uint32_t free_run_counter; /**< Free Run Counter (offset 0x9C) */ +__I uint32_t rx_dropped_frames;/**< RX Dropped Frames Counter (offset 0xA0) */ +__IO uint32_t mac_csr_cmd; /**< MAC CSR Synchronizer Cmd (offset 0xA4) */ +__IO uint32_t mac_csr_data; /**< MAC CSR Synchronizer Data (offset 0xA8) */ +__IO uint32_t afc_cfg; /**< AutomaticFlow Ctrl Config (offset 0xAC) */ +__IO uint32_t eeprom_cmd; /**< EEPROM Command (offset 0xB0) */ +__IO uint32_t eeprom_data; /**< EEPROM Data (offset 0xB4) */ +}; + +/** + * \brief TX FIFO Size definitions + * + */ +#define TX_STATUS_FIFO_SIZE_BYTES 512U /*< fixed allocation in bytes */ +#define TX_DATA_FIFO_SIZE_KBYTES_POS 16U +#define TX_DATA_FIFO_SIZE_KBYTES_MASK 0x0FU +#define KBYTES_TO_BYTES_MULTIPLIER 1024U + +/** + * \brief FIFO Info definitions + * + */ +#define FIFO_USED_SPACE_MASK 0xFFFFU +#define DATA_FIFO_USED_SPACE_POS 0U +#define STATUS_FIFO_USED_SPACE_POS 16U + +/** + * \brief MAC CSR Synchronizer Command bit definitions + * + */ +enum mac_csr_cmd_bits_t{ + MAC_CSR_CMD_RW_INDEX = 30U, + MAC_CSR_CMD_BUSY_INDEX = 31U, +}; + +#define MAC_CSR_CMD_ADDRESS_MASK 0x0FU + +/** + * \brief MAC Control register bit definitions + * + */ +enum mac_reg_cr_bits_t{ + MAC_REG_CR_RXEN_INDEX = 2U, + MAC_REG_CR_TXEN_INDEX = 3U +}; + +/** + * \brief MII Access register bit definitions + * + */ +enum mac_reg_mii_acc_bits_t{ + MAC_REG_MII_ACC_BUSY_INDEX = 0U, + MAC_REG_MII_ACC_WRITE_INDEX = 1U, + MAC_REG_MII_ACC_PHYADDR_INDEX = 11U +}; +#define MAC_REG_MII_ACC_MII_REG_MASK 0x1FU +#define MAC_REG_MII_ACC_MII_REG_OFFSET 6U + +/** + * \brief Hardware config register bit definitions + * + */ +enum hw_cfg_reg_bits_t{ + HW_CFG_REG_SRST_INDEX = 0U, + HW_CFG_REG_SRST_TIMEOUT_INDEX = 1U, + HW_CFG_REG_MUST_BE_ONE_INDEX = 20U, +}; +#define HW_CFG_REG_TX_FIFO_SIZE_POS 16U +#define HW_CFG_REG_TX_FIFO_SIZE_MIN 2U /*< Min Tx fifo size in KB */ +#define HW_CFG_REG_TX_FIFO_SIZE_MAX 14U /*< Max Tx fifo size in KB */ +#define HW_CFG_REG_TX_FIFO_SIZE 5U /*< Tx fifo size in KB */ + +/** + * \brief EEPROM command register bit definitions + * + */ +enum eeprom_cmd_reg_bits_t{ + EEPROM_CMD_REG_BUSY_INDEX = 31U, +}; + +/** + * \brief PHY Basic Control register bit definitions + * + */ +enum phy_reg_bctrl_reg_bits_t{ + PHY_REG_BCTRL_RST_AUTO_NEG_INDEX = 9U, + PHY_REG_BCTRL_AUTO_NEG_EN_INDEX = 12U, + PHY_REG_BCTRL_RESET_INDEX = 15U +}; + +/** + * \brief TX Command A bit definitions + * + */ +#define TX_CMD_DATA_START_OFFSET_BYTES_POS 16U +#define TX_CMD_DATA_START_OFFSET_BYTES_MASK 0x1FU + + +enum tx_command_a_bits_t{ + TX_COMMAND_A_LAST_SEGMENT_INDEX = 12U, + TX_COMMAND_A_FIRST_SEGMENT_INDEX = 13U +}; + +#define TX_CMD_PKT_LEN_BYTES_MASK 0x7FFU +#define TX_CMD_PKT_TAG_MASK 0xFFFFU +#define TX_CMD_PKT_TAG_POS 16U + + +/** + * \brief RX Fifo Status bit definitions + * + */ +enum rx_fifo_status_bits_t{ + RX_FIFO_STATUS_CRC_ERROR_INDEX = 1U, + RX_FIFO_STATUS_DRIBBLING_BIT_INDEX = 2U, + RX_FIFO_STATUS_MII_ERROR_INDEX = 3U, + RX_FIFO_STATUS_REC_WD_TIMEOUT_INDEX = 4U, + RX_FIFO_STATUS_FRAME_TYPE_INDEX = 5U, + RX_FIFO_STATUS_COLLISION_SEEN_INDEX = 6U, + RX_FIFO_STATUS_FRAME_TOO_LONG_INDEX = 7U, + RX_FIFO_STATUS_MULTICAST_INDEX = 10U, + RX_FIFO_STATUS_RUNT_FRAME_INDEX = 11U, + RX_FIFO_STATUS_LENGTH_ERROR_INDEX = 12U, + RX_FIFO_STATUS_BROADCAST_FRAME_INDEX = 13U, + RX_FIFO_STATUS_ERROR_INDEX = 15U, + RX_FIFO_STATUS_FILTERING_FAIL_INDEX = 30U, +}; +#define RX_FIFO_STATUS_PKT_LENGTH_POS 16U +#define RX_FIFO_STATUS_PKT_LENGTH_MASK 0x3FFFU + +/** + * \brief Interrupt Configuration register bit definitions + * + */ +enum irq_cfg_bits_t{ + IRQ_CFG_IRQ_EN_INDEX = 8U +}; + +#define IRQ_CFG_INT_DEAS_MASK 0xFFU +#define IRQ_CFG_INT_DEAS_POS 24U +#define IRQ_CFG_INT_DEAS_10US 0x22U + +/** + * \brief Automatic Flow Control register bit definitions + * + */ +enum afc_bits_t{ + AFC_ANY_INDEX = 0U, + AFC_ADDR_INDEX = 1U, + AFC_BROADCAST_INDEX = 2U, + AFC_MULTICAST_INDEX = 3U +}; + +#define AFC_BACK_DUR_MASK 0x0FU +#define AFC_BACK_DUR_POS 4U +#define AFC_BACK_DUR 4U /**< equal to 50us */ + +#define AFC_LOW_LEVEL_MASK 0xFFU +#define AFC_LOW_LEVEL_POS 8U +#define AFC_LOW_LEVEL 55U /**< specifies in multiple of 64 bytes */ + +#define AFC_HIGH_LEVEL_MASK 0xFFU +#define AFC_HIGH_LEVEL_POS 16U +#define AFC_HIGH_LEVEL 110U /**< specifies in multiple of 64 bytes */ + +/** + * \brief Auto-Negotiation Advertisement register bit definitions + * + */ +enum aneg_bits_t{ + ANEG_10_BASE_T_INDEX = 5U, /**< 10Mbps able */ + ANEG_10_BASE_T_FULL_DUPL_INDEX = 6U, /**< 10Mbps with full duplex */ + ANEG_100_BASE_TX_INDEX = 7U, /**< 100Mbps Tx able */ + ANEG_100_BASE_TX_FULL_DUPL_INDEX = 8U, /**< 100Mbps with full duplex */ + ANEG_SYMM_PAUSE_INDEX = 10U, /**< Symmetric Pause */ + ANEG_ASYMM_PAUSE_INDEX = 11U /**< Asymmetric Pause */ +}; + +/** + * \brief Transmit Configuration register bit definitions + * + */ +enum tx_cfg_bits_t{ + TX_CFG_STOP_INDEX = 0U, /*< stop */ + TX_CFG_ON_INDEX = 1U, /*< on */ + TX_CFG_AO_INDEX = 2U, /*< allow overrun */ + TX_CFG_TXD_DUMP_INDEX = 14U, /*< Data FIFO dump */ + TX_CFG_TXS_DUMP_INDEX = 15U /*< Status FIFO dump */ +}; + +/** + * \brief Chip ID definitions + * + */ +#define CHIP_ID 0x9220U +#define CHIP_ID_MASK 0xFFFFU +#define CHIP_ID_POS 16U + +/** + * \brief GPIO Configuration register bit definitions + * + */ +enum gpio_cfg_bits_t{ + GPIO_CFG_GPIO0_PUSHPULL_INDEX = 16U, /*< GPIO0 push/pull or open-drain */ + GPIO_CFG_GPIO1_PUSHPULL_INDEX = 17U, /*< GPIO1 push/pull or open-drain */ + GPIO_CFG_GPIO2_PUSHPULL_INDEX = 18U, /*< GPIO2 push/pull or open-drain */ + GPIO_CFG_GPIO0_LED_INDEX = 28U, /*< GPIO0 set to LED1 */ + GPIO_CFG_GPIO1_LED_INDEX = 29U, /*< GPIO1 set to LED2 */ + GPIO_CFG_GPIO2_LED_INDEX = 30U /*< GPIO2 set to LED3 */ +}; + + +static void fill_tx_fifo(const struct smsc9220_eth_dev_t* dev, + uint8_t *data, uint32_t size_bytes) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + uint32_t tx_data_port_tmp = 0; + uint8_t *tx_data_port_tmp_ptr = (uint8_t *)&tx_data_port_tmp; + + /*If the data length is not a multiple of 4, then the beginning of the first + * DWORD of the TX DATA FIFO gets filled up with zeros and a byte offset is + * set accordingly to guarantee proper transmission.*/ + uint32_t remainder_bytes = (size_bytes % 4); + uint32_t filler_bytes = (4 - remainder_bytes); + for(uint32_t i = 0; i < 4; i++){ + if(i < filler_bytes){ + tx_data_port_tmp_ptr[i] = 0; + } else { + tx_data_port_tmp_ptr[i] = data[i-filler_bytes]; + } + } + register_map->tx_data_port = tx_data_port_tmp; + size_bytes -= remainder_bytes; + data += remainder_bytes; + + while (size_bytes > 0) { + /* Keep the same endianness in data as in the temp variable */ + tx_data_port_tmp_ptr[0] = data[0]; + tx_data_port_tmp_ptr[1] = data[1]; + tx_data_port_tmp_ptr[2] = data[2]; + tx_data_port_tmp_ptr[3] = data[3]; + register_map->tx_data_port = tx_data_port_tmp; + data += 4; + size_bytes -= 4; + } +} + +static void empty_rx_fifo(const struct smsc9220_eth_dev_t* dev, + uint8_t *data, uint32_t size_bytes) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + uint32_t rx_data_port_tmp = 0; + uint8_t *rx_data_port_tmp_ptr = (uint8_t *)&rx_data_port_tmp; + + uint32_t remainder_bytes = (size_bytes % 4); + size_bytes -= remainder_bytes; + + while (size_bytes > 0) { + /* Keep the same endianness in data as in the temp variable */ + rx_data_port_tmp = register_map->rx_data_port; + data[0] = rx_data_port_tmp_ptr[0]; + data[1] = rx_data_port_tmp_ptr[1]; + data[2] = rx_data_port_tmp_ptr[2]; + data[3] = rx_data_port_tmp_ptr[3]; + data += 4; + size_bytes -= 4; + } + + rx_data_port_tmp = register_map->rx_data_port; + for(uint32_t i = 0; i < remainder_bytes; i++) { + data[i] = rx_data_port_tmp_ptr[i]; + } +} + +enum smsc9220_error_t smsc9220_mac_regread( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t *data) +{ + volatile uint32_t val; + uint32_t maccmd = GET_BIT_FIELD(regoffset, + MAC_CSR_CMD_ADDRESS_MASK, 0); + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* Make sure there's no pending operation */ + if(!(GET_BIT(register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX))) { + SET_BIT(maccmd, MAC_CSR_CMD_RW_INDEX); + SET_BIT(maccmd, MAC_CSR_CMD_BUSY_INDEX); + register_map->mac_csr_cmd = maccmd; /* Start operation */ + + do { + val = register_map->byte_test; /* A no-op read. */ + (void)val; + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + GET_BIT(register_map->mac_csr_cmd,MAC_CSR_CMD_BUSY_INDEX)); + + if(!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + else { + *data = register_map->mac_csr_data; + } + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_mac_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t data) +{ + volatile uint32_t read = 0; + uint32_t maccmd = GET_BIT_FIELD(regoffset, + MAC_CSR_CMD_ADDRESS_MASK, 0); + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* Make sure there's no pending operation */ + if(!GET_BIT(register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX)) { + register_map->mac_csr_data = data; /* Store data. */ + CLR_BIT(maccmd, MAC_CSR_CMD_RW_INDEX); + SET_BIT(maccmd, MAC_CSR_CMD_BUSY_INDEX); + register_map->mac_csr_cmd = maccmd; + + do { + read = register_map->byte_test; /* A no-op read. */ + (void)read; + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + (register_map->mac_csr_cmd & + GET_BIT(register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX))); + + if(!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_phy_regread( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t regoffset, + uint32_t *data) +{ + uint32_t val = 0; + uint32_t phycmd = 0; + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, &val)) { + return SMSC9220_ERROR_INTERNAL; + } + + if(!GET_BIT(val, MAC_REG_MII_ACC_BUSY_INDEX)) { + phycmd = 0; + SET_BIT(phycmd, MAC_REG_MII_ACC_PHYADDR_INDEX); + SET_BIT_FIELD(phycmd, MAC_REG_MII_ACC_MII_REG_MASK, + MAC_REG_MII_ACC_MII_REG_OFFSET, regoffset); + CLR_BIT(phycmd, MAC_REG_MII_ACC_WRITE_INDEX); + SET_BIT(phycmd, MAC_REG_MII_ACC_BUSY_INDEX); + + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + phycmd)) { + return SMSC9220_ERROR_INTERNAL; + } + + val = 0; + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + &val)) { + return SMSC9220_ERROR_INTERNAL; + } + } while(time_out && (GET_BIT(val, MAC_REG_MII_ACC_BUSY_INDEX))); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } else if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_DATA, + data)) { + return SMSC9220_ERROR_INTERNAL; + } + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_phy_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t regoffset, + uint32_t data) +{ + uint32_t val = 0; + uint32_t phycmd = 0; + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, &val)) { + return SMSC9220_ERROR_INTERNAL; + } + + if(!GET_BIT(val, MAC_REG_MII_ACC_BUSY_INDEX)) { + /* Load the data */ + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_MII_DATA, + (data & 0xFFFF))) { + return SMSC9220_ERROR_INTERNAL; + } + phycmd = 0; + SET_BIT(phycmd, MAC_REG_MII_ACC_PHYADDR_INDEX); + SET_BIT_FIELD(phycmd, MAC_REG_MII_ACC_MII_REG_MASK, + MAC_REG_MII_ACC_MII_REG_OFFSET, regoffset); + SET_BIT(phycmd, MAC_REG_MII_ACC_WRITE_INDEX); + SET_BIT(phycmd, MAC_REG_MII_ACC_BUSY_INDEX); + /* Start operation */ + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + phycmd)) { + return SMSC9220_ERROR_INTERNAL; + } + + phycmd = 0; + + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, + &phycmd)){ + return SMSC9220_ERROR_INTERNAL; + } + } while(time_out && GET_BIT(phycmd, 0)); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + + } else { + return SMSC9220_ERROR_BUSY; + } + return SMSC9220_ERROR_NONE; +} + +uint32_t smsc9220_read_id(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + return register_map->id_revision; +} + +enum smsc9220_error_t smsc9220_soft_reset( + const struct smsc9220_eth_dev_t* dev) +{ + uint32_t time_out = RESET_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + /* Soft reset */ + SET_BIT(register_map->hw_cfg, HW_CFG_REG_SRST_INDEX); + + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + GET_BIT(register_map->hw_cfg, HW_CFG_REG_SRST_TIMEOUT_INDEX)); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + + return SMSC9220_ERROR_NONE; +} + +void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev, + uint32_t val) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if(val >= HW_CFG_REG_TX_FIFO_SIZE_MIN && + val <= HW_CFG_REG_TX_FIFO_SIZE_MAX) { + register_map->hw_cfg = val << HW_CFG_REG_TX_FIFO_SIZE_POS; + } +} + +enum smsc9220_error_t smsc9220_set_fifo_level_irq( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_fifo_level_irq_pos_t irq_level_pos, + uint32_t level) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if (level < SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN || + level > SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX) { + return SMSC9220_ERROR_PARAM; + } + + CLR_BIT_FIELD(register_map->fifo_level_irq, SMSC9220_FIFO_LEVEL_IRQ_MASK, + irq_level_pos, SMSC9220_FIFO_LEVEL_IRQ_MASK); + SET_BIT_FIELD(register_map->fifo_level_irq, SMSC9220_FIFO_LEVEL_IRQ_MASK, + irq_level_pos, level); + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_wait_eeprom( + const struct smsc9220_eth_dev_t* dev) +{ + uint32_t time_out = REG_WRITE_TIME_OUT_MS; + + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + do { + if (dev->data->wait_ms) { + dev->data->wait_ms(1); + } + time_out--; + } while(time_out && + GET_BIT(register_map->eeprom_cmd, EEPROM_CMD_REG_BUSY_INDEX)); + + if (!time_out) { + return SMSC9220_ERROR_TIMEOUT; + } + + return SMSC9220_ERROR_NONE; +} + +void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + smsc9220_disable_all_interrupts(dev); + smsc9220_clear_all_interrupts(dev); + + /* Set IRQ deassertion interval */ + SET_BIT_FIELD(register_map->irq_cfg, IRQ_CFG_INT_DEAS_MASK, + IRQ_CFG_INT_DEAS_POS, IRQ_CFG_INT_DEAS_10US); + + /* enable interrupts */ + SET_BIT(register_map->irq_cfg, IRQ_CFG_IRQ_EN_INDEX); +} + +enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t phyid1 = 0; + uint32_t phyid2 = 0; + + if (smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_ID1,&phyid1)) { + return SMSC9220_ERROR_INTERNAL; + } + if (smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_ID2,&phyid2)) { + return SMSC9220_ERROR_INTERNAL; + } + if ((phyid1 == 0xFFFF && phyid2 == 0xFFFF) || + (phyid1 == 0x0 && phyid2 == 0x0)) { + return SMSC9220_ERROR_INTERNAL; + } + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t read = 0; + + if(smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, &read)) { + return SMSC9220_ERROR_INTERNAL; + } + + SET_BIT(read, PHY_REG_BCTRL_RESET_INDEX); + if(smsc9220_phy_regwrite(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, read)) { + return SMSC9220_ERROR_INTERNAL; + } + return SMSC9220_ERROR_NONE; +} + +void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t aneg_adv = 0; + smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_ANEG_ADV, &aneg_adv); + + SET_BIT(aneg_adv, ANEG_10_BASE_T_INDEX); + SET_BIT(aneg_adv, ANEG_10_BASE_T_FULL_DUPL_INDEX); + SET_BIT(aneg_adv, ANEG_100_BASE_TX_INDEX); + SET_BIT(aneg_adv, ANEG_100_BASE_TX_FULL_DUPL_INDEX); + SET_BIT(aneg_adv, ANEG_SYMM_PAUSE_INDEX); + SET_BIT(aneg_adv, ANEG_ASYMM_PAUSE_INDEX); + + smsc9220_phy_regwrite(dev, SMSC9220_PHY_REG_OFFSET_ANEG_ADV, aneg_adv); +} + +void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->tx_cfg, TX_CFG_ON_INDEX); +} + +void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + CLR_BIT(register_map->tx_cfg, TX_CFG_ON_INDEX); +} + +void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + SET_BIT(mac_cr, MAC_REG_CR_TXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + CLR_BIT(mac_cr, MAC_REG_CR_TXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + SET_BIT(mac_cr, MAC_REG_CR_RXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t mac_cr = 0; + smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr); + + CLR_BIT(mac_cr, MAC_REG_CR_RXEN_INDEX); + + smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr); +} + +int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t id = smsc9220_read_id(dev); + + return ((GET_BIT_FIELD(id, CHIP_ID_MASK, CHIP_ID_POS) == CHIP_ID) ? 0 : 1); +} + +void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->irq_enable, source); +} + +void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + CLR_BIT(register_map->irq_enable, source); +} + +void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + register_map->irq_enable = 0; +} + +void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + SET_BIT(register_map->irq_status, source); +} + +void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + register_map->irq_status = UINT32_MAX; +} + +int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + return GET_BIT(register_map->irq_status, source); +} + +void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev) +{ + uint32_t bcr = 0; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, &bcr); + SET_BIT(bcr, PHY_REG_BCTRL_AUTO_NEG_EN_INDEX); + SET_BIT(bcr, PHY_REG_BCTRL_RST_AUTO_NEG_INDEX); + smsc9220_phy_regwrite(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, bcr); + + SET_BIT(register_map->hw_cfg, HW_CFG_REG_MUST_BE_ONE_INDEX); +} + +enum smsc9220_error_t smsc9220_read_mac_address( + const struct smsc9220_eth_dev_t* dev, char *mac) +{ + uint32_t mac_low = 0; + uint32_t mac_high = 0; + + if(!mac) { + return SMSC9220_ERROR_PARAM; + } + + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_ADDRH, &mac_high)) { + return SMSC9220_ERROR_INTERNAL; + } + if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_ADDRL, &mac_low)) { + return SMSC9220_ERROR_INTERNAL; + } + mac[0] = mac_low & 0xFF; + mac[1] = (mac_low >> 8) & 0xFF; + mac[2] = (mac_low >> 16) & 0xFF; + mac[3] = (mac_low >> 24) & 0xFF; + mac[4] = mac_high & 0xFF; + mac[5] = (mac_high >> 8) & 0xFF; + + return SMSC9220_ERROR_NONE; +} + +uint32_t smsc9220_get_tx_data_fifo_size( + const struct smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + uint32_t tx_fifo_size = + GET_BIT_FIELD(register_map->hw_cfg, + TX_DATA_FIFO_SIZE_KBYTES_MASK, + TX_DATA_FIFO_SIZE_KBYTES_POS) * KBYTES_TO_BYTES_MULTIPLIER; + + return (tx_fifo_size - TX_STATUS_FIFO_SIZE_BYTES); +} + +enum smsc9220_error_t smsc9220_init( + const struct smsc9220_eth_dev_t* dev, + void(* wait_ms_function)(int)) +{ + uint32_t phyreset = 0; + enum smsc9220_error_t error = SMSC9220_ERROR_NONE; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if (!wait_ms_function) { + return SMSC9220_ERROR_PARAM; + } + dev->data->wait_ms = wait_ms_function; + + error = smsc9220_check_id(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + error = smsc9220_soft_reset(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + smsc9220_set_txfifo(dev, HW_CFG_REG_TX_FIFO_SIZE); + + SET_BIT_FIELD(register_map->afc_cfg, AFC_BACK_DUR_MASK, + AFC_BACK_DUR_POS, AFC_BACK_DUR); + SET_BIT_FIELD(register_map->afc_cfg, AFC_LOW_LEVEL_MASK, + AFC_LOW_LEVEL_POS, AFC_LOW_LEVEL); + SET_BIT_FIELD(register_map->afc_cfg, AFC_HIGH_LEVEL_MASK, + AFC_HIGH_LEVEL_POS, AFC_HIGH_LEVEL); + + error = smsc9220_wait_eeprom(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + /* Configure GPIOs as LED outputs. */ + register_map->gpio_cfg = 0; + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO0_PUSHPULL_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO1_PUSHPULL_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO2_PUSHPULL_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO0_LED_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO1_LED_INDEX); + SET_BIT(register_map->gpio_cfg, GPIO_CFG_GPIO2_LED_INDEX); + + smsc9220_init_irqs(dev); + + /* Configure MAC addresses here if needed. */ + + error = smsc9220_check_phy(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + error = smsc9220_reset_phy(dev); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + if (dev->data->wait_ms) { + dev->data->wait_ms(PHY_RESET_TIME_OUT_MS); + } + /* Checking whether phy reset completed successfully.*/ + error = smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BCTRL, + &phyreset); + if(error != SMSC9220_ERROR_NONE) { + return error; + } + + if(GET_BIT(phyreset, PHY_REG_BCTRL_RESET_INDEX)) { + return SMSC9220_ERROR_INTERNAL; + } + + smsc9220_advertise_cap(dev); + smsc9220_establish_link(dev); + + smsc9220_enable_mac_xmit(dev); + smsc9220_enable_xmit(dev); + smsc9220_enable_mac_recv(dev); + + /* This sleep is compulsory otherwise txmit/receive will fail. */ + if (dev->data->wait_ms) { + dev->data->wait_ms(INIT_FINISH_DELAY); + } + dev->data->state = 1; + + return SMSC9220_ERROR_NONE; +} + +enum smsc9220_error_t smsc9220_send_by_chunks( + const struct smsc9220_eth_dev_t* dev, + uint32_t total_payload_length, + bool is_new_packet, + const char *data, uint32_t current_size) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + bool is_first_segment = false; + bool is_last_segment = false; + uint32_t txcmd_a, txcmd_b = 0; + uint32_t tx_buffer_free_space = 0; + volatile uint32_t xmit_stat = 0; + + if (!data) { + return SMSC9220_ERROR_PARAM; + } + + if (is_new_packet) { + is_first_segment = true; + dev->data->ongoing_packet_length = total_payload_length; + dev->data->ongoing_packet_length_sent = 0; + } else if (dev->data->ongoing_packet_length != total_payload_length || + dev->data->ongoing_packet_length_sent >= total_payload_length) { + return SMSC9220_ERROR_PARAM; + } + + /* Would next chunk fit into buffer? */ + tx_buffer_free_space = GET_BIT_FIELD(register_map->tx_fifo_inf, + FIFO_USED_SPACE_MASK, + DATA_FIFO_USED_SPACE_POS); + if (current_size > tx_buffer_free_space) { + return SMSC9220_ERROR_INTERNAL; /* Not enough space in FIFO */ + } + if ((dev->data->ongoing_packet_length_sent + current_size) == + total_payload_length) { + is_last_segment = true; + } + + txcmd_a = 0; + txcmd_b = 0; + + if (is_last_segment) { + SET_BIT(txcmd_a, TX_COMMAND_A_LAST_SEGMENT_INDEX); + } + if (is_first_segment) { + SET_BIT(txcmd_a, TX_COMMAND_A_FIRST_SEGMENT_INDEX); + } + + uint32_t data_start_offset_bytes = (4 - (current_size % 4)); + + SET_BIT_FIELD(txcmd_a, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size); + SET_BIT_FIELD(txcmd_a, TX_CMD_DATA_START_OFFSET_BYTES_MASK, + TX_CMD_DATA_START_OFFSET_BYTES_POS, + data_start_offset_bytes); + + SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size); + SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_TAG_MASK, TX_CMD_PKT_TAG_POS, + current_size); + + register_map->tx_data_port = txcmd_a; + register_map->tx_data_port = txcmd_b; + + fill_tx_fifo(dev, (uint8_t *)data, current_size); + + if (is_last_segment) { + /* Pop status port for error check */ + xmit_stat = register_map->tx_status_port; + (void)xmit_stat; + } + dev->data->ongoing_packet_length_sent += current_size; + return SMSC9220_ERROR_NONE; +} + +uint32_t smsc9220_get_rxfifo_data_used_space(const struct + smsc9220_eth_dev_t* dev) +{ + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + return GET_BIT_FIELD(register_map->rx_fifo_inf, FIFO_USED_SPACE_MASK, + DATA_FIFO_USED_SPACE_POS); +} + +uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev, + char *data, uint32_t dlen) +{ + uint32_t rxfifo_inf = 0; + uint32_t rxfifo_stat = 0; + uint32_t packet_length_byte = 0; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if (!data) { + return 0; /* Invalid input parameter, cannot read */ + } + rxfifo_inf = register_map->rx_fifo_inf; + + if(rxfifo_inf & 0xFFFF) { /* If there's data */ + rxfifo_stat = register_map->rx_status_port; + if(rxfifo_stat != 0) { /* Fetch status of this packet */ + /* Ethernet controller is padding to 32bit aligned data */ + packet_length_byte = GET_BIT_FIELD(rxfifo_stat, + RX_FIFO_STATUS_PKT_LENGTH_MASK, + RX_FIFO_STATUS_PKT_LENGTH_POS); + packet_length_byte -= 4; + dev->data->current_rx_size_words = packet_length_byte; + } + } + + empty_rx_fifo(dev, (uint8_t *)data, packet_length_byte); + dev->data->current_rx_size_words = 0; + return packet_length_byte; +} + +uint32_t smsc9220_peek_next_packet_size(const struct + smsc9220_eth_dev_t* dev) +{ + uint32_t packet_size = 0; + struct smsc9220_eth_reg_map_t* register_map = + (struct smsc9220_eth_reg_map_t*)dev->cfg->base; + + if(smsc9220_get_rxfifo_data_used_space(dev)) { + packet_size = GET_BIT_FIELD(register_map->rx_status_peek, + RX_FIFO_STATUS_PKT_LENGTH_MASK, + RX_FIFO_STATUS_PKT_LENGTH_POS); + } + return packet_size; +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.h new file mode 100644 index 0000000..3c60f45 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/smsc9220_eth_drv.h @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2016-2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file smsc9220_drv.h + * \brief Generic driver for SMSC9220 Ethernet controller + */ + +#ifndef __SMSC9220_ETH_H__ +#define __SMSC9220_ETH_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** SMSC9220 device configuration structure */ +struct smsc9220_eth_dev_cfg_t { + const uint32_t base; /*!< SMSC9220 base address */ +}; + +/** SMSC9220 device data structure */ +struct smsc9220_eth_dev_data_t { + uint32_t state; /*!< Indicates if the SMSC9220 driver + is initialized and enabled */ + void (*wait_ms) (int);/*!< function pointer to system's millisec delay + function, will be used for delays */ + uint32_t ongoing_packet_length;/*!< size in bytes of the packet + is being sent */ + uint32_t ongoing_packet_length_sent; /*!< size in bytes of the packet + has been sent */ + uint32_t current_rx_size_words; /*!< Data length in words, + currently is being read */ +}; + +/** SMSC9220 device structure */ +struct smsc9220_eth_dev_t { + const struct smsc9220_eth_dev_cfg_t* const cfg; /*!< configuration */ + struct smsc9220_eth_dev_data_t* const data; /*!< data */ +}; + +/** + * \brief Error code definitions + * + */ +enum smsc9220_error_t{ + SMSC9220_ERROR_NONE = 0U, /*!< no error */ + SMSC9220_ERROR_TIMEOUT = 1U, /*!< timeout */ + SMSC9220_ERROR_BUSY = 2U, /*!< no error */ + SMSC9220_ERROR_PARAM = 3U, /*!< invalid parameter */ + SMSC9220_ERROR_INTERNAL = 4U /*!< internal error */ +}; + +/** + * \brief Interrupt source definitions + * + */ +enum smsc9220_interrupt_source { + SMSC9220_INTERRUPT_GPIO0 = 0U, + SMSC9220_INTERRUPT_GPIO1 = 1U, + SMSC9220_INTERRUPT_GPIO2 = 2U, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL = 3U, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_FULL = 4U, + /* 5 Reserved according to Datasheet */ + SMSC9220_INTERRUPT_RX_DROPPED_FRAME = 6U, + SMSC9220_INTERRUPT_TX_STATUS_FIFO_LEVEL = 7U, + SMSC9220_INTERRUPT_TX_STATUS_FIFO_FULL = 8U, + SMSC9220_INTERRUPT_TX_DATA_FIFO_AVAILABLE = 9U, + SMSC9220_INTERRUPT_TX_DATA_FIFO_OVERRUN = 10U, + /* 11, 12 Reserved according to Datasheet */ + SMSC9220_INTERRUPT_TX_ERROR = 13U, + SMSC9220_INTERRUPT_RX_ERROR = 14U, + SMSC9220_INTERRUPT_RX_WATCHDOG_TIMEOUT = 15U, + SMSC9220_INTERRUPT_TX_STATUS_OVERFLOW = 16U, + SMSC9220_INTERRUPT_TX_POWER_MANAGEMENT = 17U, + SMSC9220_INTERRUPT_PHY = 18U, + SMSC9220_INTERRUPT_GP_TIMER = 19U, + SMSC9220_INTERRUPT_RX_DMA = 20U, + SMSC9220_INTERRUPT_TX_IOC = 21U, + /* 22 Reserved according to Datasheet*/ + SMSC9220_INTERRUPT_RX_DROPPED_FRAME_HALF = 23U, + SMSC9220_INTERRUPT_RX_STOPPED = 24U, + SMSC9220_INTERRUPT_TX_STOPPED = 25U, + /* 26 - 30 Reserved according to Datasheet*/ + SMSC9220_INTERRUPT_SW = 31U +}; + +/** + * \brief MAC register offset definitions + * + */ +enum smsc9220_mac_reg_offsets_t{ + SMSC9220_MAC_REG_OFFSET_CR = 0x1U, + SMSC9220_MAC_REG_OFFSET_ADDRH = 0x2U, + SMSC9220_MAC_REG_OFFSET_ADDRL = 0x3U, + SMSC9220_MAC_REG_OFFSET_HASHH = 0x4U, + SMSC9220_MAC_REG_OFFSET_HASHL = 0x5U, + SMSC9220_MAC_REG_OFFSET_MII_ACC = 0x6U, + SMSC9220_MAC_REG_OFFSET_MII_DATA = 0x7U, + SMSC9220_MAC_REG_OFFSET_FLOW = 0x8U, + SMSC9220_MAC_REG_OFFSET_VLAN1 = 0x9U, + SMSC9220_MAC_REG_OFFSET_VLAN2 = 0xAU, + SMSC9220_MAC_REG_OFFSET_WUFF = 0xBU, + SMSC9220_MAC_REG_OFFSET_WUCSR = 0xCU, + SMSC9220_MAC_REG_OFFSET_COE_CR = 0xDU +}; + +/** + * \brief PHY register offset definitions + * + */ +enum phy_reg_offsets_t{ + SMSC9220_PHY_REG_OFFSET_BCTRL = 0U, + SMSC9220_PHY_REG_OFFSET_BSTATUS = 1U, + SMSC9220_PHY_REG_OFFSET_ID1 = 2U, + SMSC9220_PHY_REG_OFFSET_ID2 = 3U, + SMSC9220_PHY_REG_OFFSET_ANEG_ADV = 4U, + SMSC9220_PHY_REG_OFFSET_ANEG_LPA = 5U, + SMSC9220_PHY_REG_OFFSET_ANEG_EXP = 6U, + SMSC9220_PHY_REG_OFFSET_MCONTROL = 17U, + SMSC9220_PHY_REG_OFFSET_MSTATUS = 18U, + SMSC9220_PHY_REG_OFFSET_CSINDICATE = 27U, + SMSC9220_PHY_REG_OFFSET_INTSRC = 29U, + SMSC9220_PHY_REG_OFFSET_INTMASK = 30U, + SMSC9220_PHY_REG_OFFSET_CS = 31U +}; + +/* Bit definitions for PHY Basic Status Register */ +#define PHY_REG_BSTATUS_EXTENDED_CAPABILITIES_INDEX 0U +#define PHY_REG_BSTATUS_JABBER_DETECT_INDEX 1U +#define PHY_REG_BSTATUS_LINK_STATUS_INDEX 2U +#define PHY_REG_BSTATUS_AUTO_NEG_ABILITY_INDEX 3U +#define PHY_REG_BSTATUS_REMOTE_FAULT_INDEX 4U +#define PHY_REG_BSTATUS_AUTO_NEG_COMPLETE_INDEX 5U +#define PHY_REG_BSTATUS_10BASE_T_HALF_DUPLEX_INDEX 11U +#define PHY_REG_BSTATUS_10BASE_T_FULL_DUPLEX_INDEX 12U +#define PHY_REG_BSTATUS_100BASE_TX_HALF_DUPLEX_INDEX 13U +#define PHY_REG_BSTATUS_100BASE_TX_FULL_DUPLEX_INDEX 14U +#define PHY_REG_BSTATUS_100BASE_T4_INDEX 15U + +/** + * \brief FIFO Level Interrupt bit definitions + * + */ +enum smsc9220_fifo_level_irq_pos_t{ + SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS = 0U, + SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS = 16U, + SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS = 24U +}; + +/** + * \brief FIFO Level Interrupt limits + * + */ +#define SMSC9220_FIFO_LEVEL_IRQ_MASK 0xFFU +#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN 0U +#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX SMSC9220_FIFO_LEVEL_IRQ_MASK + +/** + * \brief Initializes SMSC9220 Ethernet controller to a known default state: + * - device ID is checked + * - global interrupt is enabled, but all irq sources are disabled + * - all capabilities are advertised + * - 10Mbps able + * - 10Mbps with full duplex + * - 100Mbps Tx able + * - 100Mbps with full duplex + * - Symmetric Pause + * - Asymmetric Pause + * - Establish link enabled + * - Rx enabled + * - Tx enabled + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] wait_ms_function function pointer to a millisec delay function + * for proper timing of some processes + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_init(const struct smsc9220_eth_dev_t* dev, + void(* wait_ms_function)(int)); + +/** + * \brief Reads the MAC register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[in, out] data Pointer to register will be read + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_mac_regread( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t *data); + +/** + * \brief Writes the MAC register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[in] data Register value to write + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_mac_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_mac_reg_offsets_t regoffset, + uint32_t data); + +/** + * \brief Reads the PHY register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[out] data Register value is read + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_phy_regread( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t, + uint32_t *data); + +/** + * \brief Writes the PHY register. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] regoffset Register offset + * \param[in] data Register value to write + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_phy_regwrite( + const struct smsc9220_eth_dev_t* dev, + enum phy_reg_offsets_t, + uint32_t data); + +/** + * \brief Reads the Ethernet Controller's ID. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return ID number + */ +uint32_t smsc9220_read_id(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Initiates a soft reset, returns failure or success. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_soft_reset( + const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Sets the Maximum Transmission Unit by Tx fifo size. + * Note: The MTU will be smaller by 512 bytes, + * whis is used by the status. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] val Size of the fifo in kbytes + * \ref HW_CFG_REG_TX_FIFO_SIZE_MIN + * \ref HW_CFG_REG_TX_FIFO_SIZE_MAX + */ +void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev, + uint32_t val); + +/** + * \brief Sets the FIFO level interrupt for a given source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] irq_level_pos Bit position of the FIFO to set + * \ref smsc9220_fifo_level_irq_pos_t + * \param[in] level Level of the FIFO, when the FIFO used space is greater + * than this value, corresponding interrupt will be generated. + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_set_fifo_level_irq( + const struct smsc9220_eth_dev_t* dev, + enum smsc9220_fifo_level_irq_pos_t irq_level_pos, + uint32_t level); + +/** + * \brief Waits for EEPROM to be ready to use. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_wait_eeprom( + const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Initializes irqs by clearing and disabling all interrupt sources + * and enable interrupts. Since all interrupt sources are disabled, + * interrupt won't be triggered, until interrupt sources won't be + * enabled by \ref smsc9220_enable_interrupt + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Checks PHY ID registers. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Resets PHY. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Advertises all speeds and pauses capabilities. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enables transmission. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Disables transmission. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enables MAC Transmitter. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Disables MAC Transmitter. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enables receiving. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Disables receiving. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Enables the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + */ +void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Disables the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + */ +void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Disables all interrupt sources. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Clears the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + */ +void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Clears all interrupt sources. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Gets the status of the given interrupt source. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] source Enum of the interrupt source. + * + * \return non-zero if the given interrupt source is triggered, zero otherwise + */ +int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev, + enum smsc9220_interrupt_source source); + +/** + * \brief Establishes link + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + */ +void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Reads the Ethernet Controller's MAC address from its EEPROM. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in,out] mac array will include the read MAC address in + * 6 bytes hexadecimal format. + * It should be allocated by the caller to 6 bytes. + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_read_mac_address( + const struct smsc9220_eth_dev_t* dev, char *mac); + +/** + * \brief Check device ID. + * + * \return error code /ref smsc9220_error_t + */ +int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev); + +/** + * \brief Gets the data size of the Tx buffer, aka Maximum Trasmission Unit + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return Fifo data size in bytes + */ +uint32_t smsc9220_get_tx_data_fifo_size(const struct + smsc9220_eth_dev_t* dev); + +/** + * \brief Sends data from the given buffer as an Ethernet packet. + * The full packet length must be specified at the beginning + * of a new packet transmission. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in] total_payload_length Length of the ethernet payload. + * Should be equal to the sum of passed buffers within a packet. + * \param[in] is_new_packet Should be set to true if the input buffer has to + * be sent as the start of a new packet or as a full packet. + * \param[in] data Pointer to the data buffer to be sent. + * \param[in] current_size Size of the data in bytes. + * + * \return error code /ref smsc9220_error_t + */ +enum smsc9220_error_t smsc9220_send_by_chunks( + const struct smsc9220_eth_dev_t* dev, + uint32_t total_payload_length, + bool is_new_packet, + const char *data, uint32_t current_size); + +/** + * \brief Reads an incoming Ethernet packet into the given buffer. + * Stops reading at packet border. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * \param[in,out] data Pointer to a pre-allocated input buffer. + * Allocating sufficient memory space is the caller's + * responsibility, which is typically done by calling + * \ref smsc9220_peek_next_packet_size. + * \param[in] dlen Length of the allocated data in bytes. + * + * \return Number of bytes read from the Rx FIFO into the given buffer. + */ +uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev, + char *data, uint32_t dlen); + +/** + * \brief Get the used space of Rx fifo in bytes. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return Data received and waiting for read in bytes + */ +uint32_t smsc9220_get_rxfifo_data_used_space(const struct + smsc9220_eth_dev_t* dev); + +/** + * \brief Gets the size of next unread packet in Rx buffer, using the peak + * register, which is not destructive so can be read asynchronously. + * Warning: In case of heavy receiving loads, this register may not + * be in perfect sync. + * + * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t + * + * \return Size of the next packet in bytes, read from the Rx Peek register. + */ +uint32_t smsc9220_peek_next_packet_size(const struct + smsc9220_eth_dev_t* dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __SMSC9220_ETH_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.c new file mode 100644 index 0000000..832bb02 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.c @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file syscounter_armv8-m_cntrl_drv.c + * + * \brief Driver for Armv8-M System Counter Control, covering CNTControlBase + * Frame + * + * This System Counter is a 64-bit up-counter, generating the physical + * count for System Timer. + * + * Main features: + * - Enabled/disable and Set/Get the 64-bit upcounter + * - 2 scaling register for the 2 clock sources + * - These registers are used to pre-program the scaling values so + * that when hardware based clock switching is implemented there is no + * need to program the scaling increment value each time when clock is + * switched. + * - When counter scaling is enabled, ScaleVal is the amount added to the + * Counter Count Value for every period of the counter as determined + * by 1/Frequency from the current operating frequency of the system + * counter (the “counter tick”). + * - ScaleVal is expressed as an unsigned fixed-point number with + * a 8 bit integer value and a 24-bit fractional value + * - Interrupt for error detection + * There are 2 possible reasons for error notification generation from + * the Counter: + * 1. Security attribute mismatch between register access and security + * attribute of the CONTROL frame + * 2. Address decode error within a given frame + * + */ + +#include "syscounter_armv8-m_cntrl_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) +/** Clear-and-Set bit manipulation macro */ +#define ASSIGN_BIT(WORD, BIT_INDEX, VALUE) \ + (WORD = ((WORD & ~(1U << (BIT_INDEX))) | (VALUE << (BIT_INDEX)))) +/** Getter bit-field manipulation macro */ +#define GET_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET) \ + ((WORD & BIT_MASK) >> BIT_OFFSET) +/** Bit mask for given width bit-field manipulation macro */ +#define BITMASK(width) ((1u<<(width))-1) + +/** + * \brief CNTControlBase Register map structure + */ +struct cnt_control_base_reg_map_t { + volatile uint32_t cntcr; + /*!< Offset: 0x000 (R/W) Counter Control Register */ + volatile const uint32_t cntsr; + /*!< Offset: 0x004 (RO) Counter Status Register */ + volatile uint32_t cntcv_low; + /*!< Offset: 0x008 (R/W) Counter Count Value [31:0] Register */ + volatile uint32_t cntcv_high; + /*!< Offset: 0x00C (R/W) Counter Count Value [63:32] Register */ + volatile uint32_t cntscr; + /*!< Offset: 0x010 (R/W) Counter Scale Register + * Aliased with CNTSCR0, meaning that either addresses of CNTSCR and + * CNTSCR0 will physically access a single register + */ + volatile const uint32_t reserved0[2]; + /*!< Offset: 0x014-0x018 Reserved (RAZWI) */ + volatile const uint32_t cntid; + /*!< Offset: 0x01C (RO) Counter ID Register */ + volatile const uint32_t reserved1[40]; + /*!< Offset: 0x020-0x0BC Reserved (RAZWI) */ + volatile const uint32_t reserved2[4]; + /*!< Offset: 0x0C0-0x0CC Reserved (RAZWI) */ + volatile uint32_t cntscr0; + /*!< Offset: 0x0D0 (R/W) Counter Scale Register 0 */ + volatile uint32_t cntscr1; + /*!< Offset: 0x0D4 (R/W) Counter Scale Register 1 */ + volatile const uint32_t reserved3[958]; + /*!< Offset: 0x0D8-0xFCC Reserved (RAZWI) */ + volatile const uint32_t cntpidr4; + /*!< Offset: 0xFD0 (RO) Peripheral ID Register */ + volatile const uint32_t reserved4[3]; + /*!< Offset: 0xFD4-0xFDC Reserved (RAZWI) */ + volatile const uint32_t cntpidr0; + /*!< Offset: 0xFE0 (RO) Peripheral ID Register */ + volatile const uint32_t cntpidr1; + /*!< Offset: 0xFE4 (RO) Peripheral ID Register */ + volatile const uint32_t cntpidr2; + /*!< Offset: 0xFE8 (RO) Peripheral ID Register */ + volatile const uint32_t cntpidr3; + /*!< Offset: 0xFEC (RO) Peripheral ID Register */ + volatile const uint32_t cntcidr0; + /*!< Offset: 0xFF0 (RO) Component ID Register */ + volatile const uint32_t cntcidr1; + /*!< Offset: 0xFF4 (RO) Component ID Register */ + volatile const uint32_t cntcidr2; + /*!< Offset: 0xFF8 (RO) Component ID Register */ + volatile const uint32_t cntcidr3; + /*!< Offset: 0xFFC (RO) Component ID Register */ +}; + +/** + * \brief Counter Control Register bit fields + */ +#define SYSCOUNTER_ARMV8M_CNTCR_EN_OFF 0u + /*!< Counter Control Register Enable Counter bit field offset */ +#define SYSCOUNTER_ARMV8M_CNTCR_HDBG_OFF 1u + /*!< Counter Control Register Halt On Debug bit field offset */ +#define SYSCOUNTER_ARMV8M_CNTCR_SCEN_OFF 2u + /*!< Counter Control Register Scale enable bit field offset */ +#define SYSCOUNTER_ARMV8M_CNTCR_INTRMASK_OFF 3u + /*!< Counter Control Register Interrupt mask bit field offset */ +#define SYSCOUNTER_ARMV8M_CNTCR_PSLVERRDIS_OFF 4u + /*!< Counter Control Register PSLVERR disable bit field offset */ +#define SYSCOUNTER_ARMV8M_CNTCR_INTRCLR_OFF 5u + /*!< Counter Control Register Interrupt Clear bit field offset */ + +/** + * \brief Counter Status Register bit fields + */ +#define SYSCOUNTER_ARMV8M_CNTSR_DBGH_OFF 1u + /*!< Counter Status Register Halt-on-Debug bit field offset */ + +/** + * \brief Counter ID Register bit fields + */ +#define SYSCOUNTER_ARMV8M_CNTID_CNTSC_OFF 0u + /*!< Counter ID Register Counter Scaling is implemented bit field offset */ +#define SYSCOUNTER_ARMV8M_CNTID_CNTCS_OFF 16u + /*!< Counter ID Register Clock switching is implemented bit field offset */ + +/*! Counter ID Register Clock source */ +#define SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_OFF 17u +#define SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_WIDTH 2u +#define SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_MASK \ + (BITMASK(SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_WIDTH) \ + << SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_OFF) + +#define SYSCOUNTER_ARMV8M_CNTID_CNTSCR_OVR_OFF 19u + /*!< Counter ID Register Override counter enable condition for + * writing to CNTSCR registers bit offset + */ + +enum syscounter_armv8_m_cntrl_error_t syscounter_armv8_m_cntrl_init( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + enum syscounter_armv8_m_cntrl_error_t result = SYSCOUNTER_ARMV8_M_ERR_NONE; + + if (dev->data->is_initialized == false) { + syscounter_armv8_m_cntrl_disable_counter(dev); + if (syscounter_armv8_m_cntrl_is_counter_scaling_implemented(dev)) { + result = syscounter_armv8_m_cntrl_set_counter_scale_value( + dev, SYSCOUNTER_ARMV8_M_SCALE_NR_0, dev->cfg->scale0); + if (result != SYSCOUNTER_ARMV8_M_ERR_NONE) { + return result; + } + result = syscounter_armv8_m_cntrl_set_counter_scale_value( + dev, SYSCOUNTER_ARMV8_M_SCALE_NR_1, dev->cfg->scale1); + if (result != SYSCOUNTER_ARMV8_M_ERR_NONE) { + return result; + } + } + syscounter_armv8_m_cntrl_set_counter_value(dev, + SYSCOUNTER_ARMV8_M_DEFAULT_INIT_CNT_VAL); + syscounter_armv8_m_cntrl_disable_interrupt(dev); + syscounter_armv8_m_cntrl_disable_scale(dev); + + syscounter_armv8_m_cntrl_enable_counter(dev); + dev->data->is_initialized = true; + } + return SYSCOUNTER_ARMV8_M_ERR_NONE; +} + +void syscounter_armv8_m_cntrl_uninit( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + if (dev->data->is_initialized == true) { + syscounter_armv8_m_cntrl_disable_counter(dev); + syscounter_armv8_m_cntrl_disable_interrupt(dev); + syscounter_armv8_m_cntrl_set_counter_value(dev, + SYSCOUNTER_ARMV8_M_DEFAULT_INIT_CNT_VAL); + dev->data->is_initialized = false; + } +} + +void syscounter_armv8_m_cntrl_enable_counter( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_EN_OFF); +} + +void syscounter_armv8_m_cntrl_disable_counter( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_EN_OFF); +} + +bool syscounter_armv8_m_cntrl_is_counter_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntcr, + SYSCOUNTER_ARMV8M_CNTCR_EN_OFF); +} + +void syscounter_armv8_m_cntrl_enable_halt_on_debug( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_HDBG_OFF); +} + +void syscounter_armv8_m_cntrl_disable_halt_on_debug( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_HDBG_OFF); +} + +bool syscounter_armv8_m_cntrl_is_halt_on_debug_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntcr, + SYSCOUNTER_ARMV8M_CNTCR_HDBG_OFF); +} + +void syscounter_armv8_m_cntrl_enable_scale( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_SCEN_OFF); +} + +void syscounter_armv8_m_cntrl_disable_scale( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_SCEN_OFF); +} + +bool syscounter_armv8_m_cntrl_is_scale_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntcr, + SYSCOUNTER_ARMV8M_CNTCR_SCEN_OFF); +} + +void syscounter_armv8_m_cntrl_enable_interrupt( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_INTRMASK_OFF); +} + +void syscounter_armv8_m_cntrl_disable_interrupt( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_INTRMASK_OFF); +} + +bool syscounter_armv8_m_cntrl_is_interrupt_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntcr, + SYSCOUNTER_ARMV8M_CNTCR_INTRMASK_OFF); +} + +void syscounter_armv8_m_cntrl_enable_pslverr( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_PSLVERRDIS_OFF); +} + +void syscounter_armv8_m_cntrl_disable_pslverr( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_PSLVERRDIS_OFF); +} + +bool syscounter_armv8_m_cntrl_is_pslverr_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntcr, + SYSCOUNTER_ARMV8M_CNTCR_PSLVERRDIS_OFF); +} + +void syscounter_armv8_m_cntrl_clear_interrupt( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntcr, SYSCOUNTER_ARMV8M_CNTCR_INTRCLR_OFF); +} + +bool syscounter_armv8_m_cntrl_is_counter_halted_on_debug( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntsr, + SYSCOUNTER_ARMV8M_CNTSR_DBGH_OFF); +} + +uint64_t syscounter_armv8_m_cntrl_get_counter_value( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + uint32_t high = 0; + uint32_t low = 0; + uint32_t high_prev = 0; + uint64_t value = 0; + + /* Make sure the 64-bit read will be atomic to avoid overflow between + * the low and high registers read + */ + high = p_cnt->cntcv_high; + do { + high_prev = high; + low = p_cnt->cntcv_low; + high = p_cnt->cntcv_high; + }while(high != high_prev); + + value = low | + (((uint64_t)high) << SYSCOUNTER_ARMV8_M_CNTRL_REGISTER_BIT_WIDTH); + return value; +} + +void syscounter_armv8_m_cntrl_set_counter_value( + struct syscounter_armv8_m_cntrl_dev_t* dev, + uint64_t value) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + p_cnt->cntcv_low = value & UINT32_MAX; + p_cnt->cntcv_high = value >> SYSCOUNTER_ARMV8_M_CNTRL_REGISTER_BIT_WIDTH; +} + +bool syscounter_armv8_m_cntrl_is_counter_scaling_implemented( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntid, + SYSCOUNTER_ARMV8M_CNTID_CNTSC_OFF); +} + +bool syscounter_armv8_m_cntrl_is_clock_switching_implemented( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntid, + SYSCOUNTER_ARMV8M_CNTID_CNTCS_OFF); +} + +enum syscounter_armv8_m_cntrl_selclk_t +syscounter_armv8_m_cntrl_get_clock_source( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return (enum syscounter_armv8_m_cntrl_selclk_t) + GET_BIT_FIELD(p_cnt->cntid, + SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_MASK, + SYSCOUNTER_ARMV8M_CNTID_CNTSELCLK_OFF); +} + +enum syscounter_armv8_m_cntrl_cntscr_ovr_t +syscounter_armv8_m_cntrl_get_override_cntscr( + struct syscounter_armv8_m_cntrl_dev_t* dev) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + return (enum syscounter_armv8_m_cntrl_cntscr_ovr_t) + GET_BIT(p_cnt->cntid, + SYSCOUNTER_ARMV8M_CNTID_CNTSCR_OVR_OFF); +} + +enum syscounter_armv8_m_cntrl_error_t +syscounter_armv8_m_cntrl_get_counter_scale_value( + struct syscounter_armv8_m_cntrl_dev_t* dev, + enum syscounter_armv8_m_cntrl_scale_nr_t nr, + struct syscounter_armv8_m_cntrl_scale_val_t *val) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + + switch (nr) { + case SYSCOUNTER_ARMV8_M_SCALE_NR_0: + val->integer = p_cnt->cntscr0 >> SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_OFF; + val->fixed_point_fraction = p_cnt->cntscr0 & + SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX; + break; + case SYSCOUNTER_ARMV8_M_SCALE_NR_1: + val->integer = p_cnt->cntscr1 >> SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_OFF; + val->fixed_point_fraction = p_cnt->cntscr1 & + SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX; + break; + default: + val->integer = 0; + val->fixed_point_fraction = 0; + return SYSCOUNTER_ARMV8_M_ERR_INVALID_ARG; + } + + return SYSCOUNTER_ARMV8_M_ERR_NONE; +} + +enum syscounter_armv8_m_cntrl_error_t +syscounter_armv8_m_cntrl_set_counter_scale_value( + struct syscounter_armv8_m_cntrl_dev_t* dev, + enum syscounter_armv8_m_cntrl_scale_nr_t nr, + struct syscounter_armv8_m_cntrl_scale_val_t val) +{ + struct cnt_control_base_reg_map_t* p_cnt = + (struct cnt_control_base_reg_map_t*)dev->cfg->base; + uint32_t reg_val = 0; + + if ((syscounter_armv8_m_cntrl_get_override_cntscr(dev) == + SYSCOUNTER_ARMV8_M_CNTSCR_IF_DISABLED) && + syscounter_armv8_m_cntrl_is_counter_enabled(dev)) { + return SYSCOUNTER_ARMV8_M_ERR_INVALID; + } + if (val.integer > SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_MAX || + val.fixed_point_fraction > SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX) { + return SYSCOUNTER_ARMV8_M_ERR_INVALID_ARG; + } + + reg_val = val.integer << SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_OFF; + reg_val |= (val.fixed_point_fraction & + SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX); + + switch (nr) { + case SYSCOUNTER_ARMV8_M_SCALE_NR_0: + p_cnt->cntscr0 = reg_val; + break; + case SYSCOUNTER_ARMV8_M_SCALE_NR_1: + p_cnt->cntscr1 = reg_val; + break; + default: + return SYSCOUNTER_ARMV8_M_ERR_INVALID_ARG; + } + + return SYSCOUNTER_ARMV8_M_ERR_NONE; +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.h new file mode 100644 index 0000000..e84786d --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/syscounter_armv8-m_cntrl_drv.h @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file syscounter_armv8-m_cntrl_drv.h + * + * \brief Driver for Armv8-M System Counter Control, covering CNTControlBase + * Frame + * + * This System Counter is a 64-bit up-counter, generating the physical + * count for System Timer. + * + * Main features: + * - Enable/disable and Set/Get the 64-bit upcounter + * - 2 scaling registers for the 2 clock sources + * - These registers are used to pre-program the scaling values so + * that when hardware based clock switching is implemented there is no + * need to program the scaling increment value each time when clock is + * switched. + * - When counter scaling is enabled, ScaleVal is the value added to the + * Counter Count Value for every period of the counter as determined + * by 1/Frequency from the current operating frequency of the system + * counter (the “counter tick”). + * - ScaleVal is expressed as an unsigned fixed-point number with + * a 8 bit integer value and a 24-bit fractional value + * - Interrupt for error detection + * There are 2 possible reasons for error notification generation from + * the Counter: + * 1. Security attribute mismatch between register access and security + * attribute of the CONTROL frame + * 2. Address decode error within a given frame + * + */ + +#ifndef __SYSCOUNTER_ARMV8_M_CNTRL_DRV_H__ +#define __SYSCOUNTER_ARMV8_M_CNTRL_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SYSCOUNTER_ARMV8_M_CNTRL_REGISTER_BIT_WIDTH 32u + /*!< Armv8-M System Counter Control registers bit width */ + +#define SYSCOUNTER_ARMV8_M_DEFAULT_INIT_CNT_VAL 0u + /*!< Armv8-M System Counter Control default counter init value */ + +/** + * \brief Armv8-M System Counter Control scaling value + */ +struct syscounter_armv8_m_cntrl_scale_val_t { + uint32_t integer; /* 8 bit */ + uint32_t fixed_point_fraction; /* 24 bit */ +}; + +/** + * \brief Armv8-M System Counter Control scaling value macros * + * 8 bit integer and 24 bit fixed point fractional value + */ +#define SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_MAX UINT8_MAX +#define SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_OFF 24u +#define SYSCOUNTER_ARMV8_M_SCALE_VAL_FRACT_MAX \ + ((1u << SYSCOUNTER_ARMV8_M_SCALE_VAL_INT_OFF) - 1u) + +/** + * \brief Armv8-M System Counter Control device configuration structure + */ +struct syscounter_armv8_m_cntrl_dev_cfg_t { + const uint32_t base; + /*!< Armv8-M System Counter Control device base address */ + struct syscounter_armv8_m_cntrl_scale_val_t scale0; + /*!< Default clock scaling value for Clock source 0 */ + struct syscounter_armv8_m_cntrl_scale_val_t scale1; + /*!< Default clock scaling value for Clock source 1 */ +}; + +/** + * \brief Armv8-M System Counter Control device data structure + */ +struct syscounter_armv8_m_cntrl_dev_data_t { + bool is_initialized; +}; + +/** + * \brief Armv8-M System Counter Control device structure + */ +struct syscounter_armv8_m_cntrl_dev_t { + const struct syscounter_armv8_m_cntrl_dev_cfg_t* const cfg; + /*!< Armv8-M System Counter Control configuration structure */ + struct syscounter_armv8_m_cntrl_dev_data_t* const data; + /*!< Armv8-M System Counter Control data structure */ +}; + +/** + * \brief Armv8-M System Counter Control error enumeration types + */ +enum syscounter_armv8_m_cntrl_error_t { + SYSCOUNTER_ARMV8_M_ERR_NONE = 0u, + SYSCOUNTER_ARMV8_M_ERR_INVALID = 1u, + SYSCOUNTER_ARMV8_M_ERR_INVALID_ARG = 2u +}; + +/** + * \brief Armv8-M System Counter Control scaling number for each clock sources + */ +enum syscounter_armv8_m_cntrl_scale_nr_t { + SYSCOUNTER_ARMV8_M_SCALE_NR_0 = 0u, + /*!< Scaling for \ref SYSCOUNTER_ARMV8_M_SELCLK_CLK0 */ + SYSCOUNTER_ARMV8_M_SCALE_NR_1 = 1u + /*!< Scaling for \ref SYSCOUNTER_ARMV8_M_SELCLK_CLK1 */ +}; + +/** + * \brief Clock select values + */ +enum syscounter_armv8_m_cntrl_selclk_t { + SYSCOUNTER_ARMV8_M_SELCLK_CLK_INVALID0 = 0u, + /*!< Clock select invalid value */ + SYSCOUNTER_ARMV8_M_SELCLK_CLK0 = 1u, + /*!< Clock select clock source 0 */ + SYSCOUNTER_ARMV8_M_SELCLK_CLK1 = 2u, + /*!< Clock select clock source 1 */ + SYSCOUNTER_ARMV8_M_SELCLK_CLK_INVALID1 = 3u + /*!< Clock select invalid value */ +}; + +/** + * \brief Override counter enable condition for writing to CNTSCR registers + * + */ +enum syscounter_armv8_m_cntrl_cntscr_ovr_t { + SYSCOUNTER_ARMV8_M_CNTSCR_IF_DISABLED = 0u, + /*!< Scaling registers can be written only when counter is disabled */ + SYSCOUNTER_ARMV8_M_CNTSCR_ALWAYS = 1u + /*!< CNTSCR can be written regardless of counter enabled or disabled */ +}; + +/** + * \brief Initializes counter to a known default state, which is: + * - counter is enabled, so starts counting + * - interrupt is disabled + * - counter reset to default reset value + * \ref SYSCOUNTER_ARMV8_M_DEFAULT_INIT_CNT_VAL + * - scaling is disabled + * - scaling registers are set to the set values: + * \ref struct syscounter_armv8_m_cntrl_dev_cfg_t + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * More than one call results fall through. + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return Error status \ref enum syscounter_armv8_m_cntrl_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum syscounter_armv8_m_cntrl_error_t syscounter_armv8_m_cntrl_init( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Uninitializes counter to a known default state, which is: + * - counter is disabled, so stops counting + * - interrupt is disabled + * - counter reset to default reset value + * \ref SYSCOUNTER_ARMV8_M_DEFAULT_INIT_CNT_VAL + * - scaling is disabled + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_uninit( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Enables the counter, so counter starts counting + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_enable_counter( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Disables the counter, so counter stops counting + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_disable_counter( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls counter enable status + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_counter_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Enables Halt-On-Debug feature + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_enable_halt_on_debug( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Disables Halt-On-Debug feature + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_disable_halt_on_debug( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls Halt-On-Debug enablement status + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_halt_on_debug_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Enables scaling + * The used scaling register is depending on the used HW clock source. + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_enable_scale( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Disables scaling + * Counter count will be incremented by default 1 for each ticks. + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_disable_scale( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls scaling enablement status + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_scale_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Enables interrupt + * + * There are 2 possible reasons for error notification generation from + * the Counter: + * 1. Security attribute mismatch between register access and security + * attribute of the CONTROL frame + * 2. Address decode error within a given frame + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_enable_interrupt( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Disables interrupt + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_disable_interrupt( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls interrupt enablement status + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_interrupt_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Enables PSLVERR output + * + * PSLVERR output signal on APB bus dynamically generated for the + * following error: + * For security attribute mismatch between register access and security + * attribute of the CONTROL frame + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_enable_pslverr( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Disables PSLVERR output + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_disable_pslverr( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls PSLVERR output enablement status + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_pslverr_enabled( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Clears interrupt pending flag + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_clear_interrupt( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls Halt-On-Debug status + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if counter is halted, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_counter_halted_on_debug( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Read counter value + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return 64 bit counter value + * + * \note This function doesn't check if dev is NULL. + */ +uint64_t syscounter_armv8_m_cntrl_get_counter_value( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Writes counter value + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * \param[in] value 64 bit counter value + * + * \note This function doesn't check if dev is NULL. + */ +void syscounter_armv8_m_cntrl_set_counter_value( + struct syscounter_armv8_m_cntrl_dev_t* dev, + uint64_t value); + +/** + * \brief Polls whether scaling is implemented + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if implemented, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_counter_scaling_implemented( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Polls whether HW based clock switching is implemented + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return true if implemented, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool syscounter_armv8_m_cntrl_is_clock_switching_implemented( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Reads which clock source is being used + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return Clock source \ref enum syscounter_armv8_m_cntrl_selclk_t + * + * \note This function doesn't check if dev is NULL. + */ +enum syscounter_armv8_m_cntrl_selclk_t + syscounter_armv8_m_cntrl_get_clock_source( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Reads scaling register can be overriden anytime + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * + * \return Override condition \ref enum syscounter_armv8_m_cntrl_cntscr_ovr_t + * + * \note This function doesn't check if dev is NULL. + */ +enum syscounter_armv8_m_cntrl_cntscr_ovr_t + syscounter_armv8_m_cntrl_get_override_cntscr( + struct syscounter_armv8_m_cntrl_dev_t* dev); + +/** + * \brief Reads scaling register + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * \param[in] nr Index of scaling register to read + * \ref enum syscounter_armv8_m_cntrl_scale_nr_t + * \param[out] nr Pointer to structure to read the scale value + * \ref struct syscounter_armv8_m_cntrl_scale_val_t + * + * \return Override condition \ref enum syscounter_armv8_m_cntrl_cntscr_ovr_t + * + * \note This function doesn't check if dev is NULL. + */ +enum syscounter_armv8_m_cntrl_error_t +syscounter_armv8_m_cntrl_get_counter_scale_value( + struct syscounter_armv8_m_cntrl_dev_t* dev, + enum syscounter_armv8_m_cntrl_scale_nr_t nr, + struct syscounter_armv8_m_cntrl_scale_val_t *val); + +/** + * \brief Writes scaling register + * + * \param[in] dev Counter device struct \ref syscounter_armv8_m_cntrl_dev_t + * \param[in] nr Index of scaling register to write + * \ref enum syscounter_armv8_m_cntrl_scale_nr_t + * \param[in] Scale value structure + * \ref struct syscounter_armv8_m_cntrl_scale_val_t + * + * \return Error status \ref enum syscounter_armv8_m_cntrl_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum syscounter_armv8_m_cntrl_error_t +syscounter_armv8_m_cntrl_set_counter_scale_value( + struct syscounter_armv8_m_cntrl_dev_t* dev, + enum syscounter_armv8_m_cntrl_scale_nr_t nr, + struct syscounter_armv8_m_cntrl_scale_val_t val); + +#ifdef __cplusplus +} +#endif +#endif /* __SYSCOUNTER_ARMV8_M_CNTRL_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.c new file mode 100644 index 0000000..c7b4b15 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file systimer_armv8-m_drv.c + * + * \brief Driver for Armv8-M System Timer + * + */ + +#include "systimer_armv8-m_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1u << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1u << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1u << (BIT_INDEX)))) +/** Getter bit-field manipulation macro */ +#define GET_BIT_FIELD(WORD, BIT_MASK, BIT_OFFSET) \ + ((WORD & BIT_MASK) >> BIT_OFFSET) +/** Bit mask for given width bit-field manipulation macro */ +#define BITMASK(width) ((1u<<(width))-1) + +/** + * \brief CNTBase Register map structure + */ +struct cnt_base_reg_map_t { + volatile const uint32_t cntpct_low; + /*!< Offset: 0x000 (RO) Current Physical Counter Value [31:0] */ + volatile const uint32_t cntpct_high; + /*!< Offset: 0x004 (RO) Current Physical Counter Value [63:32] */ + volatile const uint32_t reserved0[2]; + /*!< Offset: 0x008-0x0C Reserved */ + volatile uint32_t cntfrq; + /*!< Offset: 0x010 (R/W) Counter Frequency register in Hz */ + volatile const uint32_t reserved1[3]; + /*!< Offset: 0x014-0x01C Reserved */ + volatile uint32_t cntp_cval_low; + /*!< Offset: 0x020 (R/W) Timer Compare Value register [31:0] */ + volatile uint32_t cntp_cval_high; + /*!< Offset: 0x024 (R/W) Timer Compare Value register [63:32] */ + volatile uint32_t cntp_tval; + /*!< Offset: 0x028 (R/W) Timer Value register */ + volatile uint32_t cntp_ctl; + /*!< Offset: 0x02C (R/W) Timer Control register */ + volatile const uint32_t reserved2[4]; + /*!< Offset: 0x030-0x03C Reserved */ + volatile const uint32_t cntp_aival_low; + /*!< Offset: 0x040 (RO) Auto Increment Value register [31:0]*/ + volatile const uint32_t cntp_aival_high; + /*!< Offset: 0x044 (RO) Auto Increment Value register [63:32]*/ + volatile uint32_t cntp_aival_reload; + /*!< Offset: 0x048 (R/W) Auto Increment Value Reload register [63:32]*/ + volatile uint32_t cntp_aival_ctl; + /*!< Offset: 0x04C (R/W) Auto Increment Control register */ + volatile const uint32_t cntp_cfg; + /*!< Offset: 0x050 (RO) Timer Configuration register */ + volatile const uint32_t reserved3[991]; + /*!< Offset: 0x054-0xFCC Reserved */ + volatile const uint32_t cntp_pid4; + /*!< Offset: 0xFD0 (RO) Peripheral ID Register */ + volatile const uint32_t reserved4[3]; + /*!< Offset: 0xFD4-0xFDC Reserved (RAZWI) */ + volatile const uint32_t cntp_pid0; + /*!< Offset: 0xFE0 (RO) Peripheral ID Register */ + volatile const uint32_t cntp_pid1; + /*!< Offset: 0xFE4 (RO) Peripheral ID Register */ + volatile const uint32_t cntp_pid2; + /*!< Offset: 0xFE8 (RO) Peripheral ID Register */ + volatile const uint32_t cntp_pid3; + /*!< Offset: 0xFEC (RO) Peripheral ID Register */ + volatile const uint32_t cntp_cid0; + /*!< Offset: 0xFF0 (RO) Component ID Register */ + volatile const uint32_t cntp_cid1; + /*!< Offset: 0xFF4 (RO) Component ID Register */ + volatile const uint32_t cntp_cid2; + /*!< Offset: 0xFF8 (RO) Component ID Register */ + volatile const uint32_t cntp_cid3; + /*!< Offset: 0xFFC (RO) Component ID Register */ +}; + +/** + * \brief Timer Control Register bit fields + */ +#define SYSCTIMER_ARMV8M_CNTP_CTL_EN_OFF 0u + /*!< Timer Control Register Enable Counter bit field offset */ +#define SYSCTIMER_ARMV8M_CNTP_CTL_IMASK_OFF 1u +/*!< Timer Control Register Interrupt Mask bit field offset */ +#define SYSCTIMER_ARMV8M_CNTP_CTL_ISTATUS_OFF 2u +/*!< Timer Control Register Interrupt Status bit field offset */ + +/** + * \brief Timer AutoInc Control Register bit fields + */ +#define SYSCTIMER_ARMV8M_CNTP_AIVAL_CTL_EN_OFF 0u + /*!< Timer Control Register Enable Counter bit field offset */ +#define SYSCTIMER_ARMV8M_CNTP_AIVAL_CTL_IRQ_CLR_OFF 1u +/*!< Timer Control Register Interrupt clear bit field offset */ + +/** + * \brief Timer AutoInc Config Register bit fields + */ +#define SYSCTIMER_ARMV8M_CNTP_CFG_CTL_AUTOINC_OFF 0u + /*!< Timer Control Register AutoInc is implemented bit field offset */ + + +void systimer_armv8_m_init(struct systimer_armv8_m_dev_t* dev) +{ + if (dev->data->is_initialized == false) { + systimer_armv8_m_disable_interrupt(dev); + systimer_armv8_m_disable_autoinc(dev); + systimer_armv8_m_set_counter_freq(dev, dev->cfg->default_freq_hz); + systimer_armv8_m_enable_timer(dev); + dev->data->is_initialized = true; + } +} + +void systimer_armv8_m_uninit(struct systimer_armv8_m_dev_t* dev) +{ + if (dev->data->is_initialized == true) { + systimer_armv8_m_disable_interrupt(dev); + systimer_armv8_m_disable_autoinc(dev); + systimer_armv8_m_disable_timer(dev); + dev->data->is_initialized = false; + } +} + +uint64_t systimer_armv8_m_get_counter_value( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + uint32_t high = 0; + uint32_t low = 0; + uint32_t high_prev = 0; + uint64_t value = 0; + + /* Make sure the 64-bit read will be atomic to avoid overflow between + * the low and high registers read + */ + high = p_cnt->cntpct_high; + do { + high_prev = high; + low = p_cnt->cntpct_low; + high = p_cnt->cntpct_high; + }while(high != high_prev); + + value = low | (((uint64_t)high) << SYSTIMER_ARMV8_M_REGISTER_BIT_WIDTH); + return value; +} + +void systimer_armv8_m_set_compare_value( + struct systimer_armv8_m_dev_t* dev, + uint64_t value) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + p_cnt->cntp_cval_low = value & UINT32_MAX; + p_cnt->cntp_cval_high = value >> SYSTIMER_ARMV8_M_REGISTER_BIT_WIDTH; +} + +uint64_t systimer_armv8_m_get_compare_value( + struct systimer_armv8_m_dev_t* dev) +{ + uint64_t value = 0; + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + value = p_cnt->cntp_cval_low | + (((uint64_t)p_cnt->cntp_cval_high) << + SYSTIMER_ARMV8_M_REGISTER_BIT_WIDTH); + return value; +} + +void systimer_armv8_m_set_counter_freq(struct systimer_armv8_m_dev_t* dev, + uint32_t value) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + p_cnt->cntfrq = value; +} + +uint32_t systimer_armv8_m_get_counter_freq( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return p_cnt->cntfrq; +} + +void systimer_armv8_m_set_timer_value(struct systimer_armv8_m_dev_t* dev, + uint32_t value) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + p_cnt->cntp_tval = value; +} + +uint32_t systimer_armv8_m_get_timer_value( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return p_cnt->cntp_tval; +} + +void systimer_armv8_m_enable_timer(struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_EN_OFF); +} + +void systimer_armv8_m_disable_timer(struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_EN_OFF); +} + +bool systimer_armv8_m_is_timer_enabled( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_EN_OFF); +} + +void systimer_armv8_m_enable_interrupt( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + /* The bit is masking interrupt, so it should be inverted. */ + CLR_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_IMASK_OFF); +} + +void systimer_armv8_m_disable_interrupt( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + /* The bit is masking interrupt, so it should be inverted. */ + SET_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_IMASK_OFF); +} + +bool systimer_armv8_m_is_interrupt_enabled( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + /* The bit is masking interrupt, so it should be inverted. */ + return !GET_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_IMASK_OFF); +} + +bool systimer_armv8_m_is_interrupt_asserted( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntp_ctl, SYSCTIMER_ARMV8M_CNTP_CTL_ISTATUS_OFF); +} + +uint64_t systimer_armv8_m_get_autoinc_value( + struct systimer_armv8_m_dev_t* dev) +{ + uint64_t value = 0; + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + value = p_cnt->cntp_aival_low | + (((uint64_t)p_cnt->cntp_aival_high) << + SYSTIMER_ARMV8_M_REGISTER_BIT_WIDTH); + return value; +} + +void systimer_armv8_m_set_autoinc_reload( + struct systimer_armv8_m_dev_t* dev, + uint32_t value) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + p_cnt->cntp_aival_reload = value; +} + +uint32_t systimer_armv8_m_get_autoinc_reload( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return p_cnt->cntp_aival_reload; +} + +void systimer_armv8_m_enable_autoinc(struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + SET_BIT(p_cnt->cntp_aival_ctl, SYSCTIMER_ARMV8M_CNTP_AIVAL_CTL_EN_OFF); +} + +void systimer_armv8_m_disable_autoinc(struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntp_aival_ctl, SYSCTIMER_ARMV8M_CNTP_AIVAL_CTL_EN_OFF); +} + +bool systimer_armv8_m_is_autoinc_enabled( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntp_aival_ctl, + SYSCTIMER_ARMV8M_CNTP_AIVAL_CTL_EN_OFF); +} + +void systimer_armv8_m_clear_autoinc_interrupt( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + CLR_BIT(p_cnt->cntp_aival_ctl, SYSCTIMER_ARMV8M_CNTP_AIVAL_CTL_IRQ_CLR_OFF); +} + +bool systimer_armv8_m_is_autoinc_implemented( + struct systimer_armv8_m_dev_t* dev) +{ + struct cnt_base_reg_map_t* p_cnt = + (struct cnt_base_reg_map_t*)dev->cfg->base; + return GET_BIT(p_cnt->cntp_cfg, + SYSCTIMER_ARMV8M_CNTP_CFG_CTL_AUTOINC_OFF); +} + diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.h new file mode 100644 index 0000000..d14d2f7 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/systimer_armv8-m_drv.h @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file systimer_armv8-m_drv.h + * + * \brief Driver for Armv8-M System Timer + * + * This System Timer is based on the 64-bit Armv8-M System Counter, + * generating the physical count for System Timer. + * + * Main features: + * - Disabling the timer doesn't stop counting, but it disables timer output + * signal, what might be a power saving option. + * - 1 interrupt signal, can be triggered by the 2 modes below + * Modes: + * 1. Normal mode + * For clearing the interrupt generated by normal mode, the Timer + * should be disabled. + * Views + * 1.1. 64-bit up-counting Compare view + * As soon as the physical up-counter reaches the set + * compare value, the interrupt status will be asserted. + * \ref systimer_armv8_m_set_compare_value + * \ref systimer_armv8_m_get_compare_value + + * 1.2. 32-bit down-counting Timer view + * As soon as the down-counter timer reaches zero, + * the interrupt status will be asserted. + * Setting the down-counter timer value, sets the compare + * register by + * compare register = current counter + timer value + * \ref systimer_armv8_m_set_timer_value + * \ref systimer_armv8_m_get_timer_value + * + * 2. Auto-Increment mode + * - The auto-increment feature allows generation of Timer + * interrupt at regular intervals without the need for + * reprogramming the Timer after each interrupt and re-enabling + * the timer logic. + * - Auto-increment is working as a 64-bit up-counter, which is set + * by the 32-bit reload register. + * - If auto-increment mode is enabled, none of the normal modes' + * views can assert interrupt. * + * \ref systimer_armv8_m_get_autoinc_value + * \ref systimer_armv8_m_set_autoinc_reload + * \ref systimer_armv8_m_enable_autoinc + * \ref systimer_armv8_m_disable_autoinc + * \ref systimer_armv8_m_is_autoinc_enabled + * \ref systimer_armv8_m_clear_autoinc_interrupt + * \ref systimer_armv8_m_is_autoinc_implemented + * + */ + +#ifndef __SYSTIMER_ARMV8_M_DRV_H__ +#define __SYSTIMER_ARMV8_M_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SYSTIMER_ARMV8_M_REGISTER_BIT_WIDTH 32u + /*!< Armv8-M System Timer registers bit width */ + +/** + * \brief Armv8-M System Timer device configuration structure + */ +struct systimer_armv8_m_dev_cfg_t { + const uint32_t base; + /*!< Armv8-M System Timer device base address */ + uint32_t default_freq_hz; + /*!< Default reported frequency in Hz */ +}; + +/** + * \brief Armv8-M System Timer device data structure + */ +struct systimer_armv8_m_dev_data_t { + bool is_initialized; +}; + +/** + * \brief Armv8-M System Timer device structure + */ +struct systimer_armv8_m_dev_t { + const struct systimer_armv8_m_dev_cfg_t* const cfg; + /*!< Armv8-M System Timer configuration structure */ + struct systimer_armv8_m_dev_data_t* const data; + /*!< Armv8-M System Timer data structure */ +}; + +/** + * \brief Initializes timer to a known default state, which is: + * - timer is enabled + * - interrupt is disabled + * - auto-increment is disabled + * - reported timer frequency is set to default + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * More than one call results fall through. + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_init(struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Uninitializes timer to a known default state, which is: + * - timer is disabled + * - interrupt is disabled + * - auto-increment is disabled + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * More than one call results fall through. + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_uninit(struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Reads 64-bit physical counter value + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return 64-bit counter value + * + * \note This function doesn't check if dev is NULL. + */ +uint64_t systimer_armv8_m_get_counter_value( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Sets 64-bit compare value + * As soon as the physical up-counter reaches this value, the interrupt + * condition will be asserted \ref systimer_armv8_m_is_interrupt_asserted + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * \param[in] value 64-bit compare value + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_set_compare_value( + struct systimer_armv8_m_dev_t* dev, + uint64_t value); + +/** + * \brief Reads 64-bit compare value + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return 64-bit compare value + * + * \note This function doesn't check if dev is NULL. + */ +uint64_t systimer_armv8_m_get_compare_value( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Sets frequency register in Hz + * Hardware does not interpret the value of the register, so it's only + * for software can discover the frequency of the system counter. + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * \param[in] value frequency in Hz + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_set_counter_freq( + struct systimer_armv8_m_dev_t* dev, + uint32_t value); + +/** + * \brief Reads frequency register in Hz + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return frequency in Hz + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t systimer_armv8_m_get_counter_freq( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Sets 32-bit down-counter timer value + * 'Down-counter timer set' automatically sets the compare register by + * compare register = current counter + this timer value + * + * As soon as the timer value reaches zero, the interrupt condition will + * be asserted \ref systimer_armv8_m_is_interrupt_asserted. + * Reaching zero doesn't stop the timer. + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * \param[in] value 32-bit timer value + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_set_timer_value(struct systimer_armv8_m_dev_t* dev, + uint32_t value); + +/** + * \brief Reads down-counter timer value + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return 32-bit timer value + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t systimer_armv8_m_get_timer_value( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Enables timer + * Enables timer output signal and interrupt status assertion + * \ref systimer_armv8_m_is_interrupt_asserted + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_enable_timer(struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Disables timer + * Disables timer output signal. Interrupt status will be unknown + * \ref systimer_armv8_m_is_interrupt_asserted + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_disable_timer(struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Polls timer enable status + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool systimer_armv8_m_is_timer_enabled( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Enables timer interrupt + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_enable_interrupt( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Disables timer interrupt + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_disable_interrupt( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Polls timer interrupt enable status + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool systimer_armv8_m_is_interrupt_enabled( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Polls timer interrupt status + * It's asserted if + * 1. Auto-Inc is disabled and counter reaches compare value + * OR + * 2. Auto-Inc is enabled and counter reaches auto-inc value + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return true if asserted, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool systimer_armv8_m_is_interrupt_asserted( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Reads auto-increment value + * This value is automatically calculated by + * auto-inc = current counter + auto-inc reload + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return 64-bit auto-increment value + * + * \note This function doesn't check if dev is NULL. + */ +uint64_t systimer_armv8_m_get_autoinc_value( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Sets 32-bit auto-increment reload value + * Auto-Inc value is automatically calculated by adding this reload value + * to the current counter. + * If the counter reaches auto-inc value, interrupt status is asserted + * and auto-inc value is automatically set by current reload. + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * \param[in] value 32-bit reload value + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_set_autoinc_reload( + struct systimer_armv8_m_dev_t* dev, + uint32_t value); + +/** + * \brief Reads auto-increment reload value + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return 32-bit auto-increment reload value + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t systimer_armv8_m_get_autoinc_reload( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Enables auto-increment mode + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_enable_autoinc(struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Disables auto-increment mode + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_disable_autoinc(struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Polls auto-increment enable status + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return true if enabled, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool systimer_armv8_m_is_autoinc_enabled( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Clears auto-increment mode interrupt flag + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void systimer_armv8_m_clear_autoinc_interrupt( + struct systimer_armv8_m_dev_t* dev); + +/** + * \brief Polls auto-increment implementation status + * + * \param[in] dev Timer device struct \ref systimer_armv8_m_dev_t + * + * \return true if implemented, false otherwise + * + * \note This function doesn't check if dev is NULL. + */ +bool systimer_armv8_m_is_autoinc_implemented( + struct systimer_armv8_m_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __SYSTIMER_ARMV8_M_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.c b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.c new file mode 100644 index 0000000..c3d1230 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2016-2019 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "uart_cmsdk_drv.h" + +#include + +/* UART register map structure */ +struct _uart_cmsdk_reg_map_t { + volatile uint32_t data; /* Offset: 0x000 (R/W) data register */ + volatile uint32_t state; /* Offset: 0x004 (R/W) status register */ + volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */ + union { + volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status + * register + */ + volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear + * register + */ + }intr_reg; + volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider + * register + */ +}; + +/* CTRL Register */ +#define UART_CMSDK_TX_EN (1ul << 0) +#define UART_CMSDK_RX_EN (1ul << 1) +#define UART_CMSDK_TX_INTR_EN (1ul << 2) +#define UART_CMSDK_RX_INTR_EN (1ul << 3) + +/* STATE Register */ +#define UART_CMSDK_TX_BF (1ul << 0) +#define UART_CMSDK_RX_BF (1ul << 1) + +/* INTSTATUS Register */ +#define UART_CMSDK_TX_INTR (1ul << 0) +#define UART_CMSDK_RX_INTR (1ul << 1) + +/* UART state definitions */ +#define UART_CMSDK_INITIALIZED (1ul << 0) + +enum uart_cmsdk_error_t uart_cmsdk_init(struct uart_cmsdk_dev_t* dev, + uint32_t system_clk) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + if(system_clk == 0) { + return UART_CMSDK_ERR_INVALID_ARG; + } + + /* Sets baudrate and system clock */ + dev->data->system_clk = system_clk; + dev->data->baudrate = dev->cfg->default_baudrate; + + /* Sets baudrate */ + p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate); + + /* Enables receiver and transmitter */ + p_uart->ctrl = UART_CMSDK_RX_EN | UART_CMSDK_TX_EN; + + dev->data->state = UART_CMSDK_INITIALIZED; + + return UART_CMSDK_ERR_NONE; +} + +enum uart_cmsdk_error_t uart_cmsdk_set_baudrate(struct uart_cmsdk_dev_t* dev, + uint32_t baudrate) +{ + uint32_t bauddiv; + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(baudrate == 0) { + return UART_CMSDK_ERR_INVALID_BAUD; + } + + if(!(dev->data->state & UART_CMSDK_INITIALIZED)) { + return UART_CMSDK_ERR_NOT_INIT; + } + + /* Sets baudrate */ + bauddiv = (dev->data->system_clk / baudrate); + dev->data->baudrate = baudrate; + + /* Minimum bauddiv value */ + if(bauddiv < 16) { + return UART_CMSDK_ERR_INVALID_BAUD; + } + + p_uart->bauddiv = bauddiv; + + return UART_CMSDK_ERR_NONE; +} + +uint32_t uart_cmsdk_get_baudrate(struct uart_cmsdk_dev_t* dev) +{ + return dev->data->baudrate; +} + +enum uart_cmsdk_error_t uart_cmsdk_set_clock(struct uart_cmsdk_dev_t* dev, + uint32_t system_clk) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(system_clk == 0) { + return UART_CMSDK_ERR_INVALID_ARG; + } + + if(!(dev->data->state & UART_CMSDK_INITIALIZED)) { + return UART_CMSDK_ERR_NOT_INIT; + } + + /* Sets system clock */ + dev->data->system_clk = system_clk; + + /* Updates baudrate divider */ + p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate); + + /* Enables receiver and transmitter */ + return UART_CMSDK_ERR_NONE; +} + +enum uart_cmsdk_error_t uart_cmsdk_read(struct uart_cmsdk_dev_t* dev, + uint8_t* byte) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(!(p_uart->state & UART_CMSDK_RX_BF)) { + return UART_CMSDK_ERR_NOT_READY; + } + + /* Reads data */ + *byte = (uint8_t)p_uart->data; + + return UART_CMSDK_ERR_NONE; +} + +enum uart_cmsdk_error_t uart_cmsdk_write(struct uart_cmsdk_dev_t* dev, + uint8_t byte) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(p_uart->state & UART_CMSDK_TX_BF) { + return UART_CMSDK_ERR_NOT_READY; + } + + /* Sends data */ + p_uart->data = byte; + + return UART_CMSDK_ERR_NONE; +} + +enum uart_cmsdk_error_t uart_cmsdk_irq_tx_enable(struct uart_cmsdk_dev_t* dev) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & UART_CMSDK_INITIALIZED)) { + return UART_CMSDK_ERR_NOT_INIT; + } + + p_uart->ctrl |= UART_CMSDK_TX_INTR_EN; + + return UART_CMSDK_ERR_NONE; +} + +void uart_cmsdk_irq_tx_disable(struct uart_cmsdk_dev_t* dev) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(dev->data->state & UART_CMSDK_INITIALIZED ) { + p_uart->ctrl &= ~UART_CMSDK_TX_INTR_EN; + } +} + +uint32_t uart_cmsdk_tx_ready(struct uart_cmsdk_dev_t* dev) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & UART_CMSDK_INITIALIZED)) { + return 0; + } + + return !(p_uart->state & UART_CMSDK_TX_BF); +} + +enum uart_cmsdk_error_t uart_cmsdk_irq_rx_enable(struct uart_cmsdk_dev_t* dev) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & UART_CMSDK_INITIALIZED)) { + return UART_CMSDK_ERR_NOT_INIT; + } + + p_uart->ctrl |= UART_CMSDK_RX_INTR_EN; + + return UART_CMSDK_ERR_NONE; +} + +void uart_cmsdk_irq_rx_disable(struct uart_cmsdk_dev_t* dev) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(dev->data->state & UART_CMSDK_INITIALIZED) { + p_uart->ctrl &= ~UART_CMSDK_RX_INTR_EN; + } +} + +uint32_t uart_cmsdk_rx_ready(struct uart_cmsdk_dev_t* dev) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & UART_CMSDK_INITIALIZED)) { + return 0; + } + + return (p_uart->state & UART_CMSDK_RX_BF); +} + +void uart_cmsdk_clear_interrupt(struct uart_cmsdk_dev_t* dev, + enum uart_cmsdk_irq_t irq) +{ + struct _uart_cmsdk_reg_map_t* p_uart = + (struct _uart_cmsdk_reg_map_t*)dev->cfg->base; + + if(dev->data->state & UART_CMSDK_INITIALIZED) { + /* Clears pending interrupts */ + switch(irq) { + case UART_CMSDK_IRQ_RX: + p_uart->intr_reg.intrclear = UART_CMSDK_RX_INTR; + break; + case UART_CMSDK_IRQ_TX: + p_uart->intr_reg.intrclear = UART_CMSDK_TX_INTR; + break; + case UART_CMSDK_IRQ_COMBINED: + p_uart->intr_reg.intrclear = + (UART_CMSDK_RX_INTR | UART_CMSDK_TX_INTR); + break; + /* default: not defined to force all cases to be handled */ + } + } +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.h b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.h new file mode 100644 index 0000000..2d3278e --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/native_drivers/uart_cmsdk_drv.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2016-2019 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file uart_cmsdk_drv.h + * \brief Generic driver for ARM UART. + */ + +#ifndef __UART_CMSDK_DRV_H__ +#define __UART_CMSDK_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ARM UART device configuration structure */ +struct uart_cmsdk_dev_cfg_t { + const uint32_t base; /*!< UART base address */ + const uint32_t default_baudrate; /*!< Default baudrate */ +}; + +/* ARM UART device data structure */ +struct uart_cmsdk_dev_data_t { + uint32_t state; /*!< Indicates if the uart driver + * is initialized and enabled + */ + uint32_t system_clk; /*!< System clock */ + uint32_t baudrate; /*!< Baudrate */ +}; + +/* ARM UART device structure */ +struct uart_cmsdk_dev_t { + const struct uart_cmsdk_dev_cfg_t* const cfg; /*!< UART configuration */ + struct uart_cmsdk_dev_data_t* const data; /*!< UART data */ +}; + +/* ARM UART enumeration types */ +enum uart_cmsdk_error_t { + UART_CMSDK_ERR_NONE = 0, /*!< No error */ + UART_CMSDK_ERR_INVALID_ARG, /*!< Error invalid input argument */ + UART_CMSDK_ERR_INVALID_BAUD, /*!< Invalid baudrate */ + UART_CMSDK_ERR_NOT_INIT, /*!< Error UART not initialized */ + UART_CMSDK_ERR_NOT_READY, /*!< Error UART not ready */ +}; + +enum uart_cmsdk_irq_t { + UART_CMSDK_IRQ_RX, /*!< RX interrupt source */ + UART_CMSDK_IRQ_TX, /*!< TX interrupt source */ + UART_CMSDK_IRQ_COMBINED /*!< RX-TX combined interrupt source */ +}; + +/** + * \brief Initializes UART. It uses the default baudrate to configure + * the peripheral at this point. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * \param[in] system_clk System clock used by the device. + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum uart_cmsdk_error_t uart_cmsdk_init(struct uart_cmsdk_dev_t* dev, + uint32_t system_clk); + +/** + * \brief Sets the UART baudrate. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * \param[in] baudrate New baudrate. + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum uart_cmsdk_error_t uart_cmsdk_set_baudrate(struct uart_cmsdk_dev_t* dev, + uint32_t baudrate); + +/** + * \brief Gets the UART baudrate. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \return Returns the UART baudrate. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t uart_cmsdk_get_baudrate(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Sets system clock. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * \param[in] system_clk System clock used by the device. + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum uart_cmsdk_error_t uart_cmsdk_set_clock(struct uart_cmsdk_dev_t* dev, + uint32_t system_clk); +/** + * \brief Reads one byte from UART dev. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * \param[in] byte Pointer to byte. + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note For better performance, this function doesn't check if dev and byte + * pointer are NULL, and if the driver is initialized. + */ +enum uart_cmsdk_error_t uart_cmsdk_read(struct uart_cmsdk_dev_t* dev, + uint8_t* byte); + +/** + * \brief Writes a byte to UART dev. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * \param[in] byte Byte to write. + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note For better performance, this function doesn't check if dev is NULL and + * if the driver is initialized to have better performance. + */ +enum uart_cmsdk_error_t uart_cmsdk_write(struct uart_cmsdk_dev_t* dev, + uint8_t byte); + +/** + * \brief Enables TX interrupt. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum uart_cmsdk_error_t uart_cmsdk_irq_tx_enable(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Disables TX interrupt. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void uart_cmsdk_irq_tx_disable(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Verifies if Tx is ready to send more data. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \return 1 if TX is ready, 0 otherwise. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t uart_cmsdk_tx_ready(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Enables RX interrupt. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \return Returns error code as specified in \ref uart_cmsdk_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum uart_cmsdk_error_t uart_cmsdk_irq_rx_enable(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Disables RX interrupt + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void uart_cmsdk_irq_rx_disable(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Verifies if Rx has data. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * + * \return 1 if RX has data, 0 otherwise. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t uart_cmsdk_rx_ready(struct uart_cmsdk_dev_t* dev); + +/** + * \brief Clears UART interrupt. + * + * \param[in] dev UART device struct \ref uart_cmsdk_dev_t + * \param[in] irq IRQ source to clean \ref uart_cmsdk_irq_t + * + * \note This function doesn't check if dev is NULL. + */ +void uart_cmsdk_clear_interrupt(struct uart_cmsdk_dev_t* dev, + enum uart_cmsdk_irq_t irq); + +#ifdef __cplusplus +} +#endif +#endif /* __UART_CMSDK_DRV_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/partition/flash_layout.h b/bsp/tf_m_targets/arm/mps3/an547/partition/flash_layout.h new file mode 100644 index 0000000..21f49bb --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/partition/flash_layout.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FLASH_LAYOUT_H__ +#define __FLASH_LAYOUT_H__ + +#include "platform_base_address.h" + +/* WARNING: Layout below has been moved to QSPI_SRAM and addresses so different now */ +/* Flash layout on AN547 with BL2 (multiple image boot): + * + * 0x0000_0000 Secure image primary slot (384 KB) + * 0x0006_0000 Non-secure image primary slot (2 MB) + * 0x000C_0000 Secure image secondary slot (384 KB) + * 0x0012_0000 Non-secure image secondary slot (2 MB) + * 0x0018_0000 Scratch area (2 MB) + * 0x001E_0000 Protected Storage Area (20 KB) + * 0x001E_5000 Internal Trusted Storage Area (16 KB) + * 0x001E_9000 NV counters area (4 KB) + * 0x001E_E800 Unused + * + * Flash layout on AN547 with BL2 (single image boot): + * + * 0x0000_0000 Primary image area (768 KB): + * 0x0000_0000 Secure image primary (384 KB) + * 0x0006_0000 Non-secure image primary (384 KB) + * 0x000C_0000 Secondary image area (768 KB): + * 0x000C_0000 Secure image secondary (384 KB) + * 0x0012_0000 Non-secure image secondary (384 KB) + * 0x0018_0000 Scratch area (384 KB) + * 0x001C_0000 Protected Storage Area (20 KB) + * 0x001C_5000 Internal Trusted Storage Area (16 KB) + * 0x001C_9000 NV counters area (4 KB) + * 0x001C_A000 Unused + */ + + + +/* This header file is included from linker scatter file as well, where only a + * limited C constructs are allowed. Therefore it is not possible to include + * here the platform_retarget.h to access flash related defines. To resolve this + * some of the values are redefined here with different names, these are marked + * with comment. + */ + +/* Size of a Secure and of a Non-secure image */ +#define FLASH_S_PARTITION_SIZE (0x60000) /* S partition: 384 KB */ +#define FLASH_NS_PARTITION_SIZE (0x200000) /* NS partition: 1MB */ +#define FLASH_MAX_PARTITION_SIZE ((FLASH_S_PARTITION_SIZE > \ + FLASH_NS_PARTITION_SIZE) ? \ + FLASH_S_PARTITION_SIZE : \ + FLASH_NS_PARTITION_SIZE) + +/* Sector size of the flash hardware; same as FLASH0_SECTOR_SIZE */ +#define FLASH_AREA_IMAGE_SECTOR_SIZE (0x1000) /* 4 KB */ +/* Same as FLASH0_SIZE */ +#define FLASH_TOTAL_SIZE (QSPI_SRAM_SIZE) /* 2 MB */ + +/* Flash layout info for BL2 bootloader */ +/* Same as FLASH0_BASE_S */ +#define FLASH_BASE_ADDRESS (QSPI_SRAM_BASE_S) + +/* Offset and size definitions of the flash partitions that are handled by the + * bootloader. The image swapping is done between IMAGE_PRIMARY and + * IMAGE_SECONDARY, SCRATCH is used as a temporary storage during image + * swapping. + */ +#define FLASH_AREA_BL2_OFFSET (0x0) +#define FLASH_AREA_BL2_SIZE (ITCM_SIZE) /* 256 KB */ + +#if !defined(MCUBOOT_IMAGE_NUMBER) || (MCUBOOT_IMAGE_NUMBER == 1) +/* Secure + Non-secure image primary slot */ +#define FLASH_AREA_0_ID (1) +#define FLASH_AREA_0_OFFSET (0)//(FLASH_AREA_BL2_OFFSET + FLASH_AREA_BL2_SIZE)// +#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE + \ + FLASH_NS_PARTITION_SIZE) +/* Secure + Non-secure secondary slot */ +#define FLASH_AREA_2_ID (FLASH_AREA_0_ID + 1) +#define FLASH_AREA_2_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE) +#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE + \ + FLASH_NS_PARTITION_SIZE) +/* Scratch area */ +#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_2_ID + 1) +#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE) +#define FLASH_AREA_SCRATCH_SIZE (FLASH_MAX_PARTITION_SIZE) +/* The maximum number of status entries supported by the bootloader. */ +#define MCUBOOT_STATUS_MAX_ENTRIES ((FLASH_S_PARTITION_SIZE + \ + FLASH_NS_PARTITION_SIZE) / \ + FLASH_AREA_SCRATCH_SIZE) +/* Maximum number of image sectors supported by the bootloader. */ +#define MCUBOOT_MAX_IMG_SECTORS ((FLASH_S_PARTITION_SIZE + \ + FLASH_NS_PARTITION_SIZE) / \ + FLASH_AREA_IMAGE_SECTOR_SIZE) +#elif (MCUBOOT_IMAGE_NUMBER == 2) +/* Secure image primary slot */ +#define FLASH_AREA_0_ID (1) +#define FLASH_AREA_0_OFFSET (0)//(FLASH_AREA_BL2_OFFSET + FLASH_AREA_BL2_SIZE)// +#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE) +/* Non-secure image primary slot */ +#define FLASH_AREA_1_ID (FLASH_AREA_0_ID + 1) +#define FLASH_AREA_1_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE) +#define FLASH_AREA_1_SIZE (FLASH_NS_PARTITION_SIZE) +/* Secure image secondary slot */ +#define FLASH_AREA_2_ID (FLASH_AREA_1_ID + 1) +#define FLASH_AREA_2_OFFSET (FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE) +#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE) +/* Non-secure image secondary slot */ +#define FLASH_AREA_3_ID (FLASH_AREA_2_ID + 1) +#define FLASH_AREA_3_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE) +#define FLASH_AREA_3_SIZE (FLASH_NS_PARTITION_SIZE) +/* Scratch area */ +#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_3_ID + 1) +#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_3_OFFSET + FLASH_AREA_3_SIZE) +#define FLASH_AREA_SCRATCH_SIZE (FLASH_MAX_PARTITION_SIZE) +/* The maximum number of status entries supported by the bootloader. */ +#define MCUBOOT_STATUS_MAX_ENTRIES (FLASH_MAX_PARTITION_SIZE / \ + FLASH_AREA_SCRATCH_SIZE) +/* Maximum number of image sectors supported by the bootloader. */ +#define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ + FLASH_AREA_IMAGE_SECTOR_SIZE) +#else /* MCUBOOT_IMAGE_NUMBER > 2 */ +#error "Only MCUBOOT_IMAGE_NUMBER 1 and 2 are supported!" +#endif /* MCUBOOT_IMAGE_NUMBER */ + +/* mpc_init_cfg function in target_cfg.c expects that all the images can fit + * in SRAM area. */ +#if ( FLASH_AREA_SCRATCH_OFFSET + FLASH_AREA_SCRATCH_SIZE > QSPI_SRAM_SIZE) +#error "Out of SRAM memory!" +#endif + +/* Protected Storage (PS) Service definitions */ +#define FLASH_PS_AREA_OFFSET (FLASH_AREA_SCRATCH_OFFSET + \ + FLASH_AREA_SCRATCH_SIZE) +#define FLASH_PS_AREA_SIZE (0x5000) /* 20 KB */ + +/* Internal Trusted Storage (ITS) Service definitions */ +#define FLASH_ITS_AREA_OFFSET (FLASH_PS_AREA_OFFSET + \ + FLASH_PS_AREA_SIZE) +#define FLASH_ITS_AREA_SIZE (0x4000) /* 16 KB */ + +/* NV Counters definitions */ +#define FLASH_NV_COUNTERS_AREA_OFFSET (FLASH_ITS_AREA_OFFSET + \ + FLASH_ITS_AREA_SIZE) +#define FLASH_NV_COUNTERS_AREA_SIZE (FLASH_AREA_IMAGE_SECTOR_SIZE) + +/* Offset and size definition in flash area used by assemble.py */ +#define SECURE_IMAGE_OFFSET (0x0) +#define SECURE_IMAGE_MAX_SIZE FLASH_S_PARTITION_SIZE + +#define NON_SECURE_IMAGE_OFFSET (SECURE_IMAGE_OFFSET + \ + SECURE_IMAGE_MAX_SIZE) +#define NON_SECURE_IMAGE_MAX_SIZE FLASH_NS_PARTITION_SIZE + +/* Flash device name used by BL2 + * Name is defined in flash driver file: Driver_Flash.c + */ +#define FLASH_DEV_NAME Driver_FLASH0 + +/* Protected Storage (PS) Service definitions + * Note: Further documentation of these definitions can be found in the + * TF-M PS Integration Guide. + */ +#define TFM_HAL_PS_FLASH_DRIVER Driver_FLASH0 + +/* In this target the CMSIS driver requires only the offset from the base + * address instead of the full memory address. + */ +/* Base address of dedicated flash area for PS */ +#define TFM_HAL_PS_FLASH_AREA_ADDR FLASH_PS_AREA_OFFSET +/* Size of dedicated flash area for PS */ +#define TFM_HAL_PS_FLASH_AREA_SIZE FLASH_PS_AREA_SIZE +#define PS_RAM_FS_SIZE TFM_HAL_PS_FLASH_AREA_SIZE +/* Number of physical erase sectors per logical FS block */ +#define TFM_HAL_PS_SECTORS_PER_BLOCK (1) +/* Smallest flash programmable unit in bytes */ +#define TFM_HAL_PS_PROGRAM_UNIT (0x1) + +/* Internal Trusted Storage (ITS) Service definitions + * Note: Further documentation of these definitions can be found in the + * TF-M ITS Integration Guide. The ITS should be in the internal flash, but is + * allocated in the external flash just for development platforms that don't + * have internal flash available. + */ +#define TFM_HAL_ITS_FLASH_DRIVER Driver_FLASH0 + +/* In this target the CMSIS driver requires only the offset from the base + * address instead of the full memory address. + */ +/* Base address of dedicated flash area for ITS */ +#define TFM_HAL_ITS_FLASH_AREA_ADDR FLASH_ITS_AREA_OFFSET +/* Size of dedicated flash area for ITS */ +#define TFM_HAL_ITS_FLASH_AREA_SIZE FLASH_ITS_AREA_SIZE +#define ITS_RAM_FS_SIZE TFM_HAL_ITS_FLASH_AREA_SIZE +/* Number of physical erase sectors per logical FS block */ +#define TFM_HAL_ITS_SECTORS_PER_BLOCK (1) +/* Smallest flash programmable unit in bytes */ +#define TFM_HAL_ITS_PROGRAM_UNIT (0x1) + +/* NV Counters definitions */ +#define TFM_NV_COUNTERS_AREA_ADDR FLASH_NV_COUNTERS_AREA_OFFSET +#define TFM_NV_COUNTERS_AREA_SIZE (0x18) /* 24 Bytes */ +#define TFM_NV_COUNTERS_SECTOR_ADDR FLASH_NV_COUNTERS_AREA_OFFSET +#define TFM_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE + +#endif /* __FLASH_LAYOUT_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/partition/platform_base_address.h b/bsp/tf_m_targets/arm/mps3/an547/partition/platform_base_address.h new file mode 100644 index 0000000..ba39235 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/partition/platform_base_address.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2019-2021 Arm Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file platform_base_address.h + * \brief This file defines all the peripheral base addresses for AN547 MPS3 SSE-300 + + * Ethos-U55 platform. + */ + +#ifndef __PLATFORM_BASE_ADDRESS_H__ +#define __PLATFORM_BASE_ADDRESS_H__ + +/* ======= Defines peripherals memory map addresses ======= */ +/* Non-secure memory map addresses */ +#define ITCM_BASE_NS 0x00000000 /* Instruction TCM Non-Secure base address */ +#define SRAM_BASE_NS 0x01000000 /* CODE SRAM Non-Secure base address */ +#define DTCM0_BASE_NS 0x20000000 /* Data TCM block 0 Non-Secure base address */ +#define DTCM1_BASE_NS 0x20020000 /* Data TCM block 1 Non-Secure base address */ +#define DTCM2_BASE_NS 0x20040000 /* Data TCM block 2 Non-Secure base address */ +#define DTCM3_BASE_NS 0x20060000 /* Data TCM block 3 Non-Secure base address */ +#define ISRAM0_BASE_NS 0x21000000 /* Internal SRAM Area Non-Secure base address */ +#define ISRAM1_BASE_NS 0x21200000 /* Internal SRAM Area Non-Secure base address */ +#define QSPI_SRAM_BASE_NS 0x28000000 /* QSPI SRAM Non-Secure base address */ +/* Non-Secure Subsystem peripheral region */ +#define CPU0_PWRCTRL_BASE_NS 0x40012000 /* CPU 0 Power Control Block Non-Secure base address */ +#define CPU0_IDENTITY_BASE_NS 0x4001F000 /* CPU 0 Identity Block Non-Secure base address */ +#define SSE300_NSACFG_BASE_NS 0x40080000 /* SSE-300 Non-Secure Access Configuration Register Block Non-Secure base address */ +/* Non-Secure MSTEXPPILL Peripheral region */ +#define GPIO0_CMSDK_BASE_NS 0x41100000 /* GPIO 0 Non-Secure base address */ +#define GPIO1_CMSDK_BASE_NS 0x41101000 /* GPIO 1 Non-Secure base address */ +#define GPIO2_CMSDK_BASE_NS 0x41102000 /* GPIO 2 Non-Secure base address */ +#define GPIO3_CMSDK_BASE_NS 0x41103000 /* GPIO 3 Non-Secure base address */ +#define AHB_USER_0_BASE_NS 0x41104000 /* AHB USER 0 Non-Secure base address */ +#define AHB_USER_1_BASE_NS 0x41105000 /* AHB USER 1 Non-Secure base address */ +#define AHB_USER_2_BASE_NS 0x41106000 /* AHB USER 2 Non-Secure base address */ +#define AHB_USER_3_BASE_NS 0x41107000 /* AHB USER 3 Non-Secure base address */ +#define DMA_0_BASE_NS 0x41200000 /* DMA 0 Non-Secure base address */ +#define DMA_1_BASE_NS 0x41201000 /* DMA 1 Non-Secure base address */ +#define DMA_2_BASE_NS 0x41202000 /* DMA 2 Non-Secure base address */ +#define DMA_3_BASE_NS 0x41203000 /* DMA 3 Non-Secure base address */ +#define ETHERNET_BASE_NS 0x41400000 /* Ethernet Non-Secure base address */ +#define USB_BASE_NS 0x41500000 /* USB Non-Secure base address */ +#define USER_APB0_BASE_NS 0x41700000 /* User APB 0 Non-Secure base address */ +#define USER_APB1_BASE_NS 0x41701000 /* User APB 1 Non-Secure base address */ +#define USER_APB2_BASE_NS 0x41702000 /* User APB 2 Non-Secure base address */ +#define USER_APB3_BASE_NS 0x41703000 /* User APB 3 Non-Secure base address */ +#define QSPI_CONFIG_BASE_NS 0x41800000 /* QSPI Config Non-Secure base address */ +#define QSPI_WRITE_BASE_NS 0x41801000 /* QSPI Write Non-Secure base address */ +/* Non-Secure Subsystem peripheral region */ +#define SYSTIMER0_ARMV8_M_BASE_NS 0x48000000 /* System Timer 0 Non-Secure base address */ +#define SYSTIMER1_ARMV8_M_BASE_NS 0x48001000 /* System Timer 1 Non-Secure base address */ +#define SYSTIMER2_ARMV8_M_BASE_NS 0x48002000 /* System Timer 2 Non-Secure base address */ +#define SYSTIMER3_ARMV8_M_BASE_NS 0x48003000 /* System Timer 3 Non-Secure base address */ +#define SSE300_SYSINFO_BASE_NS 0x48020000 /* SSE-300 System info Block Non-Secure base address */ +#define SLOWCLK_TIMER_CMSDK_BASE_NS 0x4802F000 /* CMSDK based SLOWCLK Timer Non-Secure base address */ +#define SYSWDOG_ARMV8_M_CNTRL_BASE_NS 0x48040000 /* Non-Secure Watchdog Timer control frame Non-Secure base address */ +#define SYSWDOG_ARMV8_M_REFRESH_BASE_NS 0x48041000 /* Non-Secure Watchdog Timer refresh frame Non-Secure base address */ +#define SYSCNTR_READ_BASE_NS 0x48101000 /* System Counter Read Secure base address */ +/* Non-Secure MSTEXPPIHL Peripheral region */ +#define ETHOS_U55_APB_BASE_NS 0x48102000 /* Ethos-U55 APB Non-Secure base address */ +#define U55_TIMING_ADAPTER_0_BASE_NS 0x48103000 /* Ethos-U55 Timing Adapter 0 APB registers Non-Secure base address */ +#define U55_TIMING_ADAPTER_1_BASE_NS 0x48103200 /* Ethos-U55 Timing Adapter 1 APB registers Non-Secure base address */ +#define FPGA_SBCon_I2C_TOUCH_BASE_NS 0x49200000 /* FPGA - SBCon I2C (Touch) Non-Secure base address */ +#define FPGA_SBCon_I2C_AUDIO_BASE_NS 0x49201000 /* FPGA - SBCon I2C (Audio Conf) Non-Secure base address */ +#define FPGA_SPI_ADC_BASE_NS 0x49202000 /* FPGA - PL022 (SPI ADC) Non-Secure base address */ +#define FPGA_SPI_SHIELD0_BASE_NS 0x49203000 /* FPGA - PL022 (SPI Shield0) Non-Secure base address */ +#define FPGA_SPI_SHIELD1_BASE_NS 0x49204000 /* FPGA - PL022 (SPI Shield1) Non-Secure base address */ +#define SBCon_I2C_SHIELD0_BASE_NS 0x49205000 /* SBCon (I2C - Shield0) Non-Secure base address */ +#define SBCon_I2C_SHIELD1_BASE_NS 0x49206000 /* SBCon (I2C – Shield1) Non-Secure base address */ +#define USER_APB_BASE_NS 0x49207000 /* USER APB Non-Secure base address */ +#define FPGA_DDR4_EEPROM_BASE_NS 0x49208000 /* FPGA - SBCon I2C (DDR4 EEPROM) Non-Secure base address */ +#define FPGA_SCC_BASE_NS 0x49300000 /* FPGA - SCC registers Non-Secure base address */ +#define FPGA_I2S_BASE_NS 0x49301000 /* FPGA - I2S (Audio) Non-Secure base address */ +#define FPGA_IO_BASE_NS 0x49302000 /* FPGA - IO (System Ctrl + I/O) Non-Secure base address */ +#define UART0_BASE_NS 0x49303000 /* UART 0 Non-Secure base address */ +#define UART1_BASE_NS 0x49304000 /* UART 1 Non-Secure base address */ +#define UART2_BASE_NS 0x49305000 /* UART 2 Non-Secure base address */ +#define UART3_BASE_NS 0x49306000 /* UART 3 Non-Secure base address */ +#define UART4_BASE_NS 0x49307000 /* UART 4 Non-Secure base address */ +#define UART5_BASE_NS 0x49308000 /* UART 5 Non-Secure base address */ +#define CLCD_Config_Reg_BASE_NS 0x4930A000 /* CLCD Config Reg Non-Secure base address */ +#define RTC_BASE_NS 0x4930B000 /* RTC Non-Secure base address */ +#define DDR4_BLK0_BASE_NS 0x60000000 /* DDR4 block 0 Non-Secure base address */ +#define DDR4_BLK2_BASE_NS 0x80000000 /* DDR4 block 2 Non-Secure base address */ +#define DDR4_BLK4_BASE_NS 0xA0000000 /* DDR4 block 4 Non-Secure base address */ +#define DDR4_BLK6_BASE_NS 0xC0000000 /* DDR4 block 6 Non-Secure base address */ + +/* Secure memory map addresses */ +#define ITCM_BASE_S 0x10000000 /* Instruction TCM Secure base address */ +#define SRAM_BASE_S 0x11000000 /* CODE SRAM Secure base address */ +#define DTCM0_BASE_S 0x30000000 /* Data TCM block 0 Secure base address */ +#define DTCM1_BASE_S 0x30020000 /* Data TCM block 1 Secure base address */ +#define DTCM2_BASE_S 0x30040000 /* Data TCM block 2 Secure base address */ +#define DTCM3_BASE_S 0x30060000 /* Data TCM block 3 Secure base address */ +#define ISRAM0_BASE_S 0x31000000 /* Internal SRAM Area Secure base address */ +#define ISRAM1_BASE_S 0x31200000 /* Internal SRAM Area Secure base address */ +#define QSPI_SRAM_BASE_S 0x38000000 /* QSPI SRAM Secure base address */ +/* Secure Subsystem peripheral region */ +#define CPU0_SECCTRL_BASE_S 0x50011000 /* CPU 0 Local Security Control Block Secure base address */ +#define CPU0_PWRCTRL_BASE_S 0x50012000 /* CPU 0 Power Control Block Secure base address */ +#define CPU0_IDENTITY_BASE_S 0x5001F000 /* CPU 0 Identity Block Secure base address */ +#define SSE300_SACFG_BASE_S 0x50080000 /* SSE-300 Secure Access Configuration Register Secure base address */ +#define MPC_ISRAM0_BASE_S 0x50083000 /* Internal SRAM0 Memory Protection Controller Secure base address */ +#define MPC_ISRAM1_BASE_S 0x50084000 /* Internal SRAM1 Memory Protection Controller Secure base address */ +/* Secure MSTEXPPILL Peripheral region */ +#define GPIO0_CMSDK_BASE_S 0x51100000 /* GPIO 0 Secure base address */ +#define GPIO1_CMSDK_BASE_S 0x51101000 /* GPIO 1 Secure base address */ +#define GPIO2_CMSDK_BASE_S 0x51102000 /* GPIO 2 Secure base address */ +#define GPIO3_CMSDK_BASE_S 0x51103000 /* GPIO 3 Secure base address */ +#define AHB_USER_0_BASE_S 0x51104000 /* AHB USER 0 Secure base address */ +#define AHB_USER_1_BASE_S 0x51105000 /* AHB USER 1 Secure base address */ +#define AHB_USER_2_BASE_S 0x51106000 /* AHB USER 2 Secure base address */ +#define AHB_USER_3_BASE_S 0x51107000 /* AHB USER 3 Secure base address */ +#define DMA_0_BASE_S 0x51200000 /* DMA 0 Secure base address */ +#define DMA_1_BASE_S 0x51201000 /* DMA 1 Secure base address */ +#define DMA_2_BASE_S 0x51202000 /* DMA 2 Secure base address */ +#define DMA_3_BASE_S 0x51203000 /* DMA 3 Secure base address */ +#define ETHERNET_BASE_S 0x51400000 /* Ethernet Secure base address */ +#define USB_BASE_S 0x51500000 /* USB Secure base address */ +#define USER_APB0_BASE_S 0x51700000 /* User APB 0 Secure base address */ +#define USER_APB1_BASE_S 0x51701000 /* User APB 1 Secure base address */ +#define USER_APB2_BASE_S 0x51702000 /* User APB 2 Secure base address */ +#define USER_APB3_BASE_S 0x51703000 /* User APB 3 Secure base address */ +#define QSPI_CONFIG_BASE_S 0x51800000 /* QSPI Config Secure base address */ +#define QSPI_WRITE_BASE_S 0x51801000 /* QSPI Write Secure base address */ +#define MPC_SRAM_BASE_S 0x57000000 /* SRAM Memory Protection Controller Secure base address */ +#define MPC_QSPI_BASE_S 0x57001000 /* QSPI Memory Protection Controller Secure base address */ +#define MPC_DDR4_BASE_S 0x57002000 /* DDR4 Memory Protection Controller Secure base address */ +/* Secure Subsystem peripheral region */ +#define SYSTIMER0_ARMV8_M_BASE_S 0x58000000 /* System Timer 0 Secure base address */ +#define SYSTIMER1_ARMV8_M_BASE_S 0x58001000 /* System Timer 1 Secure base address */ +#define SYSTIMER2_ARMV8_M_BASE_S 0x58002000 /* System Timer 0 Secure base address */ +#define SYSTIMER3_ARMV8_M_BASE_S 0x58003000 /* System Timer 1 Secure base address */ +#define SSE300_SYSINFO_BASE_S 0x58020000 /* SSE-300 System info Block Secure base address */ +#define SSE300_SYSCTRL_BASE_S 0x58021000 /* SSE-300 System control Block Secure base address */ +#define SSE300_SYSPPU_BASE_S 0x58022000 /* SSE-300 System Power Policy Unit Secure base address */ +#define SSE300_CPU0PPU_BASE_S 0x58023000 /* SSE-300 CPU 0 Power Policy Unit Secure base address */ +#define SSE300_MGMTPPU_BASE_S 0x58028000 /* SSE-300 Management Power Policy Unit Secure base address */ +#define SSE300_DBGPPU_BASE_S 0x58029000 /* SSE-300 Debug Power Policy Unit Secure base address */ +#define SLOWCLK_WDOG_CMSDK_BASE_S 0x5802E000 /* CMSDK based SLOWCLK Watchdog Secure base address */ +#define SLOWCLK_TIMER_CMSDK_BASE_S 0x5802F000 /* CMSDK based SLOWCLK Timer Secure base address */ +#define SYSWDOG_ARMV8_M_CNTRL_BASE_S 0x58040000 /* Secure Watchdog Timer control frame Secure base address */ +#define SYSWDOG_ARMV8_M_REFRESH_BASE_S 0x58041000 /* Secure Watchdog Timer refresh frame Secure base address */ +#define SYSCNTR_CNTRL_BASE_S 0x58100000 /* System Counter Control Secure base address */ +#define SYSCNTR_READ_BASE_S 0x58101000 /* System Counter Read Secure base address */ +/* Secure MSTEXPPIHL Peripheral region */ +#define ETHOS_U55_APB_BASE_S 0x58102000 /* Ethos-U55 APB Secure base address */ +#define U55_TIMING_ADAPTER_0_BASE_S 0x58103000 /* Ethos-U55 Timing Adapter 0 APB registers Secure base address */ +#define U55_TIMING_ADAPTER_1_BASE_S 0x58103200 /* Ethos-U55 Timing Adapter 1 APB registers Secure base address */ +#define FPGA_SBCon_I2C_TOUCH_BASE_S 0x59200000 /* FPGA - SBCon I2C (Touch) Secure base address */ +#define FPGA_SBCon_I2C_AUDIO_BASE_S 0x59201000 /* FPGA - SBCon I2C (Audio Conf) Secure base address */ +#define FPGA_SPI_ADC_BASE_S 0x59202000 /* FPGA - PL022 (SPI ADC) Secure base address */ +#define FPGA_SPI_SHIELD0_BASE_S 0x59203000 /* FPGA - PL022 (SPI Shield0) Secure base address */ +#define FPGA_SPI_SHIELD1_BASE_S 0x59204000 /* FPGA - PL022 (SPI Shield1) Secure base address */ +#define SBCon_I2C_SHIELD0_BASE_S 0x59205000 /* SBCon (I2C - Shield0) Secure base address */ +#define SBCon_I2C_SHIELD1_BASE_S 0x59206000 /* SBCon (I2C – Shield1) Secure base address */ +#define USER_APB_BASE_S 0x59207000 /* USER APB Secure base address */ +#define FPGA_DDR4_EEPROM_BASE_S 0x59208000 /* FPGA - SBCon I2C (DDR4 EEPROM) Secure base address */ +#define FPGA_SCC_BASE_S 0x59300000 /* FPGA - SCC registers Secure base address */ +#define FPGA_I2S_BASE_S 0x59301000 /* FPGA - I2S (Audio) Secure base address */ +#define FPGA_IO_BASE_S 0x59302000 /* FPGA - IO (System Ctrl + I/O) Secure base address */ +#define UART0_BASE_S 0x59303000 /* UART 0 Secure base address */ +#define UART1_BASE_S 0x59304000 /* UART 1 Secure base address */ +#define UART2_BASE_S 0x59305000 /* UART 2 Secure base address */ +#define UART3_BASE_S 0x59306000 /* UART 3 Secure base address */ +#define UART4_BASE_S 0x59307000 /* UART 4 Secure base address */ +#define UART5_BASE_S 0x59308000 /* UART 5 Secure base address */ +#define CLCD_Config_Reg_BASE_S 0x5930A000 /* CLCD Config Reg Secure base address */ +#define RTC_BASE_S 0x5930B000 /* RTC Secure base address */ +#define DDR4_BLK1_BASE_S 0x70000000 /* DDR4 block 1 Secure base address */ +#define DDR4_BLK3_BASE_S 0x90000000 /* DDR4 block 3 Secure base address */ +#define DDR4_BLK5_BASE_S 0xB0000000 /* DDR4 block 5 Secure base address */ +#define DDR4_BLK7_BASE_S 0xD0000000 /* DDR4 block 7 Secure base address */ + +/* Memory map addresses exempt from memory attribution by both the SAU and IDAU */ +#define SSE300_EWIC_BASE 0xE0047000 /* External Wakeup Interrupt Controller + * Access from Non-secure software is only allowed + * if AIRCR.BFHFNMINS is set to 1 */ + +/* Memory size definitions */ +#define ITCM_SIZE (0x00080000) /* 512 kB */ +#define DTCM_BLK_SIZE (0x00020000) /* 128 kB */ +#define DTCM_BLK_NUM (0x4) /* Number of DTCM blocks */ +#define SRAM_SIZE (0x00200000) /* 2 MB */ +#define ISRAM0_SIZE (0x00200000) /* 2 MB */ +#define ISRAM1_SIZE (0x00200000) /* 2 MB */ +#define QSPI_SRAM_SIZE (0x00800000) /* 8 MB */ +#define DDR4_BLK_SIZE (0x10000000) /* 256 MB */ +#define DDR4_BLK_NUM (0x8) /* Number of DDR4 blocks */ + +/* Defines for Driver MPC's */ +/* SRAM -- 2 MB */ +#define MPC_SRAM_RANGE_BASE_NS (SRAM_BASE_NS) +#define MPC_SRAM_RANGE_LIMIT_NS (SRAM_BASE_NS + SRAM_SIZE-1) +#define MPC_SRAM_RANGE_OFFSET_NS (0x0) +#define MPC_SRAM_RANGE_BASE_S (SRAM_BASE_S) +#define MPC_SRAM_RANGE_LIMIT_S (SRAM_BASE_S + SRAM_SIZE-1) +#define MPC_SRAM_RANGE_OFFSET_S (0x0) + +/* QSPI -- 8 MB*/ +#define MPC_QSPI_RANGE_BASE_NS (QSPI_SRAM_BASE_NS) +#define MPC_QSPI_RANGE_LIMIT_NS (QSPI_SRAM_BASE_NS + QSPI_SRAM_SIZE-1) +#define MPC_QSPI_RANGE_OFFSET_NS (0x0) +#define MPC_QSPI_RANGE_BASE_S (QSPI_SRAM_BASE_S) +#define MPC_QSPI_RANGE_LIMIT_S (QSPI_SRAM_BASE_S + QSPI_SRAM_SIZE-1) +#define MPC_QSPI_RANGE_OFFSET_S (0x0) + +/* ISRAM0 -- 2 MB*/ +#define MPC_ISRAM0_RANGE_BASE_NS (ISRAM0_BASE_NS) +#define MPC_ISRAM0_RANGE_LIMIT_NS (ISRAM0_BASE_NS + ISRAM0_SIZE-1) +#define MPC_ISRAM0_RANGE_OFFSET_NS (0x0) +#define MPC_ISRAM0_RANGE_BASE_S (ISRAM0_BASE_S) +#define MPC_ISRAM0_RANGE_LIMIT_S (ISRAM0_BASE_S + ISRAM0_SIZE-1) +#define MPC_ISRAM0_RANGE_OFFSET_S (0x0) + +/* ISRAM1 -- 2 MB*/ +#define MPC_ISRAM1_RANGE_BASE_NS (ISRAM1_BASE_NS) +#define MPC_ISRAM1_RANGE_LIMIT_NS (ISRAM1_BASE_NS + ISRAM1_SIZE-1) +#define MPC_ISRAM1_RANGE_OFFSET_NS (0x0) +#define MPC_ISRAM1_RANGE_BASE_S (ISRAM1_BASE_S) +#define MPC_ISRAM1_RANGE_LIMIT_S (ISRAM1_BASE_S + ISRAM1_SIZE-1) +#define MPC_ISRAM1_RANGE_OFFSET_S (0x0) + +/* DDR4 -- 2GB (8 * 256 MB) */ +#define MPC_DDR4_BLK0_RANGE_BASE_NS (DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK0_RANGE_LIMIT_NS (DDR4_BLK0_BASE_NS + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK0_RANGE_OFFSET_NS (0x0) +#define MPC_DDR4_BLK1_RANGE_BASE_S (DDR4_BLK1_BASE_S) +#define MPC_DDR4_BLK1_RANGE_LIMIT_S (DDR4_BLK1_BASE_S + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK1_RANGE_OFFSET_S (DDR4_BLK1_BASE_S - DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK2_RANGE_BASE_NS (DDR4_BLK2_BASE_NS) +#define MPC_DDR4_BLK2_RANGE_LIMIT_NS (DDR4_BLK2_BASE_NS + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK2_RANGE_OFFSET_NS (DDR4_BLK2_BASE_NS - DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK3_RANGE_BASE_S (DDR4_BLK3_BASE_S) +#define MPC_DDR4_BLK3_RANGE_LIMIT_S (DDR4_BLK3_BASE_S + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK3_RANGE_OFFSET_S (DDR4_BLK3_BASE_S - DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK4_RANGE_BASE_NS (DDR4_BLK4_BASE_NS) +#define MPC_DDR4_BLK4_RANGE_LIMIT_NS (DDR4_BLK4_BASE_NS + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK4_RANGE_OFFSET_NS (DDR4_BLK4_BASE_NS - DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK5_RANGE_BASE_S (DDR4_BLK5_BASE_S) +#define MPC_DDR4_BLK5_RANGE_LIMIT_S (DDR4_BLK5_BASE_S + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK5_RANGE_OFFSET_S (DDR4_BLK5_BASE_S - DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK6_RANGE_BASE_NS (DDR4_BLK6_BASE_NS) +#define MPC_DDR4_BLK6_RANGE_LIMIT_NS (DDR4_BLK6_BASE_NS + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK6_RANGE_OFFSET_NS (DDR4_BLK6_BASE_NS - DDR4_BLK0_BASE_NS) +#define MPC_DDR4_BLK7_RANGE_BASE_S (DDR4_BLK7_BASE_S) +#define MPC_DDR4_BLK7_RANGE_LIMIT_S (DDR4_BLK7_BASE_S + ((DDR4_BLK_SIZE)-1)) +#define MPC_DDR4_BLK7_RANGE_OFFSET_S (DDR4_BLK7_BASE_S - DDR4_BLK0_BASE_NS) + +#endif /* __PLATFORM_BASE_ADDRESS_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/partition/region_defs.h b/bsp/tf_m_targets/arm/mps3/an547/partition/region_defs.h new file mode 100644 index 0000000..568d227 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/partition/region_defs.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REGION_DEFS_H__ +#define __REGION_DEFS_H__ + +#include "flash_layout.h" +#include "platform_base_address.h" + +#define BL2_HEAP_SIZE (0x0001000) +#define BL2_MSP_STACK_SIZE (0x0001800) + +#define S_HEAP_SIZE (0x0001000) +#define S_MSP_STACK_SIZE_INIT (0x0000400) +#define S_MSP_STACK_SIZE (0x0000800) +#define S_PSP_STACK_SIZE (0x0000800) + +#define NS_HEAP_SIZE (0x0008000) +#define NS_MSP_STACK_SIZE (0x0000800) +#define NS_PSP_STACK_SIZE (0x0002000) + +/* This size of buffer is big enough to store an attestation + * token produced by initial attestation service + */ +#define PSA_INITIAL_ATTEST_TOKEN_MAX_SIZE (0x250) + +#ifdef BL2 +#ifndef LINK_TO_SECONDARY_PARTITION +#define S_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET) +#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET) +#else +#define S_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET) +#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET) +#endif /* !LINK_TO_SECONDARY_PARTITION */ +#else +#define S_IMAGE_PRIMARY_PARTITION_OFFSET (0x0) +#endif /* BL2 */ + +#ifndef LINK_TO_SECONDARY_PARTITION +#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET \ + + FLASH_S_PARTITION_SIZE) +#else +#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET \ + + FLASH_S_PARTITION_SIZE) +#endif /* !LINK_TO_SECONDARY_PARTITION */ + +/* Boot partition structure if MCUBoot is used: + * 0x0_0000 Bootloader header + * 0x0_0400 Image area + * 0x5_0000 Trailer + */ +/* IMAGE_CODE_SIZE is the space available for the software binary image. + * It is less than the FLASH_S_PARTITION_SIZE + FLASH_NS_PARTITION_SIZE + * because we reserve space for the image header and trailer introduced + * by the bootloader. + */ +#ifdef BL2 +#define BL2_HEADER_SIZE (0x400) /* 1 KB */ +#define BL2_TRAILER_SIZE (0x800) /* 2 KB */ +#else +/* No header if no bootloader, but keep IMAGE_CODE_SIZE the same */ +#define BL2_HEADER_SIZE (0x0) +#define BL2_TRAILER_SIZE (0xC00) +#endif /* BL2 */ + +#define IMAGE_S_CODE_SIZE \ + (FLASH_S_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) +#define IMAGE_NS_CODE_SIZE \ + (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) + +#define CMSE_VENEER_REGION_SIZE (0x340) + +/* Secure regions */ +#define S_IMAGE_PRIMARY_AREA_OFFSET \ + (S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +/* Secure Code stored in Code SRAM */ +#define S_CODE_START ((QSPI_SRAM_BASE_S) + (S_IMAGE_PRIMARY_AREA_OFFSET)) +#define S_CODE_SIZE (IMAGE_S_CODE_SIZE - CMSE_VENEER_REGION_SIZE) +#define S_CODE_LIMIT (S_CODE_START + S_CODE_SIZE - 1) + +/* Secure Data stored in DTCM */ +#define S_DATA_START (DTCM0_BASE_S) +#define S_DATA_SIZE (DTCM_BLK_SIZE * DTCM_BLK_NUM) +#define S_DATA_LIMIT (S_DATA_START + S_DATA_SIZE - 1) + +/* CMSE Veneers region */ +#define CMSE_VENEER_REGION_START (S_CODE_LIMIT + 1) + +/* Non-secure regions */ +#define NS_IMAGE_PRIMARY_AREA_OFFSET \ + (NS_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +/* Non-Secure Code stored in Code SRAM memory */ +#define NS_CODE_START (QSPI_SRAM_BASE_NS + (NS_IMAGE_PRIMARY_AREA_OFFSET)) +#define NS_CODE_SIZE (IMAGE_NS_CODE_SIZE) +#define NS_CODE_LIMIT (NS_CODE_START + NS_CODE_SIZE - 1) + +/* Non-Secure Data stored in ISRAM0 */ +#define NS_DATA_START (ISRAM0_BASE_NS) +#define NS_DATA_SIZE (ISRAM0_SIZE + ISRAM1_SIZE) +#define NS_DATA_LIMIT (NS_DATA_START + NS_DATA_SIZE - 1) + +/* NS partition information is used for MPC and SAU configuration */ +#define NS_PARTITION_START \ + ((QSPI_SRAM_BASE_NS) + (NS_IMAGE_PRIMARY_PARTITION_OFFSET)) +#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) + +/* Secondary partition for new images in case of firmware upgrade */ +#define SECONDARY_PARTITION_START \ + ((QSPI_SRAM_BASE_NS) + (S_IMAGE_SECONDARY_PARTITION_OFFSET)) +#define SECONDARY_PARTITION_SIZE (FLASH_S_PARTITION_SIZE + \ + FLASH_NS_PARTITION_SIZE) + +#ifdef BL2 +/* Bootloader regions */ +/* Use ITCM to store Bootloader */ +#define BL2_CODE_START (ITCM_BASE_S) +#define BL2_CODE_SIZE (ITCM_SIZE) +#define BL2_CODE_LIMIT (BL2_CODE_START + BL2_CODE_SIZE - 1) + +/* Bootloader uses same memory as for secure image */ +#define BL2_DATA_START (S_DATA_START) +#define BL2_DATA_SIZE (S_DATA_SIZE) +#define BL2_DATA_LIMIT (BL2_DATA_START + BL2_DATA_SIZE - 1) +#endif /* BL2 */ + +/* Shared data area between bootloader and runtime firmware. + * Shared data area is allocated at the beginning of the RAM, it is overlapping + * with TF-M Secure code's MSP stack + */ +#define BOOT_TFM_SHARED_DATA_BASE S_DATA_START +#define BOOT_TFM_SHARED_DATA_SIZE (0x400) +#define BOOT_TFM_SHARED_DATA_LIMIT (BOOT_TFM_SHARED_DATA_BASE + \ + BOOT_TFM_SHARED_DATA_SIZE - 1) + +#endif /* __REGION_DEFS_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/plat_test.c b/bsp/tf_m_targets/arm/mps3/an547/plat_test.c new file mode 100644 index 0000000..12bd437 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/plat_test.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "platform_description.h" +#include "systimer_armv8-m_drv.h" +#include "syscounter_armv8-m_cntrl_drv.h" +#include "tfm_plat_test.h" +#include "device_definition.h" + +#define USERLED_MASK (0x3) +#define BTN_WAIT_INIT_COUNTER_VALUE (10000u) +#define TIMER_RELOAD_VALUE (SystemCoreClock) + +/** + * \brief Store the state of the mocked LED + * + * This variable have to be linked to the data section of the partition + * TFM_SP_CORE_TEST so that in case of in case of isolation within the secure + * domain the Core Test service can access it. + */ +uint32_t led_status + TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_SP_CORE_TEST", "PSA-ROT") + = 0x02u; + +/** + * \brief Simulate user reaction time + */ +static void busy_wait_to_simulate_user(void) +{ + volatile uint32_t counter = BTN_WAIT_INIT_COUNTER_VALUE; + + while (counter) { + --counter; + } +} + +void tfm_plat_test_wait_user_button_pressed(void) +{ + busy_wait_to_simulate_user(); +} + +void tfm_plat_test_wait_user_button_released(void) +{ + busy_wait_to_simulate_user(); +} + +uint32_t tfm_plat_test_get_led_status(void) +{ + return led_status; +} + +void tfm_plat_test_set_led_status(uint32_t status) +{ + led_status = status & USERLED_MASK; +} + +uint32_t tfm_plat_test_get_userled_mask(void) +{ + return USERLED_MASK; +} + +void tfm_plat_test_secure_timer_start(void) +{ + syscounter_armv8_m_cntrl_init(&SYSCOUNTER_CNTRL_ARMV8_M_DEV_S); + + systimer_armv8_m_init(&SYSTIMER0_ARMV8_M_DEV_S); + systimer_armv8_m_set_timer_value(&SYSTIMER0_ARMV8_M_DEV_S, TIMER_RELOAD_VALUE); + systimer_armv8_m_enable_interrupt(&SYSTIMER0_ARMV8_M_DEV_S); +} + +void tfm_plat_test_secure_timer_stop(void) +{ + systimer_armv8_m_uninit(&SYSTIMER0_ARMV8_M_DEV_S); + systimer_armv8_m_clear_autoinc_interrupt(&SYSTIMER0_ARMV8_M_DEV_S); +} + +void tfm_plat_test_non_secure_timer_start(void) +{ + systimer_armv8_m_init(&SYSTIMER1_ARMV8_M_DEV_NS); + systimer_armv8_m_set_timer_value(&SYSTIMER1_ARMV8_M_DEV_NS, TIMER_RELOAD_VALUE); + systimer_armv8_m_enable_interrupt(&SYSTIMER1_ARMV8_M_DEV_NS); +} + +void tfm_plat_test_non_secure_timer_stop(void) +{ + systimer_armv8_m_uninit(&SYSTIMER1_ARMV8_M_DEV_NS); + systimer_armv8_m_clear_autoinc_interrupt(&SYSTIMER1_ARMV8_M_DEV_NS); +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/preload.cmake b/bsp/tf_m_targets/arm/mps3/an547/preload.cmake new file mode 100644 index 0000000..ae27ca9 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/preload.cmake @@ -0,0 +1,16 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +# preload.cmake is used to set things that related to the platform that are both +# immutable and global, which is to say they should apply to any kind of project +# that uses this platform. In practise this is normally compiler definitions and +# variables related to hardware. + +# Set architecture and CPU +set(TFM_SYSTEM_PROCESSOR cortex-m55) +set(TFM_SYSTEM_ARCHITECTURE armv8.1-m.main) +set(TFM_SYSTEM_MVE OFF) diff --git a/bsp/tf_m_targets/arm/mps3/an547/services/src/tfm_platform_system.c b/bsp/tf_m_targets/arm/mps3/an547/services/src/tfm_platform_system.c new file mode 100644 index 0000000..df3aed7 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/services/src/tfm_platform_system.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_platform_system.h" +#include "target_cfg.h" +#include "cmsis.h" +#include "string.h" + +void tfm_platform_hal_system_reset(void) +{ + __disable_irq(); + mpc_revert_non_secure_to_secure_cfg(); + + /* Reset the system */ + NVIC_SystemReset(); +} + +enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *in_vec, + psa_outvec *out_vec) +{ + (void)request; + (void)in_vec; + (void)out_vec; + + /* Not needed for this platform */ + return TFM_PLATFORM_ERR_NOT_SUPPORTED; +} + diff --git a/bsp/tf_m_targets/arm/mps3/an547/spm_hal.c b/bsp/tf_m_targets/arm/mps3/an547/spm_hal.c new file mode 100644 index 0000000..dbdd20e --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/spm_hal.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2018-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "cmsis.h" +#include "tfm_spm_hal.h" +#include "tfm_platform_core_api.h" +#include "target_cfg.h" +#include "Driver_MPC.h" +#include "mpu_armv8m_drv.h" +#include "region_defs.h" +#include "utilities.h" +#include "region.h" + +/* Get address of memory regions to configure MPU */ +extern const struct memory_region_limits memory_regions; + +struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE }; + +#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT +#define PARTITION_REGION_PERIPH_START 5 +#define PARTITION_REGION_PERIPH_MAX_NUM 2 + +uint32_t periph_num_count = 0; +#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */ + +enum tfm_plat_err_t tfm_spm_hal_configure_default_isolation( + bool privileged, + const struct platform_data_t *platform_data) +{ +#if defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1) + struct mpu_armv8m_region_cfg_t region_cfg; +#endif + + if (!platform_data) { + return TFM_PLAT_ERR_INVALID_INPUT; + } + +#if defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1) + if (!privileged) { + region_cfg.region_nr = PARTITION_REGION_PERIPH_START + periph_num_count; + periph_num_count++; + if (periph_num_count >= PARTITION_REGION_PERIPH_MAX_NUM) { + return TFM_PLAT_ERR_MAX_VALUE; + } + region_cfg.region_base = platform_data->periph_start; + region_cfg.region_limit = platform_data->periph_limit; + region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX; + region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV; + region_cfg.attr_sh = MPU_ARMV8M_SH_NONE; + region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER; + + mpu_armv8m_disable(&dev_mpu_s); + + if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) + != MPU_ARMV8M_OK) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, + HARDFAULT_NMI_ENABLE); + } +#endif /* defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1) */ + + if (platform_data->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) { + ppc_configure_to_secure(platform_data->periph_ppc_bank, + platform_data->periph_ppc_mask); + } + return TFM_PLAT_ERR_SUCCESS; +} + +void MPC_Handler(void) +{ + /* Clear MPC interrupt flag and pending MPC IRQ */ + mpc_clear_irq(); + NVIC_ClearPendingIRQ(MPC_IRQn); + + /* Print fault message and block execution */ + ERROR_MSG("Oops... MPC fault!!!"); + + /* Inform TF-M core that isolation boundary has been violated */ + tfm_access_violation_handler(); +} + +void PPC_Handler(void) +{ + /* Clear PPC interrupt flag and pending PPC IRQ */ + ppc_clear_irq(); + NVIC_ClearPendingIRQ(PPC_IRQn); + + /* Print fault message*/ + ERROR_MSG("Oops... PPC fault!!!"); + + /* Inform TF-M core that isolation boundary has been violated */ + tfm_access_violation_handler(); +} + +uint32_t tfm_spm_hal_get_ns_VTOR(void) +{ + return memory_regions.non_secure_code_start; +} + +uint32_t tfm_spm_hal_get_ns_MSP(void) +{ + return *((uint32_t *)memory_regions.non_secure_code_start); +} + +uint32_t tfm_spm_hal_get_ns_entry_point(void) +{ + return *((uint32_t *)(memory_regions.non_secure_code_start+ 4)); +} + +enum tfm_plat_err_t tfm_spm_hal_set_secure_irq_priority(IRQn_Type irq_line) +{ + NVIC_SetPriority(irq_line, DEFAULT_IRQ_PRIORITY); + return TFM_PLAT_ERR_SUCCESS; +} + +void tfm_spm_hal_clear_pending_irq(IRQn_Type irq_line) +{ + NVIC_ClearPendingIRQ(irq_line); +} + +void tfm_spm_hal_enable_irq(IRQn_Type irq_line) +{ + NVIC_EnableIRQ(irq_line); +} + +void tfm_spm_hal_disable_irq(IRQn_Type irq_line) +{ + NVIC_DisableIRQ(irq_line); +} + +enum irq_target_state_t tfm_spm_hal_set_irq_target_state( + IRQn_Type irq_line, + enum irq_target_state_t target_state) +{ + uint32_t result; + + if (target_state == TFM_IRQ_TARGET_STATE_SECURE) { + result = NVIC_ClearTargetState(irq_line); + } else { + result = NVIC_SetTargetState(irq_line); + } + + if (result) { + return TFM_IRQ_TARGET_STATE_NON_SECURE; + } else { + return TFM_IRQ_TARGET_STATE_SECURE; + } +} + +enum tfm_plat_err_t tfm_spm_hal_enable_fault_handlers(void) +{ + return enable_fault_handlers(); +} + +enum tfm_plat_err_t tfm_spm_hal_system_reset_cfg(void) +{ + return system_reset_cfg(); +} + +enum tfm_plat_err_t tfm_spm_hal_init_debug(void) +{ + return init_debug(); +} + +enum tfm_plat_err_t tfm_spm_hal_nvic_interrupt_target_state_cfg(void) +{ + return nvic_interrupt_target_state_cfg(); +} + +enum tfm_plat_err_t tfm_spm_hal_nvic_interrupt_enable(void) +{ + return nvic_interrupt_enable(); +} + +void tfm_hal_system_reset(void) +{ + __disable_irq(); + mpc_revert_non_secure_to_secure_cfg(); + + NVIC_SystemReset(); +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/target_cfg.c b/bsp/tf_m_targets/arm/mps3/an547/target_cfg.c new file mode 100644 index 0000000..52ce574 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/target_cfg.c @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cmsis.h" +#include "utilities.h" +#include "target_cfg.h" +#include "Driver_SSE300_PPC.h" +#include "Driver_MPC.h" +#include "platform_description.h" +#include "region_defs.h" +#include "tfm_plat_defs.h" +#include "region.h" +#include "platform_base_address.h" + +/* Throw out bus error when an access causes security violation */ +#define CMSDK_SECRESPCFG_BUS_ERR_MASK (1UL << 0) + +/* The section names come from the scatter file */ +REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base); +REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Base); +REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Limit); +#ifdef BL2 +REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base); +#endif /* BL2 */ + +const struct memory_region_limits memory_regions = { + .non_secure_code_start = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + BL2_HEADER_SIZE, + + .non_secure_partition_base = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base), + + .non_secure_partition_limit = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + NS_PARTITION_SIZE - 1, + + .veneer_base = (uint32_t)®ION_NAME(Load$$LR$$, LR_VENEER, $$Base), + .veneer_limit = (uint32_t)®ION_NAME(Load$$LR$$, LR_VENEER, $$Limit), + +#ifdef BL2 + .secondary_partition_base = + (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base), + + .secondary_partition_limit = + (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) + + SECONDARY_PARTITION_SIZE - 1, +#endif /* BL2 */ +}; + +/* Configures the RAM region to NS callable in sacfg block's nsccfg register */ +#define RAMNSC 0x2 +/* Configures the CODE region to NS callable in sacfg block's nsccfg register */ +#define CODENSC 0x1 + +/* Import MPC drivers */ +extern ARM_DRIVER_MPC Driver_ISRAM0_MPC; +extern ARM_DRIVER_MPC Driver_ISRAM1_MPC; +extern ARM_DRIVER_MPC Driver_SRAM_MPC; +extern ARM_DRIVER_MPC Driver_QSPI_MPC; +extern ARM_DRIVER_MPC Driver_DDR4_MPC; + +/* Import PPC drivers */ +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN0; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP0; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP1; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP2; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_MAIN_EXP3; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH0; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH1; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP0; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP1; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP2; +extern DRIVER_PPC_SSE300 Driver_PPC_SSE300_PERIPH_EXP3; + +/* Define Peripherals NS address range for the platform */ +#define PERIPHERALS_BASE_NS_START (0x40000000) +#define PERIPHERALS_BASE_NS_END (0x4FFFFFFF) + +/* Enable system reset request for CPU 0 */ +#define ENABLE_CPU0_SYSTEM_RESET_REQUEST (1U << 8U) + +/* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field, + * otherwise the processor ignores the write. + */ +#define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)) + +/* Debug configuration flags */ +#define SPNIDEN_SEL_STATUS (0x01u << 7) +#define SPNIDEN_STATUS (0x01u << 6) +#define SPIDEN_SEL_STATUS (0x01u << 5) +#define SPIDEN_STATUS (0x01u << 4) +#define NIDEN_SEL_STATUS (0x01u << 3) +#define NIDEN_STATUS (0x01u << 2) +#define DBGEN_SEL_STATUS (0x01u << 1) +#define DBGEN_STATUS (0x01u << 0) + +#define All_SEL_STATUS (SPNIDEN_SEL_STATUS | SPIDEN_SEL_STATUS | \ + NIDEN_SEL_STATUS | DBGEN_SEL_STATUS) + +struct platform_data_t tfm_peripheral_std_uart = { + UART0_BASE_NS, + UART0_BASE_NS + 0xFFF, + PPC_SP_DO_NOT_CONFIGURE, + -1 +}; + +struct platform_data_t tfm_peripheral_fpga_io = { + FPGA_IO_BASE_S, + FPGA_IO_BASE_S + 0xFFF, + PPC_SP_PERIPH_EXP2, + FPGA_IO_PERIPH_PPCEXP2_POS_MASK +}; + +struct platform_data_t tfm_peripheral_timer0 = { + SYSTIMER0_ARMV8_M_BASE_S, + SYSTIMER0_ARMV8_M_BASE_S + 0xFFF, + PPC_SP_PERIPH0, + SYSTEM_TIMER0_PERIPH_PPC0_POS_MASK +}; + +static DRIVER_PPC_SSE300 *const ppc_bank_drivers[] = { + &Driver_PPC_SSE300_MAIN0, + &Driver_PPC_SSE300_MAIN_EXP0, + &Driver_PPC_SSE300_MAIN_EXP1, + &Driver_PPC_SSE300_MAIN_EXP2, + &Driver_PPC_SSE300_MAIN_EXP3, + &Driver_PPC_SSE300_PERIPH0, + &Driver_PPC_SSE300_PERIPH1, + &Driver_PPC_SSE300_PERIPH_EXP0, + &Driver_PPC_SSE300_PERIPH_EXP1, + &Driver_PPC_SSE300_PERIPH_EXP2, + &Driver_PPC_SSE300_PERIPH_EXP3, +}; + +#define PPC_BANK_COUNT (sizeof(ppc_bank_drivers)/sizeof(ppc_bank_drivers[0])) + +enum tfm_plat_err_t enable_fault_handlers(void) +{ + /* Explicitly set secure fault priority to the highest */ + NVIC_SetPriority(SecureFault_IRQn, 0); + + /* Enables BUS, MEM, USG and Secure faults */ + SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk + | SCB_SHCSR_BUSFAULTENA_Msk + | SCB_SHCSR_MEMFAULTENA_Msk + | SCB_SHCSR_SECUREFAULTENA_Msk; + return TFM_PLAT_ERR_SUCCESS; +} + +enum tfm_plat_err_t system_reset_cfg(void) +{ + struct sse300_sysctrl_t *sysctrl = + (struct sse300_sysctrl_t *)SSE300_SYSCTRL_BASE_S; + uint32_t reg_value = SCB->AIRCR; + + /* Enable system reset request for CPU 0, to be triggered via + * NVIC_SystemReset function. + */ + sysctrl->reset_mask |= ENABLE_CPU0_SYSTEM_RESET_REQUEST; + + /* Clear SCB_AIRCR_VECTKEY value */ + reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk); + + /* Enable system reset request only to the secure world */ + reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk); + + SCB->AIRCR = reg_value; + + return TFM_PLAT_ERR_SUCCESS; +} + +/*--------------------- NVIC interrupt NS/S configuration --------------------*/ +enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void) +{ + uint8_t i; + + /* Target every interrupt to NS; unimplemented interrupts will be WI */ + for (i = 0; i < (sizeof(NVIC->ITNS) / sizeof(NVIC->ITNS[0])); i++) { + NVIC->ITNS[i] = 0xFFFFFFFF; + } + + /* Make sure that MPC and PPC are targeted to S state */ + NVIC_ClearTargetState(MPC_IRQn); + NVIC_ClearTargetState(PPC_IRQn); + +#ifdef SECURE_UART1 + /* UART1 is a secure peripheral, so its IRQs have to target S state */ + NVIC_ClearTargetState(UARTRX1_IRQn); + NVIC_ClearTargetState(UARTTX1_IRQn); +#endif + + return TFM_PLAT_ERR_SUCCESS; +} + +/*----------------- NVIC interrupt enabling for S peripherals ----------------*/ +enum tfm_plat_err_t nvic_interrupt_enable(void) +{ + int32_t ret = ARM_DRIVER_OK; + int32_t i = 0; + + /* MPC interrupt enabling */ + mpc_clear_irq(); + ret = Driver_ISRAM0_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Enable MPC interrupt for ISRAM0!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_ISRAM1_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Enable MPC interrupt for ISRAM1!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + ret = Driver_DDR4_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Enable MPC interrupt for DDR4!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + ret = Driver_SRAM_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Enable MPC interrupt for SRAM!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + ret = Driver_QSPI_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Enable MPC interrupt for QSPI!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + NVIC_ClearPendingIRQ(MPC_IRQn); + NVIC_EnableIRQ(MPC_IRQn); + + /* PPC interrupt enabling */ + ppc_clear_irq(); + + for (i = 0; i < PPC_BANK_COUNT; i++) { + ret = ppc_bank_drivers[i]->EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Enable interrupt on PPC"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + } + + NVIC_ClearPendingIRQ(PPC_IRQn); + NVIC_EnableIRQ(PPC_IRQn); + +#ifdef PSA_FF_TEST_SECURE_UART2 + NVIC_EnableIRQ(FF_TEST_UART_IRQ); +#endif + return TFM_PLAT_ERR_SUCCESS; +} + +enum tfm_plat_err_t init_debug(void) +{ + struct sse300_sysctrl_t *sysctrl = + (struct sse300_sysctrl_t *)SSE300_SYSCTRL_BASE_S; + +#if defined(DAUTH_NONE) + /* Set all the debug enable selector bits to 1 */ + sysctrl->secdbgset = All_SEL_STATUS; + /* Set all the debug enable bits to 0 */ + sysctrl->secdbgclr = + DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS; +#elif defined(DAUTH_NS_ONLY) + /* Set all the debug enable selector bits to 1 */ + sysctrl->secdbgset = All_SEL_STATUS; + /* Set the debug enable bits to 1 for NS, and 0 for S mode */ + sysctrl->secdbgset = DBGEN_STATUS | NIDEN_STATUS; + sysctrl->secdbgclr = SPIDEN_STATUS | SPNIDEN_STATUS; +#elif defined(DAUTH_FULL) + /* Set all the debug enable selector bits to 1 */ + sysctrl->secdbgset = All_SEL_STATUS; + /* Set all the debug enable bits to 1 */ + sysctrl->secdbgset = + DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS; +#else + +#if !defined(DAUTH_CHIP_DEFAULT) +#error "No debug authentication setting is provided." +#endif + + /* Set all the debug enable selector bits to 0 */ + sysctrl->secdbgclr = All_SEL_STATUS; + + /* No need to set any enable bits because the value depends on + * input signals. + */ +#endif + return TFM_PLAT_ERR_SUCCESS; +} + +/*------------------- SAU/IDAU configuration functions -----------------------*/ +void sau_and_idau_cfg(void) +{ + struct sse300_sacfg_t *sacfg = (struct sse300_sacfg_t*)SSE300_SACFG_BASE_S; + + /* Enables SAU */ + TZ_SAU_Enable(); + + /* Configures SAU regions to be non-secure */ + SAU->RNR = 0; + SAU->RBAR = (ISRAM0_BASE_NS & SAU_RBAR_BADDR_Msk); + SAU->RLAR = ((ISRAM0_BASE_NS + ISRAM0_SIZE + ISRAM1_SIZE - 1) & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + /* Configures SAU regions to be non-secure */ + SAU->RNR = 1; + SAU->RBAR = (memory_regions.non_secure_partition_base + & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (memory_regions.non_secure_partition_limit + & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + /* Configures veneers region to be non-secure callable */ + SAU->RNR = 2; + SAU->RBAR = (memory_regions.veneer_base & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (memory_regions.veneer_limit & SAU_RLAR_LADDR_Msk) + | SAU_RLAR_ENABLE_Msk | SAU_RLAR_NSC_Msk; + + /* Configure the peripherals space */ + SAU->RNR = 3; + SAU->RBAR = (PERIPHERALS_BASE_NS_START & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (PERIPHERALS_BASE_NS_END & SAU_RLAR_LADDR_Msk) + | SAU_RLAR_ENABLE_Msk; + + /* Secondary image partition */ + SAU->RNR = 4; + SAU->RBAR = (memory_regions.secondary_partition_base + & SAU_RBAR_BADDR_Msk); + SAU->RLAR = (memory_regions.secondary_partition_limit + & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + /* steal data memory from QSPI end */ + SAU->RNR = 5; + SAU->RBAR = (0x28700000 & SAU_RBAR_BADDR_Msk); + SAU->RLAR = ((0x28800000 - 1) + & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + SAU->RNR = 6; + SAU->RBAR = (DDR4_BLK0_BASE_NS & SAU_RBAR_BADDR_Msk); + SAU->RLAR = ((DDR4_BLK0_BASE_NS + DDR4_BLK_SIZE - 1) + & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + SAU->RNR = 7; + SAU->RBAR = (DDR4_BLK2_BASE_NS & SAU_RBAR_BADDR_Msk); + SAU->RLAR = ((DDR4_BLK2_BASE_NS + DDR4_BLK_SIZE - 1) + & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk; + + + + /* Allows SAU to define the CODE region as a NSC */ + sacfg->nsccfg |= RAMNSC; +} + +/*------------------- Memory configuration functions -------------------------*/ +enum tfm_plat_err_t mpc_init_cfg(void) +{ + int32_t ret = ARM_DRIVER_OK; + + /* ISRAM0 is allocated for NS data, so whole range is set to non-secure + * accesible. */ + ret = Driver_ISRAM0_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Initialize MPC for ISRAM0!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_ISRAM0_MPC.ConfigRegion(ISRAM0_BASE_NS, + ISRAM0_BASE_NS + ISRAM0_SIZE - 1, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for ISRAM0!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + ret = Driver_ISRAM1_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Initialize MPC for ISRAM1!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_ISRAM1_MPC.ConfigRegion(ISRAM1_BASE_NS, + ISRAM1_BASE_NS + ISRAM1_SIZE - 1, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for ISRAM1!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + ret = Driver_SRAM_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Initialize MPC for SRAM!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_SRAM_MPC.ConfigRegion(MPC_SRAM_RANGE_BASE_NS, + MPC_SRAM_RANGE_LIMIT_NS, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for SRAM!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + /* Configuring primary and secondary non-secure partition. + * It is ensured in flash_layout.h that these memory regions are located in + * SRAM SRAM device. */ + ret = Driver_QSPI_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Initialize MPC for QSPI!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_QSPI_MPC.ConfigRegion( + memory_regions.non_secure_partition_base, + memory_regions.non_secure_partition_limit, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for QSPI!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_QSPI_MPC.ConfigRegion( + 0x28700000, /* steal data memory from QSPI end */ + 0x28800000-1, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for QSPI!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + ret = Driver_DDR4_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Initialize MPC for DDR4!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_DDR4_MPC.ConfigRegion(DDR4_BLK0_BASE_NS, + DDR4_BLK0_BASE_NS + DDR4_BLK_SIZE - 1, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for DDR4!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + /* second init just like memtest */ + ret = Driver_DDR4_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Initialize MPC for DDR4!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_DDR4_MPC.ConfigRegion(DDR4_BLK2_BASE_NS, + DDR4_BLK2_BASE_NS + DDR4_BLK_SIZE - 1, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + ERROR_MSG("Failed to Configure MPC for DDR4!"); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + /* Lock down not used MPC's */ + //Driver_QSPI_MPC.LockDown(); + //Driver_ISRAM1_MPC.LockDown(); + + /* SRAM and ISRAM0 MPCs left unlocked as they are not reset if NVIC system + * reset asserted. + */ + + /* Add barriers to assure the MPC configuration is done before continue + * the execution. + */ + __DSB(); + __ISB(); + + return TFM_PLAT_ERR_SUCCESS; +} + +void mpc_revert_non_secure_to_secure_cfg(void) +{ + Driver_ISRAM0_MPC.ConfigRegion(ISRAM0_BASE_NS, + ISRAM1_SIZE, + ARM_MPC_ATTR_SECURE); + + Driver_ISRAM1_MPC.ConfigRegion(ISRAM1_BASE_NS, + ISRAM1_SIZE, + ARM_MPC_ATTR_SECURE); + + Driver_DDR4_MPC.ConfigRegion(DDR4_BLK0_BASE_NS, + DDR4_BLK0_BASE_NS + DDR4_BLK_SIZE - 1, + ARM_MPC_ATTR_SECURE); + + Driver_QSPI_MPC.ConfigRegion(MPC_QSPI_RANGE_BASE_S, + MPC_QSPI_RANGE_LIMIT_S, + ARM_MPC_ATTR_SECURE); + + /* Add barriers to assure the MPC configuration is done before continue + * the execution. + */ + __DSB(); + __ISB(); +} + +void mpc_clear_irq(void) +{ + Driver_ISRAM0_MPC.ClearInterrupt(); + Driver_ISRAM1_MPC.ClearInterrupt(); + Driver_SRAM_MPC.ClearInterrupt(); + Driver_QSPI_MPC.ClearInterrupt(); + Driver_DDR4_MPC.ClearInterrupt(); +} + +/*------------------- PPC configuration functions -------------------------*/ +enum tfm_plat_err_t ppc_init_cfg(void) +{ + struct sse300_sacfg_t *sacfg = + (struct sse300_sacfg_t*)SSE300_SACFG_BASE_S; + int32_t err = ARM_DRIVER_OK; + + /* Grant non-secure access to peripherals on MAIN EXP0 */ + err |= Driver_PPC_SSE300_MAIN_EXP0.Initialize(); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + GPIO0_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + GPIO1_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + GPIO2_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + GPIO3_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + USER_AHB0_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + USER_AHB1_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + USER_AHB2_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + USER_AHB3_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + err |= Driver_PPC_SSE300_MAIN_EXP0.ConfigSecurity( + USB_AND_ETHERNET_MAIN_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + /* Grant non-secure access to peripherals on MAIN EXP1 */ + err |= Driver_PPC_SSE300_MAIN_EXP1.Initialize(); + err |= Driver_PPC_SSE300_MAIN_EXP1.ConfigSecurity( + DMA1_MAIN_PPCEXP1_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP1.ConfigSecurity( + DMA2_MAIN_PPCEXP1_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_MAIN_EXP1.ConfigSecurity( + DMA3_MAIN_PPCEXP1_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + /* Grant non-secure access to peripherals on PERIPH0 */ + err |= Driver_PPC_SSE300_PERIPH0.Initialize(); + err |= Driver_PPC_SSE300_PERIPH0.ConfigSecurity( + SYSTEM_TIMER0_PERIPH_PPC0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH0.ConfigSecurity( + SYSTEM_TIMER1_PERIPH_PPC0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH0.ConfigSecurity( + SYSTEM_TIMER2_PERIPH_PPC0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH0.ConfigSecurity( + SYSTEM_TIMER3_PERIPH_PPC0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH0.ConfigSecurity( + WATCHDOG_PERIPH_PPC0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + /* Grant non-secure access to peripherals on PERIPH1 */ + err |= Driver_PPC_SSE300_PERIPH1.Initialize(); + err |= Driver_PPC_SSE300_PERIPH1.ConfigSecurity( + SLOWCLK_TIMER_PERIPH_PPC1_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + /* Grant non-secure access to peripherals on PERIPH EXP0 */ + err |= Driver_PPC_SSE300_PERIPH_EXP0.Initialize(); + + err |= Driver_PPC_SSE300_PERIPH_EXP0.ConfigSecurity( + NPU_APB0_PERIPH_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP0.ConfigSecurity( + NPU_APB1_PERIPH_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + err |= Driver_PPC_SSE300_PERIPH_EXP0.ConfigSecurity( + USER_MEM_APB0_PERIPH_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP0.ConfigSecurity( + USER_MEM_APB1_PERIPH_PPCEXP0_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + /* Grant non-secure access to peripherals on PERIPH EXP2 */ + err |= Driver_PPC_SSE300_PERIPH_EXP2.Initialize(); + + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + FPGA_I2S_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + FPGA_IO_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + UART0_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + UART1_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + UART2_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + UART3_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + UART4_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + UART5_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + CLCD_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigSecurity( + VSI_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG); + + /* Grant un-privileged access for UART0 in NS domain */ + err |= Driver_PPC_SSE300_PERIPH_EXP2.ConfigPrivilege( + UART0_PERIPH_PPCEXP2_POS_MASK, + PPC_SSE300_NONSECURE_CONFIG, + PPC_SSE300_PRIV_AND_NONPRIV_CONFIG); + + /* Initialize not used PPC drivers */ + err |= Driver_PPC_SSE300_MAIN0.Initialize(); + err |= Driver_PPC_SSE300_MAIN_EXP2.Initialize(); + err |= Driver_PPC_SSE300_MAIN_EXP3.Initialize(); + err |= Driver_PPC_SSE300_PERIPH_EXP1.Initialize(); + err |= Driver_PPC_SSE300_PERIPH_EXP3.Initialize(); + + /* + * Configure the response to a security violation as a + * bus error instead of RAZ/WI + */ + sacfg->secrespcfg |= CMSDK_SECRESPCFG_BUS_ERR_MASK; + + if (err != ARM_DRIVER_OK) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + return TFM_PLAT_ERR_SUCCESS; +} + +void ppc_configure_to_secure(enum ppc_bank_e bank, uint32_t pos) +{ + DRIVER_PPC_SSE300 *ppc_driver; + + if (bank >= PPC_BANK_COUNT) { + return; + } + + ppc_driver = ppc_bank_drivers[bank]; + if (ppc_driver) { + ppc_driver->ConfigSecurity(pos, PPC_SSE300_SECURE_CONFIG); + } +} + +void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint32_t pos) +{ + DRIVER_PPC_SSE300 *ppc_driver; + + if (bank >= PPC_BANK_COUNT) { + return; + } + + ppc_driver = ppc_bank_drivers[bank]; + if (ppc_driver) { + ppc_driver->ConfigSecurity(pos, PPC_SSE300_NONSECURE_CONFIG); + } +} + +void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint32_t pos) +{ + DRIVER_PPC_SSE300 *ppc_driver; + + if (bank >= PPC_BANK_COUNT) { + return; + } + + ppc_driver = ppc_bank_drivers[bank]; + if (ppc_driver) { + ppc_driver->ConfigPrivilege(pos, + PPC_SSE300_SECURE_CONFIG, + PPC_SSE300_PRIV_AND_NONPRIV_CONFIG); + } +} + +void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint32_t pos) +{ + DRIVER_PPC_SSE300 *ppc_driver; + + if (bank >= PPC_BANK_COUNT) { + return; + } + + ppc_driver = ppc_bank_drivers[bank]; + if (ppc_driver) { + ppc_driver->ConfigPrivilege(pos, + PPC_SSE300_SECURE_CONFIG, + PPC_SSE300_PRIV_CONFIG); + } +} + +void ppc_clear_irq(void) +{ + int32_t i = 0; + + for (i = 0; i < PPC_BANK_COUNT; i++) { + ppc_bank_drivers[i]->ClearInterrupt(); + } +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/target_cfg.h b/bsp/tf_m_targets/arm/mps3/an547/target_cfg.h new file mode 100644 index 0000000..8e0f0af --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/target_cfg.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TARGET_CFG_H__ +#define __TARGET_CFG_H__ + +#include +#include "tfm_peripherals_def.h" +#include "tfm_plat_defs.h" + +#define TFM_DRIVER_STDIO Driver_USART0 +#define NS_DRIVER_STDIO Driver_USART0 + +/** + * \brief Defines the word offsets of Slave Peripheral Protection Controller + * Registers + */ +enum ppc_bank_e +{ + PPC_SP_DO_NOT_CONFIGURE = -1, + PPC_SP_MAIN0 = 0, + PPC_SP_MAIN_EXP0 = 1, + PPC_SP_MAIN_EXP1 = 2, + PPC_SP_MAIN_EXP2 = 3, + PPC_SP_MAIN_EXP3 = 4, + PPC_SP_PERIPH0 = 5, + PPC_SP_PERIPH1 = 6, + PPC_SP_PERIPH_EXP0 = 7, + PPC_SP_PERIPH_EXP1 = 8, + PPC_SP_PERIPH_EXP2 = 9, + PPC_SP_PERIPH_EXP3 = 10, +}; + +/** + * \brief Store the addresses of memory regions + */ +struct memory_region_limits { + uint32_t non_secure_code_start; + uint32_t non_secure_partition_base; + uint32_t non_secure_partition_limit; + uint32_t veneer_base; + uint32_t veneer_limit; +#ifdef BL2 + uint32_t secondary_partition_base; + uint32_t secondary_partition_limit; +#endif /* BL2 */ +}; + +/** + * \brief Holds the data necessary to do isolation for a specific peripheral. + */ +struct platform_data_t { + uint32_t periph_start; + uint32_t periph_limit; + enum ppc_bank_e periph_ppc_bank; + int16_t periph_ppc_mask; +}; + +/** + * \brief Enables the fault handlers BusFault, UsageFault, + * MemManageFault and SecureFault. + */ +enum tfm_plat_err_t enable_fault_handlers(void); + +/** + * \brief Configures the system reset request properties + * + * \return Returns values as specified by the \ref tfm_plat_err_t + */ +enum tfm_plat_err_t system_reset_cfg(void); + +/** + * \brief Configures all external interrupts to target the + * NS state, apart for the ones associated to secure + * peripherals (plus MPC and PPC) + * + * \return Returns values as specified by the \ref tfm_plat_err_t + */ +enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void); + +/** + * \brief This function enable the interrupts associated + * to the secure peripherals (plus MPC and PPC) + * + * \return Returns values as specified by the \ref tfm_plat_err_t + */ +enum tfm_plat_err_t nvic_interrupt_enable(void); + +/** + * \brief Configures the system debug properties. + * + * \return Returns values as specified by the \ref tfm_plat_err_t + */ +enum tfm_plat_err_t init_debug(void); + +/** + * \brief Configures the Memory Protection Controller. + * + * \return Returns error code. + */ +enum tfm_plat_err_t mpc_init_cfg(void); + +/** + * \brief Clear MPC interrupt. + */ +void mpc_clear_irq(void); + +/** + * \brief Configures the Peripheral Protection Controller. + */ +enum tfm_plat_err_t ppc_init_cfg(void); + +/** + * \brief Restict peripheral access to secure access only + * + * \note The function does not configure privilege + */ +void ppc_configure_to_secure(enum ppc_bank_e bank, uint32_t pos); + +/** + * \brief Allow non-secure access to peripheral + * + * \note The function does not configure privilege + */ +void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint32_t pos); + +/** + * \brief Enable secure unprivileged access to peripheral + */ +void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint32_t pos); + +/** + * \brief Clear secure unprivileged access to peripheral + */ +void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint32_t pos); + +/** + * \brief Clears PPC interrupt. + */ +void ppc_clear_irq(void); + +/** + * \brief Configures SAU and IDAU. + */ +void sau_and_idau_cfg(void); + +/** + * \brief Sets to secure the initialized non-secure regions of + * the Memory Protection Controller. + */ +void mpc_revert_non_secure_to_secure_cfg(void); + +#endif /* __TARGET_CFG_H__ */ diff --git a/bsp/tf_m_targets/arm/mps3/an547/tfm_hal_isolation.c b/bsp/tf_m_targets/arm/mps3/an547/tfm_hal_isolation.c new file mode 100644 index 0000000..419ad0f --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/tfm_hal_isolation.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "cmsis.h" +#include "Driver_Common.h" +#include "mpu_armv8m_drv.h" +#include "region.h" +#include "target_cfg.h" +#include "tfm_hal_isolation.h" + +#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT +#if TFM_LVL != 3 +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +#define MPU_REGION_VENEERS 0 +#define MPU_REGION_TFM_UNPRIV_CODE 1 +#define MPU_REGION_NS_STACK 2 +#define PARTITION_REGION_RO 3 +#define PARTITION_REGION_RW_STACK 4 +#ifdef TFM_SP_META_PTR_ENABLE +#define MPU_REGION_SP_META_PTR 7 +#endif /* TFM_SP_META_PTR_ENABLE */ + +REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Base); +REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Limit); +REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base); +REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit); +REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base); +REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base); +REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base); +REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base); +REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base); +REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit); +#ifdef TFM_SP_META_PTR_ENABLE +REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$RW$$Base); +REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$RW$$Limit); +#endif /* TFM_SP_META_PTR_ENABLE */ + +const struct mpu_armv8m_region_cfg_t region_cfg[] = { + /* Veneer region */ + { + MPU_REGION_VENEERS, + (uint32_t)®ION_NAME(Load$$LR$$, LR_VENEER, $$Base), + (uint32_t)®ION_NAME(Load$$LR$$, LR_VENEER, $$Limit), + MPU_ARMV8M_MAIR_ATTR_CODE_IDX, + MPU_ARMV8M_XN_EXEC_OK, + MPU_ARMV8M_AP_RO_PRIV_UNPRIV, + MPU_ARMV8M_SH_NONE, +#ifdef TFM_PXN_ENABLE + MPU_ARMV8M_PRIV_EXEC_OK +#endif + }, + /* TFM Core unprivileged code region */ + { + MPU_REGION_TFM_UNPRIV_CODE, + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base), + (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit), + MPU_ARMV8M_MAIR_ATTR_CODE_IDX, + MPU_ARMV8M_XN_EXEC_OK, + MPU_ARMV8M_AP_RO_PRIV_UNPRIV, + MPU_ARMV8M_SH_NONE, +#ifdef TFM_PXN_ENABLE + MPU_ARMV8M_PRIV_EXEC_OK +#endif + }, + /* NSPM PSP */ + { + MPU_REGION_NS_STACK, + (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base), + (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit), + MPU_ARMV8M_MAIR_ATTR_DATA_IDX, + MPU_ARMV8M_XN_EXEC_NEVER, + MPU_ARMV8M_AP_RW_PRIV_UNPRIV, + MPU_ARMV8M_SH_NONE, +#ifdef TFM_PXN_ENABLE + MPU_ARMV8M_PRIV_EXEC_NEVER +#endif + }, + /* RO region */ + { + PARTITION_REGION_RO, + (uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_START, $$Base), + (uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_END, $$Base), + MPU_ARMV8M_MAIR_ATTR_CODE_IDX, + MPU_ARMV8M_XN_EXEC_OK, + MPU_ARMV8M_AP_RO_PRIV_UNPRIV, + MPU_ARMV8M_SH_NONE, +#ifdef TFM_PXN_ENABLE +#if TFM_LVL == 1 + MPU_ARMV8M_PRIV_EXEC_OK +#else + MPU_ARMV8M_PRIV_EXEC_NEVER +#endif +#endif + }, + /* RW, ZI and stack as one region */ + { + PARTITION_REGION_RW_STACK, + (uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base), + (uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base), + MPU_ARMV8M_MAIR_ATTR_DATA_IDX, + MPU_ARMV8M_XN_EXEC_NEVER, + MPU_ARMV8M_AP_RW_PRIV_UNPRIV, + MPU_ARMV8M_SH_NONE, +#ifdef TFM_PXN_ENABLE + MPU_ARMV8M_PRIV_EXEC_NEVER +#endif + }, +#ifdef TFM_SP_META_PTR_ENABLE + /* TFM partition metadata pointer region */ + { + MPU_REGION_SP_META_PTR, + (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$RW$$Base), + (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$RW$$Limit), + MPU_ARMV8M_MAIR_ATTR_DATA_IDX, + MPU_ARMV8M_XN_EXEC_NEVER, + MPU_ARMV8M_AP_RW_PRIV_UNPRIV, + MPU_ARMV8M_SH_NONE, +#ifdef TFM_PXN_ENABLE + MPU_ARMV8M_PRIV_EXEC_NEVER +#endif + } +#endif +}; +#endif /* TFM_LVL != 3 */ +#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */ + +enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void) +{ + /* Set up isolation boundaries between SPE and NSPE */ + sau_and_idau_cfg(); + + if (mpc_init_cfg() != TFM_PLAT_ERR_SUCCESS) { + return TFM_HAL_ERROR_GENERIC; + } + + if (ppc_init_cfg() != TFM_PLAT_ERR_SUCCESS) { + return TFM_HAL_ERROR_GENERIC; + } + + /* Set up static isolation boundaries inside SPE */ +#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT +#if TFM_LVL != 3 + int32_t i; + struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE }; + + mpu_armv8m_clean(&dev_mpu_s); + + for (i = 0; i < ARRAY_SIZE(region_cfg); i++) { + if (mpu_armv8m_region_enable(&dev_mpu_s, + (struct mpu_armv8m_region_cfg_t *)®ion_cfg[i]) + != MPU_ARMV8M_OK) { + return TFM_HAL_ERROR_GENERIC; + } + } + + mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, + HARDFAULT_NMI_ENABLE); +#endif /* TFM_LVL != 3 */ +#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */ + + return TFM_HAL_SUCCESS; +} diff --git a/bsp/tf_m_targets/arm/mps3/an547/tfm_peripherals_def.h b/bsp/tf_m_targets/arm/mps3/an547/tfm_peripherals_def.h new file mode 100644 index 0000000..1c00be5 --- /dev/null +++ b/bsp/tf_m_targets/arm/mps3/an547/tfm_peripherals_def.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * Copyright (c) 2020, Cypress Semiconductor Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PERIPHERALS_DEF_H__ +#define __TFM_PERIPHERALS_DEF_H__ + +#include "platform_irq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TFM_TIMER0_IRQ (TIMER0_IRQn) +#define TFM_TIMER1_IRQ (TIMER1_IRQn) + +struct platform_data_t; + +extern struct platform_data_t tfm_peripheral_std_uart; +extern struct platform_data_t tfm_peripheral_fpga_io; +extern struct platform_data_t tfm_peripheral_timer0; + +#define TFM_PERIPHERAL_STD_UART (&tfm_peripheral_std_uart) +#define TFM_PERIPHERAL_FPGA_IO (&tfm_peripheral_fpga_io) +#define TFM_PERIPHERAL_TIMER0 (&tfm_peripheral_timer0) + +#ifdef PSA_API_TEST_IPC +extern struct platform_data_t tfm_peripheral_FF_TEST_UART_REGION; +extern struct platform_data_t tfm_peripheral_FF_TEST_WATCHDOG_REGION; +extern struct platform_data_t tfm_peripheral_FF_TEST_NVMEM_REGION; +extern struct platform_data_t tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO; +extern struct platform_data_t tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO; +#define FF_TEST_UART_REGION (&tfm_peripheral_FF_TEST_UART_REGION) +#define FF_TEST_WATCHDOG_REGION (&tfm_peripheral_FF_TEST_WATCHDOG_REGION) +#define FF_TEST_NVMEM_REGION (&tfm_peripheral_FF_TEST_NVMEM_REGION) +#define FF_TEST_SERVER_PARTITION_MMIO (&tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO) +#define FF_TEST_DRIVER_PARTITION_MMIO (&tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO) +#endif /* PSA_API_TEST_IPC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PERIPHERALS_DEF_H__ */ diff --git a/bsp/tfm_s.sct b/bsp/tfm_s.sct index 6ee8d52..f3e2489 100644 --- a/bsp/tfm_s.sct +++ b/bsp/tfm_s.sct @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2021-2022 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + LR_CODE ((0x38000000) + ((((0)) + (0x400)))) (((0x60000) - (0x400) - (0x800)) - (0x340)) { diff --git a/kws.uvmpw b/kws.uvmpw deleted file mode 100644 index 8e242dc..0000000 --- a/kws.uvmpw +++ /dev/null @@ -1,23 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - WorkSpace - - - .\tfm.bootloader.uvprojx - - - - .\tfm.secure.uvprojx - - - - .\tfm.kws_ns.uvprojx - 1 - - -
diff --git a/kws/CMakeLists.txt b/kws/CMakeLists.txt new file mode 100644 index 0000000..9a408a7 --- /dev/null +++ b/kws/CMakeLists.txt @@ -0,0 +1,191 @@ +# Copyright (c) 2021 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.21) + +add_executable(kws + # network driver + "${PRJ_DIR}/bsp/freertos-platform/lwip_emac_netif.c" + "${PRJ_DIR}/bsp/freertos-platform/lwip_memory_manager.c" + "${PRJ_DIR}/bsp/freertos-platform/lwip_stack.c" + "${PRJ_DIR}/bsp/aws_libraries/3rdparty/lwip_osal/src/sys_arch.c" + "${PRJ_DIR}/bsp/aws_libraries/abstractions/secure_sockets/lwip/iot_secure_sockets.c" + "${PRJ_DIR}/bsp/aws_libraries/freertos_plus/standard/crypto/src/iot_crypto.c" + "${PRJ_DIR}/bsp/aws_libraries/freertos_plus/standard/tls/src/iot_tls.c" + + # application + "${PRJ_DIR}/kws/source/ml_interface.cc" + "${PRJ_DIR}/kws/source/model_config.cc" + "${PRJ_DIR}/kws/source/blink_task.c" + "${PRJ_DIR}/kws/source/main_ns.c" +) + +target_compile_options(kws + PRIVATE + $<$:-std=gnu++14> + $<$:-std=gnu11> +) + +target_compile_definitions(kws + PRIVATE + ARMCM55 + LIBRARY_LOG_LEVEL=3 + MBEDTLS_CONFIG_FILE= + ACTIVATION_BUF_SRAM_SZ=0x00400000 + ACTIVATION_BUF_SZ=0x00400000 + ARM_MATH_DSP + ARM_MATH_LOOPUNROLL + ARM_MATH_MVEI + ARM_NPU=1 + BL2 + CONFIG_KWS_SCORE_THRESHOLD=0.8 + CPU_CORTEX_M55=1 + DAUTH_CHIP_DEFAULT + MCUBOOT_DATA_SHARING=1 + MCUBOOT_IMAGE_NUMBER=2 + MCUBOOT_SIGN_RSA + MCUBOOT_SIGN_RSA_LEN=2048 + MPS3_PLATFORM=1 + PLATFORM_DEFAULT_UART_STDOUT=ON + PLATFORM_HAL=1 + TFM_PARTITION_AUDIT_LOG=OFF + TFM_PARTITION_CRYPTO + TFM_PARTITION_FIRMWARE_UPDATE + TFM_PARTITION_INITIAL_ATTESTATION + TFM_PARTITION_INTERNAL_TRUSTED_STORAGE + TFM_PARTITION_LOG_LEVEL=TFM_PARTITION_LOG_LEVEL_DEBUG + TFM_PARTITION_PLATFORM + TFM_PARTITION_PROTECTED_STORAGE + TFM_PSA_API=OFF + TFM_SPM_LOG_LEVEL=0 + TFM_SYSTEM_FP=2 + TFM_SYSTEM_FPU=2 + TFM_SYSTEM_FP_NS=2 + TF_LITE_STATIC_MEMORY +) + +target_include_directories(kws + PRIVATE + ${PRJ_DIR}/bsp/aws_configs + ${PRJ_DIR}/kws/source + ${PRJ_DIR}/kws/include + + ${ml-embedded-evaluation-kit_GENERATED_DIR}/kws/include/ + ${ml-embedded-evaluation-kit_SOURCE_DIR}/dependencies/cmsis/CMSIS/DSP/Include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/dependencies/core-driver/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/dependencies/tensorflow + ${ml-embedded-evaluation-kit_SOURCE_DIR}/dependencies/tensorflow/tensorflow/lite/micro + ${ml-embedded-evaluation-kit_SOURCE_DIR}/dependencies/tensorflow/tensorflow/lite/micro/tools/make/downloads/flatbuffers/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/generated/kws/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/platforms/bare-metal/bsp/bsp-core/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/platforms/bare-metal/bsp/bsp-packs/mps3/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/platforms/bare-metal/bsp/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/platforms/bare-metal/timer/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/platforms/native/timer/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/hal/platforms/native/utils/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/main/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/application/tensorflow-lite-micro/include + ${ml-embedded-evaluation-kit_SOURCE_DIR}/source/use_case/kws/include +) + +add_dependencies(kws + ml-embedded-evaluation-kit +) + +# final binary +target_link_libraries(kws + startup + tfm-ns-interface + tfm-ns-interface-cmsis-rtos + freertos-kernel-heap-4 + mcu-driver-hal + cmsis-rtos-api + freertos-cmsis-rtos + freertos-kernel + lib-bsp + lib-AWS-client + lwip +) + +target_link_options(kws + PRIVATE + ${ml-embedded-evaluation-kit_LIB_DIR}/liblibethos-u-kws.a + ${ml-embedded-evaluation-kit_LIB_DIR}/libcmsis-dsp.a + ${ml-embedded-evaluation-kit_LIB_DIR}/libtiming_adapter.a + ${ml-embedded-evaluation-kit_LIB_DIR}/libtensorflow-microlite.a +) + +# Copy the result of TF-M build in the top level build directory +# Convert axf files into bin +# Sign binaries +ExternalProject_Get_Property(tf-m BINARY_DIR) +ExternalProject_Get_Property(tf-m SOURCE_DIR) +add_custom_command( + TARGET + kws + POST_BUILD + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/kws.axf + + BYPRODUCTS + ${CMAKE_CURRENT_BINARY_DIR}/kws_unsigned.bin + ${CMAKE_CURRENT_BINARY_DIR}/kws_signed.bin + ${CMAKE_CURRENT_BINARY_DIR}/kws_signed_update.bin + ${CMAKE_CURRENT_BINARY_DIR}/update-digest.bin + ${CMAKE_CURRENT_BINARY_DIR}/update-signature.bin + ${CMAKE_CURRENT_BINARY_DIR}/update-signature.txt + + COMMAND + ${ARM_ELF2BIN} --bin --output ${CMAKE_CURRENT_BINARY_DIR}/kws_unsigned.bin ${CMAKE_CURRENT_BINARY_DIR}/kws.axf --bincombined + + COMMAND + python3 ${BINARY_DIR}/install/image_signing/scripts/wrapper/wrapper.py + -v 1.0.0 + --layout ${PRJ_DIR}/bsp/signing_layout_ns.c + -k ${BINARY_DIR}/install/image_signing/keys/root-RSA-2048_1.pem + --public-key-format full + --align 1 + --pad + --pad-header + -H 0x400 + -s auto + ${CMAKE_CURRENT_BINARY_DIR}/kws_unsigned.bin + ${CMAKE_CURRENT_BINARY_DIR}/kws_signed.bin + + COMMAND + python3 ${BINARY_DIR}/install/image_signing/scripts/wrapper/wrapper.py + -v 1.4.0 + --layout ${PRJ_DIR}/bsp/signing_layout_ns.c + -k ${BINARY_DIR}/install/image_signing/keys/root-RSA-2048_1.pem + --public-key-format full + --align 1 + --pad + --pad-header + -H 0x400 + -s auto + ${CMAKE_CURRENT_BINARY_DIR}/kws_unsigned.bin + ${CMAKE_CURRENT_BINARY_DIR}/kws_signed_update.bin + + COMMAND + openssl dgst -sha256 -binary -out ${CMAKE_CURRENT_BINARY_DIR}/update-digest.bin ${CMAKE_CURRENT_BINARY_DIR}/kws_signed_update.bin + + COMMAND + openssl pkeyutl -sign -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_mgf1_md:sha256 -inkey ${BINARY_DIR}/install/image_signing/keys/root-RSA-2048_1.pem -in ${CMAKE_CURRENT_BINARY_DIR}/update-digest.bin -out ${CMAKE_CURRENT_BINARY_DIR}/update-signature.bin + + COMMAND + openssl base64 -A -in ${CMAKE_CURRENT_BINARY_DIR}/update-signature.bin -out ${CMAKE_CURRENT_BINARY_DIR}/update-signature.txt + + COMMAND + ${CMAKE_COMMAND} -E echo "Use this base 64 encoded signature in OTA job:" + + COMMAND + ${CMAKE_COMMAND} -E cat ${CMAKE_CURRENT_BINARY_DIR}/update-signature.txt +) + +add_test( + NAME kws-test + COMMAND pytest -s kws/tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND_EXPAND_LISTS +) diff --git a/kws/include/ml_interface.h b/kws/include/ml_interface.h index 8d27be4..87cb4d5 100644 --- a/kws/include/ml_interface.h +++ b/kws/include/ml_interface.h @@ -63,8 +63,12 @@ void on_ml_processing_change(ml_processing_change_handler_t handler, void* self) void ml_process_audio(const int16_t* buffer, size_t size); +/* this task does actual ml processing and is gated by the net task which let's it run if no ota job is present */ void ml_task(void*); +/* task used to communicate ml results via mqtt */ +void ml_mqtt_task(void*); + #ifdef __cplusplus } #endif diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.appveyor.yml b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.appveyor.yml deleted file mode 100644 index d86e1d2..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.appveyor.yml +++ /dev/null @@ -1,35 +0,0 @@ -version: 0.5.4-build-{build} -pull_requests: - do_not_increment_build_number: true -image: -- Visual Studio 2015 -- Visual Studio 2013 -- Visual Studio 2017 -install: -- cmd: >- - set tests=1 - - if /i "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" (call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64) & (set tests=0) - - if /i "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86) & (set QTDIR=C:\Qt\5.9\msvc2015) - - if /i "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64) & (set QTDIR=C:\Qt\5.9\msvc2017_64) - - set path=%PATH%;%QTDIR%\bin -build_script: -- cmd: >- - nmake -f Makefile.nmake -nologo CFLAGS="-W3 -Os -MDd" - - cd tests - - if /i "%tests%"=="1" qmake CONFIG-=release CONFIG+=debug - - if /i "%tests%"=="1" nmake -nologo -s -test_script: -- cmd: >- - if /i "%tests%"=="1" nmake -s -nologo TESTARGS=-silent check - - if /i "%tests%"=="0" echo Tests skipped. -artifacts: -- path: lib\tinycbor.lib -deploy: off diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitattributes b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitattributes deleted file mode 100644 index 76ed256..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -.tag export-subst -.gitignore export-ignore -.gitattributes export-ignore -.appveyor.yml text diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitignore b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitignore deleted file mode 100644 index 3272de3..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.gitignore +++ /dev/null @@ -1,81 +0,0 @@ -# Frequent generated files -callgrind.out.* -pcviewer.cfg -*~ -*.a -*.la -*.core -*.d -*.dylib -*.moc -*.o -*.obj -*.orig -*.swp -*.rej -*.so -*.so.* -*.pbxuser -*.mode1 -*.mode1v3 -*_pch.h.cpp -*_resource.rc -.#* -*.*# -core -.qmake.cache -.qmake.stash -.qmake.vars -.device.vars -tags -.DS_Store -*.debug -Makefile* -*.prl -*.app -*.pro.user* -*.qmlproject.user* -*.gcov -*.gcda -*.gcno -*.flc -.*.swp -tinycbor.pc - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.vcxproj -*.vcxproj.filters -*.vcxproj.user -*.exe.embed.manifest -*.exe_manifest.rc -*.exe_manifest.res - -# MinGW generated files -*.Debug -*.Release - -# INTEGRITY generated files -*.gpj -*.int -*.ael -*.dla -*.dnm -*.dep -*.map - -bin -doc -lib -src/cjson -src/doxygen.log -!/Makefile -.config diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.tag b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.tag deleted file mode 100644 index 6828f88..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.tag +++ /dev/null @@ -1 +0,0 @@ -$Format:%H$ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.travis.yml b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.travis.yml deleted file mode 100644 index 7ca287d..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/.travis.yml +++ /dev/null @@ -1,84 +0,0 @@ -language: cpp -matrix: - include: - - os: linux - dist: xenial - addons: - apt: - sources: - - sourceline: 'ppa:beineri/opt-qt-5.12.1-xenial' - packages: - - qt512base valgrind - - doxygen - env: - - QMAKESPEC=linux-g++ - - EVAL="CC=gcc && CXX=g++" - - CFLAGS="-Os" - - LDFLAGS="-Wl,--no-undefined -lm" - - QMAKEFLAGS="-config release" - - QT_NO_CPU_FEATURE=rdrnd - - os: linux - dist: xenial - addons: - apt: - sources: - - sourceline: 'ppa:beineri/opt-qt-5.12.1-xenial' - packages: - - qt512base - env: - - QMAKESPEC=linux-clang - - EVAL="CC=clang && CXX=clang++" - - CFLAGS="-Oz" - - LDFLAGS="-Wl,--no-undefined -lm" - - QMAKEFLAGS="-config release" - - MAKEFLAGS=-s - - TESTARGS=-silent - - os: linux - dist: xenial - env: - - QMAKESPEC=linux-gcc-freestanding - - EVAL="CXX=false" - - CFLAGS="-ffreestanding -Os" - - LDFLAGS="-Wl,--no-undefined -lm" - - os: linux - dist: xenial - env: - - QMAKESPEC=linux-gcc-no-math - - EVAL="CXX=false && touch src/math.h src/float.h" - - CFLAGS="-ffreestanding -DCBOR_NO_FLOATING_POINT -Os" - - LDFLAGS="-Wl,--no-undefined" - - LDLIBS="" - - os: osx - env: - - QMAKESPEC=macx-clang - - CFLAGS="-Oz" - - QMAKEFLAGS="-config debug" - - MAKEFLAGS=-s - - TESTARGS=-silent - - PATH=/usr/local/opt/qt5/bin:$PATH -install: - - if [ "${TRAVIS_OS_NAME}" != "linux" ]; then - brew update; - brew install qt5; - fi -script: - - PATH=`echo /opt/qt*/bin`:$PATH - - eval "$EVAL" - - make -s -f Makefile.configure configure | tee .config - - make -k - CFLAGS="$CFLAGS -march=native -g1 -Wall -Wextra -Werror" - CPPFLAGS="-DNDEBUG" - lib/libtinycbor.a - - size lib/libtinycbor.a | tee sizes - - make -s clean - - make -k - CFLAGS="$CFLAGS -O0 -g" - LDFLAGS="$LDFLAGS" ${LDLIBS+LDLIBS="$LDLIBS"} - - grep -q freestanding-pass .config || make - QMAKEFLAGS="$QMAKEFLAGS QMAKE_CXX=$CXX" - tests/Makefile - - grep -q freestanding-pass .config || - (cd tests && make TESTARGS=-silent check -k - TESTRUNNER=`which valgrind 2>/dev/null`) - - make -s clean - - ./scripts/update-docs.sh diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Doxyfile b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Doxyfile deleted file mode 100644 index a7263c2..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Doxyfile +++ /dev/null @@ -1,49 +0,0 @@ -PROJECT_NAME = "TinyCBOR $(VERSION) API" -OUTPUT_DIRECTORY = ../doc -ABBREVIATE_BRIEF = -SHORT_NAMES = YES -JAVADOC_AUTOBRIEF = YES -QT_AUTOBRIEF = YES -TAB_SIZE = 8 -ALIASES = "value=\arg \c" -OPTIMIZE_OUTPUT_FOR_C = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = NO -HIDE_UNDOC_MEMBERS = YES -HIDE_UNDOC_CLASSES = YES -GENERATE_TODOLIST = NO -GENERATE_TESTLIST = NO -GENERATE_BUGLIST = NO -GENERATE_DEPRECATEDLIST= NO -SHOW_USED_FILES = NO -WARN_IF_UNDOCUMENTED = NO -WARN_LOGFILE = doxygen.log -INPUT = . -FILE_PATTERNS = *.h \ - *.c \ - *.dox -EXCLUDE_PATTERNS = *_p.h -STRIP_CODE_COMMENTS = NO -REFERENCED_BY_RELATION = YES -IGNORE_PREFIX = cbor_ \ - Cbor -HTML_TIMESTAMP = NO -GENERATE_HTMLHELP = YES -GENERATE_CHI = YES -BINARY_TOC = YES -TOC_EXPAND = YES -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest -SEARCHENGINE = NO -GENERATE_LATEX = NO -COMPACT_LATEX = YES -MACRO_EXPANSION = YES -PREDEFINED = DOXYGEN \ - CBOR_INLINE_API= -CLASS_DIAGRAMS = NO -CLASS_GRAPH = NO -COLLABORATION_GRAPH = NO -GROUP_GRAPHS = NO -INCLUDE_GRAPH = NO -INCLUDED_BY_GRAPH = NO -GRAPHICAL_HIERARCHY = NO -DIRECTORY_GRAPH = NO diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/LICENSE b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/LICENSE deleted file mode 100644 index 4aad977..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Intel Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Makefile b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Makefile deleted file mode 100644 index 239dde8..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/Makefile +++ /dev/null @@ -1,240 +0,0 @@ -# Variables: -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin -libdir = $(exec_prefix)/lib -includedir = $(prefix)/include -pkgconfigdir = $(libdir)/pkgconfig - -CFLAGS = -Wall -Wextra -LDFLAGS_GCSECTIONS = -Wl,--gc-sections -LDFLAGS += $(if $(gc_sections-pass),$(LDFLAGS_GCSECTIONS)) -LDLIBS = -lm - -GIT_ARCHIVE = git archive --prefix="$(PACKAGE)/" -9 -INSTALL = install -INSTALL_DATA = $(INSTALL) -m 644 -INSTALL_PROGRAM = $(INSTALL) -m 755 -QMAKE = qmake -MKDIR = mkdir -p -RMDIR = rmdir -SED = sed - -# Our sources -TINYCBOR_HEADERS = src/cbor.h src/cborjson.h src/tinycbor-version.h -TINYCBOR_FREESTANDING_SOURCES = \ - src/cborerrorstrings.c \ - src/cborencoder.c \ - src/cborencoder_close_container_checked.c \ - src/cborparser.c \ - src/cborpretty.c \ -# -CBORDUMP_SOURCES = tools/cbordump/cbordump.c - -BUILD_SHARED = $(shell file -L /bin/sh 2>/dev/null | grep -q ELF && echo 1) -BUILD_STATIC = 1 - -ifneq ($(BUILD_STATIC),1) -ifneq ($(BUILD_SHARED),1) - $(error error: BUILD_STATIC and BUILD_SHARED can not be both disabled) -endif -endif - -INSTALL_TARGETS += $(bindir)/cbordump -ifeq ($(BUILD_SHARED),1) -BINLIBRARY=lib/libtinycbor.so -INSTALL_TARGETS += $(libdir)/libtinycbor.so -INSTALL_TARGETS += $(libdir)/libtinycbor.so.$(SOVERSION) -INSTALL_TARGETS += $(libdir)/libtinycbor.so.$(VERSION) -endif -ifeq ($(BUILD_STATIC),1) -BINLIBRARY=lib/libtinycbor.a -INSTALL_TARGETS += $(libdir)/libtinycbor.a -endif -INSTALL_TARGETS += $(pkgconfigdir)/tinycbor.pc -INSTALL_TARGETS += $(TINYCBOR_HEADERS:src/%=$(includedir)/tinycbor/%) - -# setup VPATH -MAKEFILE := $(lastword $(MAKEFILE_LIST)) -SRCDIR := $(dir $(MAKEFILE)) -VPATH = $(SRCDIR):$(SRCDIR)/src - -# Our version -GIT_DIR := $(strip $(shell git -C $(SRCDIR). rev-parse --git-dir 2> /dev/null)) -VERSION = $(shell cat $(SRCDIR)VERSION) -SOVERSION = $(shell cut -f1-2 -d. $(SRCDIR)VERSION) -PACKAGE = tinycbor-$(VERSION) - -# Check that QMAKE is Qt 5 -ifeq ($(origin QMAKE),file) - check_qmake = $(strip $(shell $(1) -query QT_VERSION 2>/dev/null | cut -b1)) - ifneq ($(call check_qmake,$(QMAKE)),5) - QMAKE := qmake -qt5 - ifneq ($(call check_qmake,$(QMAKE)),5) - QMAKE := qmake-qt5 - ifneq ($(call check_qmake,$(QMAKE)),5) - QMAKE := @echo >&2 $(MAKEFILE): Cannot find a Qt 5 qmake; false - endif - endif - endif -endif - --include .config - -ifeq ($(wildcard .config),) - $(info .config file not yet created) -endif - -ifeq ($(freestanding-pass),1) -TINYCBOR_SOURCES = $(TINYCBOR_FREESTANDING_SOURCES) -else -TINYCBOR_SOURCES = \ - $(TINYCBOR_FREESTANDING_SOURCES) \ - src/cborparser_dup_string.c \ - src/cborpretty_stdio.c \ - src/cbortojson.c \ - src/cborvalidation.c \ -# -# if open_memstream is unavailable on the system, try to implement our own -# version using funopen or fopencookie -ifeq ($(open_memstream-pass),) - ifeq ($(funopen-pass)$(fopencookie-pass),) - CFLAGS += -DWITHOUT_OPEN_MEMSTREAM - ifeq ($(wildcard .config),.config) - $(warning warning: funopen and fopencookie unavailable, open_memstream can not be implemented and conversion to JSON will not work properly!) - endif - else - TINYCBOR_SOURCES += src/open_memstream.c - endif -endif -endif - -# json2cbor depends on an external library (cjson) -ifneq ($(cjson-pass)$(system-cjson-pass),) - JSON2CBOR_SOURCES = tools/json2cbor/json2cbor.c - INSTALL_TARGETS += $(bindir)/json2cbor - ifeq ($(system-cjson-pass),1) - LDFLAGS_CJSON = -lcjson - else - JSON2CBOR_SOURCES += src/cjson/cJSON.c - json2cbor_CCFLAGS = -I$(SRCDIR)src/cjson - endif -endif - -# Rules -all: .config \ - $(if $(subst 0,,$(BUILD_STATIC)),lib/libtinycbor.a) \ - $(if $(subst 0,,$(BUILD_SHARED)),lib/libtinycbor.so) \ - $(if $(freestanding-pass),,bin/cbordump) \ - tinycbor.pc -all: $(if $(JSON2CBOR_SOURCES),bin/json2cbor) -check: tests/Makefile | $(BINLIBRARY) - $(MAKE) -C tests check -silentcheck: | $(BINLIBRARY) - TESTARGS=-silent $(MAKE) -f $(MAKEFILE) -s check -configure: .config -.config: Makefile.configure - $(MAKE) -f $(SRCDIR)Makefile.configure OUT='>&9' configure 9> $@ - -lib/libtinycbor-freestanding.a: $(TINYCBOR_FREESTANDING_SOURCES:.c=.o) - @$(MKDIR) -p lib - $(AR) cqs $@ $^ - -lib/libtinycbor.a: $(TINYCBOR_SOURCES:.c=.o) - @$(MKDIR) -p lib - $(AR) cqs $@ $^ - -lib/libtinycbor.so: $(TINYCBOR_SOURCES:.c=.pic.o) - @$(MKDIR) -p lib - $(CC) -shared -Wl,-soname,libtinycbor.so.$(SOVERSION) -o lib/libtinycbor.so.$(VERSION) $(LDFLAGS) $^ $(LDLIBS) - cd lib ; ln -sf libtinycbor.so.$(VERSION) libtinycbor.so ; ln -sf libtinycbor.so.$(VERSION) libtinycbor.so.$(SOVERSION) - -bin/cbordump: $(CBORDUMP_SOURCES:.c=.o) $(BINLIBRARY) - @$(MKDIR) -p bin - $(CC) -o $@ $(LDFLAGS) $^ $(LDLIBS) - -bin/json2cbor: $(JSON2CBOR_SOURCES:.c=.o) $(BINLIBRARY) - @$(MKDIR) -p bin - $(CC) -o $@ $(LDFLAGS) $^ $(LDFLAGS_CJSON) $(LDLIBS) - -tinycbor.pc: tinycbor.pc.in - $(SED) > $@ < $< \ - -e 's,@prefix@,$(prefix),' \ - -e 's,@exec_prefix@,$(exec_prefix),' \ - -e 's,@libdir@,$(libdir),' \ - -e 's,@includedir@,$(includedir),' \ - -e 's,@version@,$(VERSION),' - -tests/Makefile: tests/tests.pro - $(QMAKE) $(QMAKEFLAGS) -o $@ $< - -$(PACKAGE).tar.gz: | .git - GIT_DIR=$(SRCDIR).git $(GIT_ARCHIVE) --format=tar.gz -o "$(PACKAGE).tar.gz" HEAD -$(PACKAGE).zip: | .git - GIT_DIR=$(SRCDIR).git $(GIT_ARCHIVE) --format=zip -o "$(PACKAGE).zip" HEAD - -$(DESTDIR)$(libdir)/%: lib/% - $(INSTALL) -d $(@D) - $(INSTALL_DATA) $< $@ -$(DESTDIR)$(bindir)/%: bin/% - $(INSTALL) -d $(@D) - $(INSTALL_PROGRAM) $< $@ -$(DESTDIR)$(pkgconfigdir)/%: % - $(INSTALL) -d $(@D) - $(INSTALL_DATA) $< $@ -$(DESTDIR)$(includedir)/tinycbor/%: src/% - $(INSTALL) -d $(@D) - $(INSTALL_DATA) $< $@ - -install-strip: - $(MAKE) -f $(MAKEFILE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install - -install: $(INSTALL_TARGETS:%=$(DESTDIR)%) -uninstall: - $(RM) $(INSTALL_TARGETS:%=$(DESTDIR)%) - -mostlyclean: - $(RM) $(TINYCBOR_SOURCES:.c=.o) - $(RM) $(TINYCBOR_SOURCES:.c=.pic.o) - $(RM) $(CBORDUMP_SOURCES:.c=.o) - -clean: mostlyclean - $(RM) bin/cbordump - $(RM) bin/json2cbor - $(RM) lib/libtinycbor.a - $(RM) lib/libtinycbor-freestanding.a - $(RM) tinycbor.pc - $(RM) lib/libtinycbor.so* - test -e tests/Makefile && $(MAKE) -C tests clean || : - -distclean: clean - test -e tests/Makefile && $(MAKE) -C tests distclean || : - -docs: - cd $(SRCDIR)src && VERSION=$(VERSION) doxygen $(SRCDIR)/../Doxyfile - -dist: $(PACKAGE).tar.gz $(PACKAGE).zip -distcheck: .git - -$(RM) -r $${TMPDIR-/tmp}/tinycbor-distcheck - GIT_DIR=$(SRCDIR).git git archive --prefix=tinycbor-distcheck/ --format=tar HEAD | tar -xf - -C $${TMPDIR-/tmp} - cd $${TMPDIR-/tmp}/tinycbor-distcheck && $(MAKE) silentcheck - $(RM) -r $${TMPDIR-/tmp}/tinycbor-distcheck - -tag: distcheck - @cd $(SRCDIR). && perl scripts/maketag.pl - -.PHONY: all check silentcheck configure install uninstall -.PHONY: mostlyclean clean distclean -.PHONY: docs dist distcheck release -.SECONDARY: - -cflags := $(CPPFLAGS) -I$(SRCDIR)src -cflags += -std=gnu99 $(CFLAGS) -%.o: %.c - @test -d $(@D) || $(MKDIR) $(@D) - $(CC) $(cflags) $($(basename $(notdir $@))_CCFLAGS) -c -o $@ $< -%.pic.o: %.c - @test -d $(@D) || $(MKDIR) $(@D) - $(CC) $(cflags) -fPIC $($(basename $(notdir $@))_CCFLAGS) -c -o $@ $< - --include src/*.d diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/README b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/README deleted file mode 100644 index 167efa0..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/README +++ /dev/null @@ -1,13 +0,0 @@ -Concise Binary Object Representation (CBOR) Library ---------------------------------------------------- - -To build TinyCBOR: - - make - -If you want to change the compiler or pass extra compiler flags: - - make CC=clang CFLAGS="-m32 -Oz" LDFLAGS="-m32" - -Documentation: https://intel.github.io/tinycbor/current/ - diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/TODO b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/TODO deleted file mode 100644 index e9103ee..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/TODO +++ /dev/null @@ -1,25 +0,0 @@ -==== To Do list for libcbor ==== -=== General === -* API review -* Benchmark -* Write examples -** Simple decoder -** Decoder to JSON -** Windowed encoding/decoding (limited memory) - -=== Encoder === -* Write API docs -* Add API for creating indeterminate-length arrays and maps -* Add API for creating indeterminate-length strings -* Add API for relaxing doubles to floats and to integers -* Add length-checking of the sub-containers (#ifndef CBOR_ENCODER_NO_USER_CHECK) -* Decide how to indicate number of bytes needed -** Suggestion: return negative number from the functions - -=== Decoder === -* Write functions not yet implemented -* Add API for stream-decoding strings -* Add API for checking known tags and simple types -* (unlikely) Add API for checking the pairing of a tag and the tagged type -* Write tests for error conditions -* Fuzzy-test the decoder diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/VERSION b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/VERSION deleted file mode 100644 index 7d85683..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.5.4 diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.dox b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.dox deleted file mode 100644 index 0bf5c54..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.dox +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -/** - * \mainpage - * The TinyCBOR $(VERSION) library is a small CBOR encoder and decoder library, - * optimized for very fast operation with very small footprint. The main encoder - * and decoder functions do not allocate memory. - * - * TinyCBOR is divided into the following groups of functions and structures: - * - \ref CborGlobals - * - \ref CborEncoding - * - \ref CborParsing - * - \ref CborPretty - * - \ref CborToJson - */ - -/** - * \file - * The is the main header in TinyCBOR and defines the constants used by most functions - * as well as the structures for encoding (CborEncoder) and decoding (CborValue). - * - * \sa - */ - -/** - * \file - * The file contains the routines that are used to convert a CBOR - * data stream into JSON. - * - * \sa - */ - -/** - * \defgroup CborGlobals Global constants - * \brief Constants used by all TinyCBOR function groups. - */ - -/** - * \addtogroup CborGlobals - * @{ - */ - -/** - * \var size_t CborIndefiniteLength - * - * This variable is a constant used to indicate that the length of the map or - * array is not yet determined. It is used in functions - * cbor_encoder_create_map() and cbor_encoder_create_array() - */ - -/** - * \enum CborType - * The CborType enum contains the types known to TinyCBOR. - * - * \value CborIntegerType Type is an integer value, positive, negative or zero - * \value CborByteStringType Type is a string of arbitrary raw bytes - * \value CborTextStringType Type is a text string encoded in UTF-8 - * \value CborArrayType Type is a CBOR array - * \value CborMapType Type is a CBOR map (an associative container with key and value pairs) - * \value CborTagType Type is a CBOR tag (a 64-bit integer describing the item that follows, see CborKnownTags) - * \value CborSimpleType Type is one of the CBOR Simple Types - * \value CborBooleanType Type is a boolean (true or false) - * \value CborNullType Type encodes a null - * \value CborUndefinedType Type encodes an undefined value - * \value CborHalfFloatType Type is an IEEE 754 half precision (16-bit) floating point type - * \value CborFloatType Type is an IEEE 754 single precision (32-bit) floating point type - * \value CborDoubleType Type is an IEEE 754 double precision (64-bit) floating point type - * \value CborInvalidType Type is not valid (this value is used to indicate error conditions) - */ - -/** - * \enum CborKnownTags - * The CborKnownTags enum contains known tags specified in RFC 7049, for use by the application. - * TinyCBOR does not usually interpret the meaning of these tags and does not add them to the - * output stream, unless specifically instructed to do so in functions for that effect. - * - * \value CborDateTimeStringTag Text string contains a date-time encoded in RFC 3339 format, "YYYY-MM-DD hh:mm:ss+zzzz" - * \value CborUnixTime_tTag Number is a Unix time_t quantity, the number of seconds since 1970-01-01 midnight UTC - * \value CborPositiveBignumTag Item is a CBOR byte string encoding a positive integer of arbitrary precision - * \value CborNegativeBignumTag Item is a CBOR byte string encoding a negative integer of arbitrary precision - * \value CborDecimalTag Item is a CBOR array of two integers encoding a fixed-point decimal - * \value CborBigfloatTag Item is a bigfloat - * \value CborExpectedBase64urlTag Item is a CBOR byte string that is expected to be encoded as Base64Url - * \value CborExpectedBase64Tag Item is a CBOR byte string that is expected to be encoded as Base64 - * \value CborExpectedBase16Tag Item is a CBOR byte string that is expected to be encoded as Base16 (also known as "hexdump") - * \value CborUriTag Item is a CBOR text string containing a URI (RFC 3986) or IRI (RFC 3987) - * \value CborBase64urlTag Item is a CBOR text string that was encoded as Base64Url - * \value CborBase64Tag Item is a CBOR text string that was encoded as Base64 - * \value CborRegularExpressionTag Item is a CBOR text string containing a regular expression - * \value CborMimeMessageTag Item is a CBOR text string containing a MIME message (RFC 2045, 2046, 2047, 2822) - * \value CborSignatureTag Item contains CBOR-encoded data. - * This tag is also used as "file magic," marking a file as containing CBOR - */ - -/** - * \typedef CborTag - * This typedef is an unsigned 64-bit integer. Known CBOR tags can be used from the CborKnownTags enum - * but the user application may use other tag values than the ones specified in RFC 7049. - */ - -/** @} */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.h b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.h deleted file mode 100644 index d6360d8..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbor.h +++ /dev/null @@ -1,607 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBOR_H -#define CBOR_H - -#ifndef assert -#include -#endif -#include -#include -#include -#include -#include - -#include "tinycbor-version.h" - -#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH) - -#ifdef __cplusplus -extern "C" { -#else -#include -#endif - -#ifndef SIZE_MAX -/* Some systems fail to define SIZE_MAX in , even though C99 requires it... - * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2, - * which says: "the value is converted by repeatedly adding or subtracting one more than the - * maximum value that can be represented in the new type until the value is in the range of the - * new type." - * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX. - */ -# define SIZE_MAX ((size_t)-1) -#endif - -#ifndef CBOR_API -# define CBOR_API -#endif -#ifndef CBOR_PRIVATE_API -# define CBOR_PRIVATE_API -#endif -#ifndef CBOR_INLINE_API -# if defined(__cplusplus) -# define CBOR_INLINE inline -# define CBOR_INLINE_API inline -# else -# define CBOR_INLINE_API static CBOR_INLINE -# if defined(_MSC_VER) -# define CBOR_INLINE __inline -# elif defined(__GNUC__) -# define CBOR_INLINE __inline__ -# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -# define CBOR_INLINE inline -# else -# define CBOR_INLINE -# endif -# endif -#endif - -typedef enum CborType { - CborIntegerType = 0x00, - CborByteStringType = 0x40, - CborTextStringType = 0x60, - CborArrayType = 0x80, - CborMapType = 0xa0, - CborTagType = 0xc0, - CborSimpleType = 0xe0, - CborBooleanType = 0xf5, - CborNullType = 0xf6, - CborUndefinedType = 0xf7, - CborHalfFloatType = 0xf9, - CborFloatType = 0xfa, - CborDoubleType = 0xfb, - - CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */ -} CborType; - -typedef uint64_t CborTag; -typedef enum CborKnownTags { - CborDateTimeStringTag = 0, - CborUnixTime_tTag = 1, - CborPositiveBignumTag = 2, - CborNegativeBignumTag = 3, - CborDecimalTag = 4, - CborBigfloatTag = 5, - CborCOSE_Encrypt0Tag = 16, - CborCOSE_Mac0Tag = 17, - CborCOSE_Sign1Tag = 18, - CborExpectedBase64urlTag = 21, - CborExpectedBase64Tag = 22, - CborExpectedBase16Tag = 23, - CborEncodedCborTag = 24, - CborUrlTag = 32, - CborBase64urlTag = 33, - CborBase64Tag = 34, - CborRegularExpressionTag = 35, - CborMimeMessageTag = 36, - CborCOSE_EncryptTag = 96, - CborCOSE_MacTag = 97, - CborCOSE_SignTag = 98, - CborSignatureTag = 55799 -} CborKnownTags; - -/* #define the constants so we can check with #ifdef */ -#define CborDateTimeStringTag CborDateTimeStringTag -#define CborUnixTime_tTag CborUnixTime_tTag -#define CborPositiveBignumTag CborPositiveBignumTag -#define CborNegativeBignumTag CborNegativeBignumTag -#define CborDecimalTag CborDecimalTag -#define CborBigfloatTag CborBigfloatTag -#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag -#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag -#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag -#define CborExpectedBase64urlTag CborExpectedBase64urlTag -#define CborExpectedBase64Tag CborExpectedBase64Tag -#define CborExpectedBase16Tag CborExpectedBase16Tag -#define CborEncodedCborTag CborEncodedCborTag -#define CborUrlTag CborUrlTag -#define CborBase64urlTag CborBase64urlTag -#define CborBase64Tag CborBase64Tag -#define CborRegularExpressionTag CborRegularExpressionTag -#define CborMimeMessageTag CborMimeMessageTag -#define CborCOSE_EncryptTag CborCOSE_EncryptTag -#define CborCOSE_MacTag CborCOSE_MacTag -#define CborCOSE_SignTag CborCOSE_SignTag -#define CborSignatureTag CborSignatureTag - -/* Error API */ - -typedef enum CborError { - CborNoError = 0, - - /* errors in all modes */ - CborUnknownError, - CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */ - CborErrorAdvancePastEOF, - CborErrorIO, - - /* parser errors streaming errors */ - CborErrorGarbageAtEnd = 256, - CborErrorUnexpectedEOF, - CborErrorUnexpectedBreak, - CborErrorUnknownType, /* can only happen in major type 7 */ - CborErrorIllegalType, /* type not allowed here */ - CborErrorIllegalNumber, - CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */ - - /* parser errors in strict mode parsing only */ - CborErrorUnknownSimpleType = 512, - CborErrorUnknownTag, - CborErrorInappropriateTagForType, - CborErrorDuplicateObjectKeys, - CborErrorInvalidUtf8TextString, - CborErrorExcludedType, - CborErrorExcludedValue, - CborErrorImproperValue, - CborErrorOverlongEncoding, - CborErrorMapKeyNotString, - CborErrorMapNotSorted, - CborErrorMapKeysNotUnique, - - /* encoder errors */ - CborErrorTooManyItems = 768, - CborErrorTooFewItems, - - /* internal implementation errors */ - CborErrorDataTooLarge = 1024, - CborErrorNestingTooDeep, - CborErrorUnsupportedType, - - /* errors in converting to JSON */ - CborErrorJsonObjectKeyIsAggregate = 1280, - CborErrorJsonObjectKeyNotString, - CborErrorJsonNotImplemented, - - CborErrorOutOfMemory = (int) (~0U / 2 + 1), - CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */ -} CborError; - -CBOR_API const char *cbor_error_string(CborError error); - -/* Encoder API */ -struct CborEncoder -{ - union { - uint8_t *ptr; - ptrdiff_t bytes_needed; - } data; - const uint8_t *end; - size_t remaining; - int flags; -}; -typedef struct CborEncoder CborEncoder; - -static const size_t CborIndefiniteLength = SIZE_MAX; - -CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags); -CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value); -CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value); -CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value); -CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value); -CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag); -CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length); -CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) -{ return cbor_encode_text_string(encoder, string, strlen(string)); } -CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length); -CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value); - -CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value) -{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); } -CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder) -{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); } -CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder) -{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); } - -CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) -{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); } -CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value) -{ return cbor_encode_floating_point(encoder, CborFloatType, &value); } -CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value) -{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); } - -CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length); -CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length); -CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder); -CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder); - -CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder) -{ - return encoder->data.ptr; -} - -CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) -{ - return (size_t)(encoder->data.ptr - buffer); -} - -CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) -{ - return encoder->end ? 0 : (size_t)encoder->data.bytes_needed; -} - -/* Parser API */ - -enum CborParserIteratorFlags -{ - CborIteratorFlag_IntegerValueTooLarge = 0x01, - CborIteratorFlag_NegativeInteger = 0x02, - CborIteratorFlag_IteratingStringChunks = 0x02, - CborIteratorFlag_UnknownLength = 0x04, - CborIteratorFlag_ContainerIsMap = 0x20, - CborIteratorFlag_NextIsMapKey = 0x40 -}; - -struct CborParser -{ - const uint8_t *end; - uint32_t flags; -}; -typedef struct CborParser CborParser; - -struct CborValue -{ - const CborParser *parser; - const uint8_t *ptr; - uint32_t remaining; - uint16_t extra; - uint8_t type; - uint8_t flags; -}; -typedef struct CborValue CborValue; - -CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it); - -CBOR_API CborError cbor_value_validate_basic(const CborValue *it); - -CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it) -{ return it->remaining == 0; } -CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it) -{ return it->ptr; } -CBOR_API CborError cbor_value_advance_fixed(CborValue *it); -CBOR_API CborError cbor_value_advance(CborValue *it); -CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it) -{ return it->type == CborArrayType || it->type == CborMapType; } -CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed); -CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed); - -CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value); -CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value) -{ - return value->flags & CborIteratorFlag_IntegerValueTooLarge ? - _cbor_value_decode_int64_internal(value) : value->extra; -} - -CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value) -{ return value && value->type != CborInvalidType; } -CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value) -{ return (CborType)value->type; } - -/* Null & undefined type */ -CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value) -{ return value->type == CborNullType; } -CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value) -{ return value->type == CborUndefinedType; } - -/* Booleans */ -CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value) -{ return value->type == CborBooleanType; } -CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result) -{ - assert(cbor_value_is_boolean(value)); - *result = !!value->extra; - return CborNoError; -} - -/* Simple types */ -CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value) -{ return value->type == CborSimpleType; } -CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) -{ - assert(cbor_value_is_simple_type(value)); - *result = (uint8_t)value->extra; - return CborNoError; -} - -/* Integers */ -CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value) -{ return value->type == CborIntegerType; } -CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value) -{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; } -CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value) -{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); } - -CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) -{ - assert(cbor_value_is_integer(value)); - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) -{ - assert(cbor_value_is_unsigned_integer(value)); - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result) -{ - assert(cbor_value_is_integer(value)); - *result = (int64_t) _cbor_value_extract_int64_helper(value); - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result) -{ - assert(cbor_value_is_integer(value)); - *result = (int) _cbor_value_extract_int64_helper(value); - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result); -CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result); - -CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value) -{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; } - -/* Tags */ -CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value) -{ return value->type == CborTagType; } -CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result) -{ - assert(cbor_value_is_tag(value)); - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} -CBOR_API CborError cbor_value_skip_tag(CborValue *it); - -/* Strings */ -CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value) -{ return value->type == CborByteStringType; } -CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value) -{ return value->type == CborTextStringType; } - -CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length) -{ - uint64_t v; - assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer, - size_t *buflen, CborValue *next); -CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer, - size_t *buflen, CborValue *next); - -CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length); - -CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, - size_t *buflen, CborValue *next) -{ - assert(cbor_value_is_text_string(value)); - return _cbor_value_copy_string(value, buffer, buflen, next); -} -CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, - size_t *buflen, CborValue *next) -{ - assert(cbor_value_is_byte_string(value)); - return _cbor_value_copy_string(value, buffer, buflen, next); -} - -CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, - size_t *buflen, CborValue *next) -{ - assert(cbor_value_is_text_string(value)); - return _cbor_value_dup_string(value, (void **)buffer, buflen, next); -} -CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, - size_t *buflen, CborValue *next) -{ - assert(cbor_value_is_byte_string(value)); - return _cbor_value_dup_string(value, (void **)buffer, buflen, next); -} - -CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result); - -/* Maps and arrays */ -CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value) -{ return value->type == CborArrayType; } -CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value) -{ return value->type == CborMapType; } - -CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length) -{ - uint64_t v; - assert(cbor_value_is_array(value)); - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length) -{ - uint64_t v; - assert(cbor_value_is_map(value)); - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element); - -/* Floating point */ -CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value) -{ return value->type == CborHalfFloatType; } -CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result); - -CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value) -{ return value->type == CborFloatType; } -CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result) -{ - uint32_t data; - assert(cbor_value_is_float(value)); - assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); - data = (uint32_t)_cbor_value_decode_int64_internal(value); - memcpy(result, &data, sizeof(*result)); - return CborNoError; -} - -CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value) -{ return value->type == CborDoubleType; } -CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result) -{ - uint64_t data; - assert(cbor_value_is_double(value)); - assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); - data = _cbor_value_decode_int64_internal(value); - memcpy(result, &data, sizeof(*result)); - return CborNoError; -} - -/* Validation API */ - -enum CborValidationFlags { - /* Bit mapping: - * bits 0-7 (8 bits): canonical format - * bits 8-11 (4 bits): canonical format & strict mode - * bits 12-20 (8 bits): strict mode - * bits 21-31 (10 bits): other - */ - - CborValidateShortestIntegrals = 0x0001, - CborValidateShortestFloatingPoint = 0x0002, - CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint, - CborValidateNoIndeterminateLength = 0x0100, - CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength, - - CborValidateCanonicalFormat = 0x0fff, - - CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted, - CborValidateTagUse = 0x2000, - CborValidateUtf8 = 0x4000, - - CborValidateStrictMode = 0xfff00, - - CborValidateMapKeysAreString = 0x100000, - CborValidateNoUndefined = 0x200000, - CborValidateNoTags = 0x400000, - CborValidateFiniteFloatingPoint = 0x800000, - /* unused = 0x1000000, */ - /* unused = 0x2000000, */ - - CborValidateNoUnknownSimpleTypesSA = 0x4000000, - CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA, - CborValidateNoUnknownTagsSA = 0x10000000, - CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA, - CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR, - - CborValidateCompleteData = (int)0x80000000, - - CborValidateStrictest = (int)~0U, - CborValidateBasic = 0 -}; - -CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags); - -/* Human-readable (dump) API */ - -enum CborPrettyFlags { - CborPrettyNumericEncodingIndicators = 0x01, - CborPrettyTextualEncodingIndicators = 0, - - CborPrettyIndicateIndeterminateLength = 0x02, - CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */ - CborPrettyIndicateOverlongNumbers = 0x04, - - CborPrettyShowStringFragments = 0x100, - CborPrettyMergeStringFragments = 0, - - CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength -}; - -typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...) -#ifdef __GNUC__ - __attribute__((__format__(printf, 2, 3))) -#endif -; - -CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags); - -/* The following API requires a hosted C implementation (uses FILE*) */ -#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1 -CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags); -CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value); -CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value) -{ - CborValue copy = *value; - return cbor_value_to_pretty_advance_flags(out, ©, CborPrettyDefaultFlags); -} -#endif /* __STDC_HOSTED__ check */ - -#ifdef __cplusplus -} -#endif - -#endif /* CBOR_H */ - diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder.c deleted file mode 100644 index fb39137..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder.c +++ /dev/null @@ -1,645 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include -#include - -/** - * \defgroup CborEncoding Encoding to CBOR - * \brief Group of functions used to encode data to CBOR. - * - * CborEncoder is used to encode data into a CBOR stream. The outermost - * CborEncoder is initialized by calling cbor_encoder_init(), with the buffer - * where the CBOR stream will be stored. The outermost CborEncoder is usually - * used to encode exactly one item, most often an array or map. It is possible - * to encode more than one item, but care must then be taken on the decoder - * side to ensure the state is reset after each item was decoded. - * - * Nested CborEncoder objects are created using cbor_encoder_create_array() and - * cbor_encoder_create_map(), later closed with cbor_encoder_close_container() - * or cbor_encoder_close_container_checked(). The pairs of creation and closing - * must be exactly matched and their parameters are always the same. - * - * CborEncoder writes directly to the user-supplied buffer, without extra - * buffering. CborEncoder does not allocate memory and CborEncoder objects are - * usually created on the stack of the encoding functions. - * - * The example below initializes a CborEncoder object with a buffer and encodes - * a single integer. - * - * \code - * uint8_t buf[16]; - * CborEncoder encoder; - * cbor_encoder_init(&encoder, buf, sizeof(buf), 0); - * cbor_encode_int(&encoder, some_value); - * \endcode - * - * As explained before, usually the outermost CborEncoder object is used to add - * one array or map, which in turn contains multiple elements. The example - * below creates a CBOR map with one element: a key "foo" and a boolean value. - * - * \code - * uint8_t buf[16]; - * CborEncoder encoder, mapEncoder; - * cbor_encoder_init(&encoder, buf, sizeof(buf), 0); - * cbor_encoder_create_map(&encoder, &mapEncoder, 1); - * cbor_encode_text_stringz(&mapEncoder, "foo"); - * cbor_encode_boolean(&mapEncoder, some_value); - * cbor_encoder_close_container(&encoder, &mapEncoder); - * \endcode - * - *

Error checking and buffer size

- * - * All functions operating on CborEncoder return a condition of type CborError. - * If the encoding was successful, they return CborNoError. Some functions do - * extra checking on the input provided and may return some other error - * conditions (for example, cbor_encode_simple_value() checks that the type is - * of the correct type). - * - * In addition, all functions check whether the buffer has enough bytes to - * encode the item being appended. If that is not possible, they return - * CborErrorOutOfMemory. - * - * It is possible to continue with the encoding of data past the first function - * that returns CborErrorOutOfMemory. CborEncoder functions will not overrun - * the buffer, but will instead count how many more bytes are needed to - * complete the encoding. At the end, you can obtain that count by calling - * cbor_encoder_get_extra_bytes_needed(). - * - * \section1 Finalizing the encoding - * - * Once all items have been appended and the containers have all been properly - * closed, the user-supplied buffer will contain the CBOR stream and may be - * immediately used. To obtain the size of the buffer, call - * cbor_encoder_get_buffer_size() with the original buffer pointer. - * - * The example below illustrates how one can encode an item with error checking - * and then pass on the buffer for network sending. - * - * \code - * uint8_t buf[16]; - * CborError err; - * CborEncoder encoder, mapEncoder; - * cbor_encoder_init(&encoder, buf, sizeof(buf), 0); - * err = cbor_encoder_create_map(&encoder, &mapEncoder, 1); - * if (err) - * return err; - * err = cbor_encode_text_stringz(&mapEncoder, "foo"); - * if (err) - * return err; - * err = cbor_encode_boolean(&mapEncoder, some_value); - * if (err) - * return err; - * err = cbor_encoder_close_container_checked(&encoder, &mapEncoder); - * if (err) - * return err; - * - * size_t len = cbor_encoder_get_buffer_size(&encoder, buf); - * send_payload(buf, len); - * return CborNoError; - * \endcode - * - * Finally, the example below expands on the one above and also - * deals with dynamically growing the buffer if the initial allocation wasn't - * big enough. Note the two places where the error checking was replaced with - * an cbor_assertion, showing where the author assumes no error can occur. - * - * \code - * uint8_t *encode_string_array(const char **strings, int n, size_t *bufsize) - * { - * CborError err; - * CborEncoder encoder, arrayEncoder; - * size_t size = 256; - * uint8_t *buf = NULL; - * - * while (1) { - * int i; - * size_t more_bytes; - * uint8_t *nbuf = realloc(buf, size); - * if (nbuf == NULL) - * goto error; - * buf = nbuf; - * - * cbor_encoder_init(&encoder, buf, size, 0); - * err = cbor_encoder_create_array(&encoder, &arrayEncoder, n); - * cbor_assert(!err); // can't fail, the buffer is always big enough - * - * for (i = 0; i < n; ++i) { - * err = cbor_encode_text_stringz(&arrayEncoder, strings[i]); - * if (err && err != CborErrorOutOfMemory) - * goto error; - * } - * - * err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder); - * cbor_assert(!err); // shouldn't fail! - * - * more_bytes = cbor_encoder_get_extra_bytes_needed(encoder); - * if (more_size) { - * // buffer wasn't big enough, try again - * size += more_bytes; - * continue; - * } - * - * *bufsize = cbor_encoder_get_buffer_size(encoder, buf); - * return buf; - * } - * error: - * free(buf); - * return NULL; - * } - * \endcode - */ - -/** - * \addtogroup CborEncoding - * @{ - */ - -/** - * \struct CborEncoder - * Structure used to encode to CBOR. - */ - -/** - * Initializes a CborEncoder structure \a encoder by pointing it to buffer \a - * buffer of size \a size. The \a flags field is currently unused and must be - * zero. - */ -void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags) -{ - encoder->data.ptr = buffer; - encoder->end = buffer + size; - encoder->remaining = 2; - encoder->flags = flags; -} - -static inline void put16(void *where, uint16_t v) -{ - uint16_t v_be = cbor_htons(v); - memcpy(where, &v_be, sizeof(v_be)); -} - -/* Note: Since this is currently only used in situations where OOM is the only - * valid error, we KNOW this to be true. Thus, this function now returns just 'true', - * but if in the future, any function starts returning a non-OOM error, this will need - * to be changed to the test. At the moment, this is done to prevent more branches - * being created in the tinycbor output */ -static inline bool isOomError(CborError err) -{ - (void) err; - return true; -} - -static inline void put32(void *where, uint32_t v) -{ - uint32_t v_be = cbor_htonl(v); - memcpy(where, &v_be, sizeof(v_be)); -} - -static inline void put64(void *where, uint64_t v) -{ - uint64_t v_be = cbor_htonll(v); - memcpy(where, &v_be, sizeof(v_be)); -} - -static inline bool would_overflow(CborEncoder *encoder, size_t len) -{ - ptrdiff_t remaining = (ptrdiff_t)encoder->end; - remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed; - remaining -= (ptrdiff_t)len; - return unlikely(remaining < 0); -} - -static inline void advance_ptr(CborEncoder *encoder, size_t n) -{ - if (encoder->end) - encoder->data.ptr += n; - else - encoder->data.bytes_needed += n; -} - -static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) -{ - if (would_overflow(encoder, len)) { - if (encoder->end != NULL) { - len -= encoder->end - encoder->data.ptr; - encoder->end = NULL; - encoder->data.bytes_needed = 0; - } - - advance_ptr(encoder, len); - return CborErrorOutOfMemory; - } - - memcpy(encoder->data.ptr, data, len); - encoder->data.ptr += len; - return CborNoError; -} - -static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) -{ - return append_to_buffer(encoder, &byte, 1); -} - -static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) -{ - /* Little-endian would have been so much more convenient here: - * We could just write at the beginning of buf but append_to_buffer - * only the necessary bytes. - * Since it has to be big endian, do it the other way around: - * write from the end. */ - uint64_t buf[2]; - uint8_t *const bufend = (uint8_t *)buf + sizeof(buf); - uint8_t *bufstart = bufend - 1; - put64(buf + 1, ui); /* we probably have a bunch of zeros in the beginning */ - - if (ui < Value8Bit) { - *bufstart += shiftedMajorType; - } else { - uint8_t more = 0; - if (ui > 0xffU) - ++more; - if (ui > 0xffffU) - ++more; - if (ui > 0xffffffffU) - ++more; - bufstart -= (size_t)1 << more; - *bufstart = shiftedMajorType + Value8Bit + more; - } - - return append_to_buffer(encoder, bufstart, bufend - bufstart); -} - -static inline void saturated_decrement(CborEncoder *encoder) -{ - if (encoder->remaining) - --encoder->remaining; -} - -static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) -{ - saturated_decrement(encoder); - return encode_number_no_update(encoder, ui, shiftedMajorType); -} - -/** - * Appends the unsigned 64-bit integer \a value to the CBOR stream provided by - * \a encoder. - * - * \sa cbor_encode_negative_int, cbor_encode_int - */ -CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value) -{ - return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift); -} - -/** - * Appends the negative 64-bit integer whose absolute value is \a - * absolute_value to the CBOR stream provided by \a encoder. - * - * If the value \a absolute_value is zero, this function encodes -2^64. - * - * \sa cbor_encode_uint, cbor_encode_int - */ -CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value) -{ - return encode_number(encoder, absolute_value - 1, NegativeIntegerType << MajorTypeShift); -} - -/** - * Appends the signed 64-bit integer \a value to the CBOR stream provided by - * \a encoder. - * - * \sa cbor_encode_negative_int, cbor_encode_uint - */ -CborError cbor_encode_int(CborEncoder *encoder, int64_t value) -{ - /* adapted from code in RFC 7049 appendix C (pseudocode) */ - uint64_t ui = value >> 63; /* extend sign to whole length */ - uint8_t majorType = ui & 0x20; /* extract major type */ - ui ^= value; /* complement negatives */ - return encode_number(encoder, ui, majorType); -} - -/** - * Appends the CBOR Simple Type of value \a value to the CBOR stream provided by - * \a encoder. - * - * This function may return error CborErrorIllegalSimpleType if the \a value - * variable contains a number that is not a valid simple type. - */ -CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value) -{ -#ifndef CBOR_ENCODER_NO_CHECK_USER - /* check if this is a valid simple type */ - if (value >= HalfPrecisionFloat && value <= Break) - return CborErrorIllegalSimpleType; -#endif - return encode_number(encoder, value, SimpleTypesType << MajorTypeShift); -} - -/** - * Appends the floating-point value of type \a fpType and pointed to by \a - * value to the CBOR stream provided by \a encoder. The value of \a fpType must - * be one of CborHalfFloatType, CborFloatType or CborDoubleType, otherwise the - * behavior of this function is undefined. - * - * This function is useful for code that needs to pass through floating point - * values but does not wish to have the actual floating-point code. - * - * \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double - */ -CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value) -{ - unsigned size; - uint8_t buf[1 + sizeof(uint64_t)]; - cbor_assert(fpType == CborHalfFloatType || fpType == CborFloatType || fpType == CborDoubleType); - buf[0] = fpType; - - size = 2U << (fpType - CborHalfFloatType); - if (size == 8) - put64(buf + 1, *(const uint64_t*)value); - else if (size == 4) - put32(buf + 1, *(const uint32_t*)value); - else - put16(buf + 1, *(const uint16_t*)value); - saturated_decrement(encoder); - return append_to_buffer(encoder, buf, size + 1); -} - -/** - * Appends the CBOR tag \a tag to the CBOR stream provided by \a encoder. - * - * \sa CborTag - */ -CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag) -{ - /* tags don't count towards the number of elements in an array or map */ - return encode_number_no_update(encoder, tag, TagType << MajorTypeShift); -} - -static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string) -{ - CborError err = encode_number(encoder, length, shiftedMajorType); - if (err && !isOomError(err)) - return err; - return append_to_buffer(encoder, string, length); -} - -/** - * \fn CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) - * - * Appends the null-terminated text string \a string to the CBOR stream - * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but - * TinyCBOR makes no verification of correctness. The terminating null is not - * included in the stream. - * - * \sa cbor_encode_text_string, cbor_encode_byte_string - */ - -/** - * Appends the byte string \a string of length \a length to the CBOR stream - * provided by \a encoder. CBOR byte strings are arbitrary raw data. - * - * \sa cbor_encode_text_stringz, cbor_encode_text_string - */ -CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length) -{ - return encode_string(encoder, length, ByteStringType << MajorTypeShift, string); -} - -/** - * Appends the text string \a string of length \a length to the CBOR stream - * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but - * TinyCBOR makes no verification of correctness. - * - * \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string - */ -CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length) -{ - return encode_string(encoder, length, TextStringType << MajorTypeShift, string); -} - -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType) -{ - CborError err; - container->data.ptr = encoder->data.ptr; - container->end = encoder->end; - saturated_decrement(encoder); - container->remaining = length + 1; /* overflow ok on CborIndefiniteLength */ - - cbor_static_assert(((MapType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == CborIteratorFlag_ContainerIsMap); - cbor_static_assert(((ArrayType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == 0); - container->flags = shiftedMajorType & CborIteratorFlag_ContainerIsMap; - - if (length == CborIndefiniteLength) { - container->flags |= CborIteratorFlag_UnknownLength; - err = append_byte_to_buffer(container, shiftedMajorType + IndefiniteLength); - } else { - if (shiftedMajorType & CborIteratorFlag_ContainerIsMap) - container->remaining += length; - err = encode_number_no_update(container, length, shiftedMajorType); - } - return err; -} - -/** - * Creates a CBOR array in the CBOR stream provided by \a encoder and - * initializes \a arrayEncoder so that items can be added to the array using - * the CborEncoder functions. The array must be terminated by calling either - * cbor_encoder_close_container() or cbor_encoder_close_container_checked() - * with the same \a encoder and \a arrayEncoder parameters. - * - * The number of items inserted into the array must be exactly \a length items, - * otherwise the stream is invalid. If the number of items is not known when - * creating the array, the constant \ref CborIndefiniteLength may be passed as - * length instead. - * - * \sa cbor_encoder_create_map - */ -CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length) -{ - return create_container(encoder, arrayEncoder, length, ArrayType << MajorTypeShift); -} - -/** - * Creates a CBOR map in the CBOR stream provided by \a encoder and - * initializes \a mapEncoder so that items can be added to the map using - * the CborEncoder functions. The map must be terminated by calling either - * cbor_encoder_close_container() or cbor_encoder_close_container_checked() - * with the same \a encoder and \a mapEncoder parameters. - * - * The number of pair of items inserted into the map must be exactly \a length - * items, otherwise the stream is invalid. If the number is not known - * when creating the map, the constant \ref CborIndefiniteLength may be passed as - * length instead. - * - * \b{Implementation limitation:} TinyCBOR cannot encode more than SIZE_MAX/2 - * key-value pairs in the stream. If the length \a length is larger than this - * value (and is not \ref CborIndefiniteLength), this function returns error - * CborErrorDataTooLarge. - * - * \sa cbor_encoder_create_array - */ -CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length) -{ - if (length != CborIndefiniteLength && length > SIZE_MAX / 2) - return CborErrorDataTooLarge; - return create_container(encoder, mapEncoder, length, MapType << MajorTypeShift); -} - -/** - * Closes the CBOR container (array or map) provided by \a containerEncoder and - * updates the CBOR stream provided by \a encoder. Both parameters must be the - * same as were passed to cbor_encoder_create_array() or - * cbor_encoder_create_map(). - * - * Since version 0.5, this function verifies that the number of items (or pairs - * of items, in the case of a map) was correct. It is no longer necessary to call - * cbor_encoder_close_container_checked() instead. - * - * \sa cbor_encoder_create_array(), cbor_encoder_create_map() - */ -CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder) -{ - // synchronise buffer state with that of the container - encoder->end = containerEncoder->end; - encoder->data = containerEncoder->data; - - if (containerEncoder->flags & CborIteratorFlag_UnknownLength) - return append_byte_to_buffer(encoder, BreakByte); - - if (containerEncoder->remaining != 1) - return containerEncoder->remaining == 0 ? CborErrorTooManyItems : CborErrorTooFewItems; - - if (!encoder->end) - return CborErrorOutOfMemory; /* keep the state */ - - return CborNoError; -} - -/** - * \fn CborError cbor_encode_boolean(CborEncoder *encoder, bool value) - * - * Appends the boolean value \a value to the CBOR stream provided by \a encoder. - */ - -/** - * \fn CborError cbor_encode_null(CborEncoder *encoder) - * - * Appends the CBOR type representing a null value to the CBOR stream provided - * by \a encoder. - * - * \sa cbor_encode_undefined() - */ - -/** - * \fn CborError cbor_encode_undefined(CborEncoder *encoder) - * - * Appends the CBOR type representing an undefined value to the CBOR stream - * provided by \a encoder. - * - * \sa cbor_encode_null() - */ - -/** - * \fn CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) - * - * Appends the IEEE 754 half-precision (16-bit) floating point value pointed to - * by \a value to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double() - */ - -/** - * \fn CborError cbor_encode_float(CborEncoder *encoder, float value) - * - * Appends the IEEE 754 single-precision (32-bit) floating point value \a value - * to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double() - */ - -/** - * \fn CborError cbor_encode_double(CborEncoder *encoder, double value) - * - * Appends the IEEE 754 double-precision (64-bit) floating point value \a value - * to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float() - */ - -/** - * \fn size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) - * - * Returns the total size of the buffer starting at \a buffer after the - * encoding finished without errors. The \a encoder and \a buffer arguments - * must be the same as supplied to cbor_encoder_init(). - * - * If the encoding process had errors, the return value of this function is - * meaningless. If the only errors were CborErrorOutOfMemory, instead use - * cbor_encoder_get_extra_bytes_needed() to find out by how much to grow the - * buffer before encoding again. - * - * See \ref CborEncoding for an example of using this function. - * - * \sa cbor_encoder_init(), cbor_encoder_get_extra_bytes_needed(), CborEncoding - */ - -/** - * \fn size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) - * - * Returns how many more bytes the original buffer supplied to - * cbor_encoder_init() needs to be extended by so that no CborErrorOutOfMemory - * condition will happen for the encoding. If the buffer was big enough, this - * function returns 0. The \a encoder must be the original argument as passed - * to cbor_encoder_init(). - * - * This function is usually called after an encoding sequence ended with one or - * more CborErrorOutOfMemory errors, but no other error. If any other error - * happened, the return value of this function is meaningless. - * - * See \ref CborEncoding for an example of using this function. - * - * \sa cbor_encoder_init(), cbor_encoder_get_buffer_size(), CborEncoding - */ - -/** @} */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder_close_container_checked.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder_close_container_checked.c deleted file mode 100644 index 5661e4d..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborencoder_close_container_checked.c +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" - -/** - * \addtogroup CborEncoding - * @{ - */ - -/** - * @deprecated - * - * Closes the CBOR container (array or map) provided by \a containerEncoder and - * updates the CBOR stream provided by \a encoder. Both parameters must be the - * same as were passed to cbor_encoder_create_array() or - * cbor_encoder_create_map(). - * - * Prior to version 0.5, cbor_encoder_close_container() did not check the - * number of items added. Since that version, it does and now - * cbor_encoder_close_container_checked() is no longer needed. - * - * \sa cbor_encoder_create_array(), cbor_encoder_create_map() - */ -CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder) -{ - return cbor_encoder_close_container(encoder, containerEncoder); -} - -/** @} */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborerrorstrings.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborerrorstrings.c deleted file mode 100644 index 3fe3a98..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborerrorstrings.c +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include "cbor.h" - -#ifndef _ -# define _(msg) msg -#endif - -/** - * \enum CborError - * \ingroup CborGlobals - * The CborError enum contains the possible error values used by the CBOR encoder and decoder. - * - * TinyCBOR functions report success by returning CborNoError, or one error - * condition by returning one of the values below. One exception is the - * out-of-memory condition (CborErrorOutOfMemory), which the functions for \ref - * CborEncoding may report in bit-wise OR with other conditions. - * - * This technique allows code to determine whether the only error condition was - * a lack of buffer space, which may not be a fatal condition if the buffer can - * be resized. Additionally, the functions for \ref CborEncoding may continue - * to be used even after CborErrorOutOfMemory is returned, and instead they - * will simply calculate the extra space needed. - * - * \value CborNoError No error occurred - * \omitvalue CborUnknownError - * \value CborErrorUnknownLength Request for the length of an array, map or string whose length is not provided in the CBOR stream - * \value CborErrorAdvancePastEOF Not enough data in the stream to decode item (decoding would advance past end of stream) - * \value CborErrorIO An I/O error occurred, probably due to an out-of-memory situation - * \value CborErrorGarbageAtEnd Bytes exist past the end of the CBOR stream - * \value CborErrorUnexpectedEOF End of stream reached unexpectedly - * \value CborErrorUnexpectedBreak A CBOR break byte was found where not expected - * \value CborErrorUnknownType An unknown type (future extension to CBOR) was found in the stream - * \value CborErrorIllegalType An invalid type was found while parsing a chunked CBOR string - * \value CborErrorIllegalNumber An illegal initial byte (encoding unspecified additional information) was found - * \value CborErrorIllegalSimpleType An illegal encoding of a CBOR Simple Type of value less than 32 was found - * \omitvalue CborErrorUnknownSimpleType - * \omitvalue CborErrorUnknownTag - * \omitvalue CborErrorInappropriateTagForType - * \omitvalue CborErrorDuplicateObjectKeys - * \value CborErrorInvalidUtf8TextString Illegal UTF-8 encoding found while parsing CBOR Text String - * \value CborErrorTooManyItems Too many items were added to CBOR map or array of pre-determined length - * \value CborErrorTooFewItems Too few items were added to CBOR map or array of pre-determined length - * \value CborErrorDataTooLarge Data item size exceeds TinyCBOR's implementation limits - * \value CborErrorNestingTooDeep Data item nesting exceeds TinyCBOR's implementation limits - * \omitvalue CborErrorUnsupportedType - * \value CborErrorJsonObjectKeyIsAggregate Conversion to JSON failed because the key in a map is a CBOR map or array - * \value CborErrorJsonObjectKeyNotString Conversion to JSON failed because the key in a map is not a text string - * \value CborErrorOutOfMemory During CBOR encoding, the buffer provided is insufficient for encoding the data item; - * in other situations, TinyCBOR failed to allocate memory - * \value CborErrorInternalError An internal error occurred in TinyCBOR - */ - -/** - * \ingroup CborGlobals - * Returns the error string corresponding to the CBOR error condition \a error. - */ -const char *cbor_error_string(CborError error) -{ - switch (error) { - case CborNoError: - return ""; - - case CborUnknownError: - return _("unknown error"); - - case CborErrorOutOfMemory: - return _("out of memory/need more memory"); - - case CborErrorUnknownLength: - return _("unknown length (attempted to get the length of a map/array/string of indeterminate length"); - - case CborErrorAdvancePastEOF: - return _("attempted to advance past EOF"); - - case CborErrorIO: - return _("I/O error"); - - case CborErrorGarbageAtEnd: - return _("garbage after the end of the content"); - - case CborErrorUnexpectedEOF: - return _("unexpected end of data"); - - case CborErrorUnexpectedBreak: - return _("unexpected 'break' byte"); - - case CborErrorUnknownType: - return _("illegal byte (encodes future extension type)"); - - case CborErrorIllegalType: - return _("mismatched string type in chunked string"); - - case CborErrorIllegalNumber: - return _("illegal initial byte (encodes unspecified additional information)"); - - case CborErrorIllegalSimpleType: - return _("illegal encoding of simple type smaller than 32"); - - case CborErrorUnknownSimpleType: - return _("unknown simple type"); - - case CborErrorUnknownTag: - return _("unknown tag"); - - case CborErrorInappropriateTagForType: - return _("inappropriate tag for type"); - - case CborErrorDuplicateObjectKeys: - return _("duplicate keys in object"); - - case CborErrorInvalidUtf8TextString: - return _("invalid UTF-8 content in string"); - - case CborErrorExcludedType: - return _("excluded type found"); - - case CborErrorExcludedValue: - return _("excluded value found"); - - case CborErrorImproperValue: - case CborErrorOverlongEncoding: - return _("value encoded in non-canonical form"); - - case CborErrorMapKeyNotString: - case CborErrorJsonObjectKeyNotString: - return _("key in map is not a string"); - - case CborErrorMapNotSorted: - return _("map is not sorted"); - - case CborErrorMapKeysNotUnique: - return _("map keys are not unique"); - - case CborErrorTooManyItems: - return _("too many items added to encoder"); - - case CborErrorTooFewItems: - return _("too few items added to encoder"); - - case CborErrorDataTooLarge: - return _("internal error: data too large"); - - case CborErrorNestingTooDeep: - return _("internal error: too many nested containers found in recursive function"); - - case CborErrorUnsupportedType: - return _("unsupported type"); - - case CborErrorJsonObjectKeyIsAggregate: - return _("conversion to JSON failed: key in object is an array or map"); - - case CborErrorJsonNotImplemented: - return _("conversion to JSON failed: open_memstream unavailable"); - - case CborErrorInternalError: - return _("internal error"); - } - return cbor_error_string(CborUnknownError); -} diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborinternal_p.h b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborinternal_p.h deleted file mode 100644 index a85a929..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborinternal_p.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBORINTERNAL_P_H -#define CBORINTERNAL_P_H - -#include "compilersupport_p.h" - -#ifndef CBOR_NO_FLOATING_POINT -# include -# include -#else -# ifndef CBOR_NO_HALF_FLOAT_TYPE -# define CBOR_NO_HALF_FLOAT_TYPE 1 -# endif -#endif - -#ifndef CBOR_NO_HALF_FLOAT_TYPE -# ifdef __F16C__ -# include -static inline unsigned short encode_half(double val) -{ - return _cvtss_sh((float)val, 3); -} -static inline double decode_half(unsigned short half) -{ - return _cvtsh_ss(half); -} -# else -/* software implementation of float-to-fp16 conversions */ -static inline unsigned short encode_half(double val) -{ - uint64_t v; - int sign, exp, mant; - memcpy(&v, &val, sizeof(v)); - sign = v >> 63 << 15; - exp = (v >> 52) & 0x7ff; - mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */ - exp -= 1023; - if (exp == 1024) { - /* infinity or NaN */ - exp = 16; - mant >>= 1; - } else if (exp >= 16) { - /* overflow, as largest number */ - exp = 15; - mant = 1023; - } else if (exp >= -14) { - /* regular normal */ - } else if (exp >= -24) { - /* subnormal */ - mant |= 1024; - mant >>= -(exp + 14); - exp = -15; - } else { - /* underflow, make zero */ - return 0; - } - - /* safe cast here as bit operations above guarantee not to overflow */ - return (unsigned short)(sign | ((exp + 15) << 10) | mant); -} - -/* this function was copied & adapted from RFC 7049 Appendix D */ -static inline double decode_half(unsigned short half) -{ - int exp = (half >> 10) & 0x1f; - int mant = half & 0x3ff; - double val; - if (exp == 0) val = ldexp(mant, -24); - else if (exp != 31) val = ldexp(mant + 1024, exp - 25); - else val = mant == 0 ? INFINITY : NAN; - return half & 0x8000 ? -val : val; -} -# endif -#endif /* CBOR_NO_HALF_FLOAT_TYPE */ - -#ifndef CBOR_INTERNAL_API -# define CBOR_INTERNAL_API -#endif - -#ifndef CBOR_PARSER_MAX_RECURSIONS -# define CBOR_PARSER_MAX_RECURSIONS 1024 -#endif - -/* - * CBOR Major types - * Encoded in the high 3 bits of the descriptor byte - * See http://tools.ietf.org/html/rfc7049#section-2.1 - */ -typedef enum CborMajorTypes { - UnsignedIntegerType = 0U, - NegativeIntegerType = 1U, - ByteStringType = 2U, - TextStringType = 3U, - ArrayType = 4U, - MapType = 5U, /* a.k.a. object */ - TagType = 6U, - SimpleTypesType = 7U -} CborMajorTypes; - -/* - * CBOR simple and floating point types - * Encoded in the low 8 bits of the descriptor byte when the - * Major Type is 7. - */ -typedef enum CborSimpleTypes { - FalseValue = 20, - TrueValue = 21, - NullValue = 22, - UndefinedValue = 23, - SimpleTypeInNextByte = 24, /* not really a simple type */ - HalfPrecisionFloat = 25, /* ditto */ - SinglePrecisionFloat = 26, /* ditto */ - DoublePrecisionFloat = 27, /* ditto */ - Break = 31 -} CborSimpleTypes; - -enum { - SmallValueBitLength = 5U, - SmallValueMask = (1U << SmallValueBitLength) - 1, /* 31 */ - Value8Bit = 24U, - Value16Bit = 25U, - Value32Bit = 26U, - Value64Bit = 27U, - IndefiniteLength = 31U, - - MajorTypeShift = SmallValueBitLength, - MajorTypeMask = (int) (~0U << MajorTypeShift), - - BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift) -}; - -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len); -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it); -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, - size_t *len, CborValue *next); - - -#endif /* CBORINTERNAL_P_H */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborjson.h b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborjson.h deleted file mode 100644 index 8ff27b9..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborjson.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBORJSON_H -#define CBORJSON_H - -#include "cbor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Conversion to JSON */ -enum CborToJsonFlags -{ - CborConvertAddMetadata = 1, - CborConvertTagsToObjects = 2, - CborConvertIgnoreTags = 0, - - CborConvertObeyByteStringTags = 0, - CborConvertByteStringsToBase64Url = 4, - - CborConvertRequireMapStringKeys = 0, - CborConvertStringifyMapKeys = 8, - - CborConvertDefaultFlags = 0 -}; - -CBOR_API CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags); -CBOR_INLINE_API CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) -{ - CborValue copy = *value; - return cbor_value_to_json_advance(out, ©, flags); -} - -#ifdef __cplusplus -} -#endif - -#endif /* CBORJSON_H */ - diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser.c deleted file mode 100644 index 60ce574..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser.c +++ /dev/null @@ -1,1449 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include - -/** - * \defgroup CborParsing Parsing CBOR streams - * \brief Group of functions used to parse CBOR streams. - * - * TinyCBOR provides functions for pull-based stream parsing of a CBOR-encoded - * payload. The main data type for the parsing is a CborValue, which behaves - * like an iterator and can be used to extract the encoded data. It is first - * initialized with a call to cbor_parser_init() and is usually used to extract - * exactly one item, most often an array or map. - * - * Nested CborValue objects can be parsed using cbor_value_enter_container(). - * Each call to cbor_value_enter_container() must be matched by a call to - * cbor_value_leave_container(), with the exact same parameters. - * - * The example below initializes a CborParser object, begins the parsing with a - * CborValue and decodes a single integer: - * - * \code - * int extract_int(const uint8_t *buffer, size_t len) - * { - * CborParser parser; - * CborValue value; - * int result; - * cbor_parser_init(buffer, len, 0, &parser, &value); - * cbor_value_get_int(&value, &result); - * return result; - * } - * \endcode - * - * The code above does no error checking, which means it assumes the data comes - * from a source trusted to send one properly-encoded integer. The following - * example does the exact same operation, but includes error checking and - * returns 0 on parsing failure: - * - * \code - * int extract_int(const uint8_t *buffer, size_t len) - * { - * CborParser parser; - * CborValue value; - * int result; - * if (cbor_parser_init(buffer, len, 0, &parser, &value) != CborNoError) - * return 0; - * if (!cbor_value_is_integer(&value) || - * cbor_value_get_int(&value, &result) != CborNoError) - * return 0; - * return result; - * } - * \endcode - * - * Note, in the example above, that one can't distinguish a parsing failure - * from an encoded value of zero. Reporting a parsing error is left as an - * exercise to the reader. - * - * The code above does not execute a range-check either: it is possible that - * the value decoded from the CBOR stream encodes a number larger than what can - * be represented in a variable of type \c{int}. If detecting that case is - * important, the code should call cbor_value_get_int_checked() instead. - * - *

Memory and parsing constraints

- * - * TinyCBOR is designed to run with little memory and with minimal overhead. - * Except where otherwise noted, the parser functions always run on constant - * time (O(1)), do not recurse and never allocate memory (thus, stack usage is - * bounded and is O(1)). - * - *

Error handling and preconditions

- * - * All functions operating on a CborValue return a CborError condition, with - * CborNoError standing for the normal situation in which no parsing error - * occurred. All functions may return parsing errors in case the stream cannot - * be decoded properly, be it due to corrupted data or due to reaching the end - * of the input buffer. - * - * Error conditions must not be ignored. All decoder functions have undefined - * behavior if called after an error has been reported, and may crash. - * - * Some functions are also documented to have preconditions, like - * cbor_value_get_int() requiring that the input be an integral value. - * Violation of preconditions also results in undefined behavior and the - * program may crash. - */ - -/** - * \addtogroup CborParsing - * @{ - */ - -/** - * \struct CborValue - * - * This type contains one value parsed from the CBOR stream. Each CborValue - * behaves as an iterator in a StAX-style parser. - * - * \if privatedocs - * Implementation details: the CborValue contains these fields: - * \list - * \li ptr: pointer to the actual data - * \li flags: flags from the decoder - * \li extra: partially decoded integer value (0, 1 or 2 bytes) - * \li remaining: remaining items in this collection after this item or UINT32_MAX if length is unknown - * \endlist - * \endif - */ - -static inline uint16_t get16(const uint8_t *ptr) -{ - uint16_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohs(result); -} - -static inline uint32_t get32(const uint8_t *ptr) -{ - uint32_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohl(result); -} - -static inline uint64_t get64(const uint8_t *ptr) -{ - uint64_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohll(result); -} - -CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len) -{ - size_t bytesNeeded; - uint8_t additional_information = **ptr & SmallValueMask; - ++*ptr; - if (additional_information < Value8Bit) { - *len = additional_information; - return CborNoError; - } - if (unlikely(additional_information > Value64Bit)) - return CborErrorIllegalNumber; - - bytesNeeded = (size_t)(1 << (additional_information - Value8Bit)); - if (unlikely(bytesNeeded > (size_t)(end - *ptr))) { - return CborErrorUnexpectedEOF; - } else if (bytesNeeded == 1) { - *len = (uint8_t)(*ptr)[0]; - } else if (bytesNeeded == 2) { - *len = get16(*ptr); - } else if (bytesNeeded == 4) { - *len = get32(*ptr); - } else { - *len = get64(*ptr); - } - *ptr += bytesNeeded; - return CborNoError; -} - -static CborError extract_length(const CborParser *parser, const uint8_t **ptr, size_t *len) -{ - uint64_t v; - CborError err = _cbor_value_extract_number(ptr, parser->end, &v); - if (err) { - *len = 0; - return err; - } - - *len = (size_t)v; - if (v != *len) - return CborErrorDataTooLarge; - return CborNoError; -} - -static bool is_fixed_type(uint8_t type) -{ - return type != CborTextStringType && type != CborByteStringType && type != CborArrayType && - type != CborMapType; -} - -static CborError preparse_value(CborValue *it) -{ - enum { - /* flags to keep */ - FlagsToKeep = CborIteratorFlag_ContainerIsMap | CborIteratorFlag_NextIsMapKey - }; - const CborParser *parser = it->parser; - it->type = CborInvalidType; - - /* are we at the end? */ - if (it->ptr == parser->end) - return CborErrorUnexpectedEOF; - - uint8_t descriptor = *it->ptr; - uint8_t type = descriptor & MajorTypeMask; - it->type = type; - it->flags &= FlagsToKeep; - it->extra = (descriptor &= SmallValueMask); - - if (descriptor > Value64Bit) { - if (unlikely(descriptor != IndefiniteLength)) - return type == CborSimpleType ? CborErrorUnknownType : CborErrorIllegalNumber; - if (likely(!is_fixed_type(type))) { - /* special case */ - it->flags |= CborIteratorFlag_UnknownLength; - it->type = type; - return CborNoError; - } - return type == CborSimpleType ? CborErrorUnexpectedBreak : CborErrorIllegalNumber; - } - - size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit)); - if (bytesNeeded + 1 > (size_t)(parser->end - it->ptr)) - return CborErrorUnexpectedEOF; - - uint8_t majortype = type >> MajorTypeShift; - if (majortype == NegativeIntegerType) { - it->flags |= CborIteratorFlag_NegativeInteger; - it->type = CborIntegerType; - } else if (majortype == SimpleTypesType) { - switch (descriptor) { - case FalseValue: - it->extra = false; - it->type = CborBooleanType; - break; - - case SinglePrecisionFloat: - case DoublePrecisionFloat: - it->flags |= CborIteratorFlag_IntegerValueTooLarge; - /* fall through */ - case TrueValue: - case NullValue: - case UndefinedValue: - case HalfPrecisionFloat: - it->type = *it->ptr; - break; - - case SimpleTypeInNextByte: - it->extra = (uint8_t)it->ptr[1]; -#ifndef CBOR_PARSER_NO_STRICT_CHECKS - if (unlikely(it->extra < 32)) { - it->type = CborInvalidType; - return CborErrorIllegalSimpleType; - } -#endif - break; - - case 28: - case 29: - case 30: - case Break: - cbor_assert(false); /* these conditions can't be reached */ - return CborErrorUnexpectedBreak; - } - return CborNoError; - } - - /* try to decode up to 16 bits */ - if (descriptor < Value8Bit) - return CborNoError; - - if (descriptor == Value8Bit) - it->extra = (uint8_t)it->ptr[1]; - else if (descriptor == Value16Bit) - it->extra = get16(it->ptr + 1); - else - it->flags |= CborIteratorFlag_IntegerValueTooLarge; /* Value32Bit or Value64Bit */ - return CborNoError; -} - -static CborError preparse_next_value_nodecrement(CborValue *it) -{ - if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) { - /* end of map or array */ - if ((it->flags & CborIteratorFlag_ContainerIsMap && it->flags & CborIteratorFlag_NextIsMapKey) - || it->type == CborTagType) { - /* but we weren't expecting it! */ - return CborErrorUnexpectedBreak; - } - ++it->ptr; - it->type = CborInvalidType; - it->remaining = 0; - return CborNoError; - } - - return preparse_value(it); -} - -static CborError preparse_next_value(CborValue *it) -{ - /* tags don't count towards item totals or whether we've successfully - * read a map's key or value */ - bool itemCounts = it->type != CborTagType; - - if (it->remaining != UINT32_MAX) { - if (itemCounts && --it->remaining == 0) { - it->type = CborInvalidType; - return CborNoError; - } - } - if (itemCounts) { - /* toggle the flag indicating whether this was a map key */ - it->flags ^= CborIteratorFlag_NextIsMapKey; - } - return preparse_next_value_nodecrement(it); -} - -static CborError advance_internal(CborValue *it) -{ - uint64_t length; - CborError err = _cbor_value_extract_number(&it->ptr, it->parser->end, &length); - cbor_assert(err == CborNoError); - - if (it->type == CborByteStringType || it->type == CborTextStringType) { - cbor_assert(length == (size_t)length); - cbor_assert((it->flags & CborIteratorFlag_UnknownLength) == 0); - it->ptr += length; - } - - return preparse_next_value(it); -} - -/** \internal - * - * Decodes the CBOR integer value when it is larger than the 16 bits available - * in value->extra. This function requires that value->flags have the - * CborIteratorFlag_IntegerValueTooLarge flag set. - * - * This function is also used to extract single- and double-precision floating - * point values (SinglePrecisionFloat == Value32Bit and DoublePrecisionFloat == - * Value64Bit). - */ -uint64_t _cbor_value_decode_int64_internal(const CborValue *value) -{ - cbor_assert(value->flags & CborIteratorFlag_IntegerValueTooLarge || - value->type == CborFloatType || value->type == CborDoubleType); - - /* since the additional information can only be Value32Bit or Value64Bit, - * we just need to test for the one bit those two options differ */ - cbor_assert((*value->ptr & SmallValueMask) == Value32Bit || (*value->ptr & SmallValueMask) == Value64Bit); - if ((*value->ptr & 1) == (Value32Bit & 1)) - return get32(value->ptr + 1); - - cbor_assert((*value->ptr & SmallValueMask) == Value64Bit); - return get64(value->ptr + 1); -} - -/** - * Initializes the CBOR parser for parsing \a size bytes beginning at \a - * buffer. Parsing will use flags set in \a flags. The iterator to the first - * element is returned in \a it. - * - * The \a parser structure needs to remain valid throughout the decoding - * process. It is not thread-safe to share one CborParser among multiple - * threads iterating at the same time, but the object can be copied so multiple - * threads can iterate. - */ -CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it) -{ - memset(parser, 0, sizeof(*parser)); - parser->end = buffer + size; - parser->flags = flags; - it->parser = parser; - it->ptr = buffer; - it->remaining = 1; /* there's one type altogether, usually an array or map */ - it->flags = 0; - return preparse_value(it); -} - -/** - * \fn bool cbor_value_at_end(const CborValue *it) - * - * Returns true if \a it has reached the end of the iteration, usually when - * advancing after the last item in an array or map. - * - * In the case of the outermost CborValue object, this function returns true - * after decoding a single element. A pointer to the first byte of the - * remaining data (if any) can be obtained with cbor_value_get_next_byte(). - * - * \sa cbor_value_advance(), cbor_value_is_valid(), cbor_value_get_next_byte() - */ - -/** - * \fn const uint8_t *cbor_value_get_next_byte(const CborValue *it) - * - * Returns a pointer to the next byte that would be decoded if this CborValue - * object were advanced. - * - * This function is useful if cbor_value_at_end() returns true for the - * outermost CborValue: the pointer returned is the first byte of the data - * remaining in the buffer, if any. Code can decide whether to begin decoding a - * new CBOR data stream from this point, or parse some other data appended to - * the same buffer. - * - * This function may be used even after a parsing error. If that occurred, - * then this function returns a pointer to where the parsing error occurred. - * Note that the error recovery is not precise and the pointer may not indicate - * the exact byte containing bad data. - * - * \sa cbor_value_at_end() - */ - -/** - * \fn bool cbor_value_is_valid(const CborValue *it) - * - * Returns true if the iterator \a it contains a valid value. Invalid iterators - * happen when iteration reaches the end of a container (see \ref - * cbor_value_at_end()) or when a search function resulted in no matches. - * - * \sa cbor_value_advance(), cbor_value_at_end(), cbor_value_get_type() - */ - -/** - * Performs a basic validation of the CBOR stream pointed by \a it and returns - * the error it found. If no error was found, it returns CborNoError and the - * application can iterate over the items with certainty that no other errors - * will appear during parsing. - * - * A basic validation checks for: - * \list - * \li absence of undefined additional information bytes; - * \li well-formedness of all numbers, lengths, and simple values; - * \li string contents match reported sizes; - * \li arrays and maps contain the number of elements they are reported to have; - * \endlist - * - * For further checks, see cbor_value_validate(). - * - * This function has the same timing and memory requirements as - * cbor_value_advance(). - * - * \sa cbor_value_validate(), cbor_value_advance() - */ -CborError cbor_value_validate_basic(const CborValue *it) -{ - CborValue value = *it; - return cbor_value_advance(&value); -} - -/** - * Advances the CBOR value \a it by one fixed-size position. Fixed-size types - * are: integers, tags, simple types (including boolean, null and undefined - * values) and floating point types. - * - * If the type is not of fixed size, this function has undefined behavior. Code - * must be sure that the current type is one of the fixed-size types before - * calling this function. This function is provided because it can guarantee - * that it runs in constant time (O(1)). - * - * If the caller is not able to determine whether the type is fixed or not, code - * can use the cbor_value_advance() function instead. - * - * \sa cbor_value_at_end(), cbor_value_advance(), cbor_value_enter_container(), cbor_value_leave_container() - */ -CborError cbor_value_advance_fixed(CborValue *it) -{ - cbor_assert(it->type != CborInvalidType); - cbor_assert(is_fixed_type(it->type)); - if (!it->remaining) - return CborErrorAdvancePastEOF; - return advance_internal(it); -} - -static CborError advance_recursive(CborValue *it, int nestingLevel) -{ - CborError err; - CborValue recursed; - - if (is_fixed_type(it->type)) - return advance_internal(it); - - if (!cbor_value_is_container(it)) { - size_t len = SIZE_MAX; - return _cbor_value_copy_string(it, NULL, &len, it); - } - - /* map or array */ - if (nestingLevel == 0) - return CborErrorNestingTooDeep; - - err = cbor_value_enter_container(it, &recursed); - if (err) - return err; - while (!cbor_value_at_end(&recursed)) { - err = advance_recursive(&recursed, nestingLevel - 1); - if (err) - return err; - } - return cbor_value_leave_container(it, &recursed); -} - - -/** - * Advances the CBOR value \a it by one element, skipping over containers. - * Unlike cbor_value_advance_fixed(), this function can be called on a CBOR - * value of any type. However, if the type is a container (map or array) or a - * string with a chunked payload, this function will not run in constant time - * and will recurse into itself (it will run on O(n) time for the number of - * elements or chunks and will use O(n) memory for the number of nested - * containers). - * - * The number of recursions can be limited at compile time to avoid stack - * exhaustion in constrained systems. - * - * \sa cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_enter_container(), cbor_value_leave_container() - */ -CborError cbor_value_advance(CborValue *it) -{ - cbor_assert(it->type != CborInvalidType); - if (!it->remaining) - return CborErrorAdvancePastEOF; - return advance_recursive(it, CBOR_PARSER_MAX_RECURSIONS); -} - -/** - * \fn bool cbor_value_is_tag(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR tag. - * - * \sa cbor_value_get_tag(), cbor_value_skip_tag() - */ - -/** - * \fn CborError cbor_value_get_tag(const CborValue *value, CborTag *result) - * - * Retrieves the CBOR tag value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to a CBOR tag value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_tag is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_tag() - */ - -/** - * Advances the CBOR value \a it until it no longer points to a tag. If \a it is - * already not pointing to a tag, then this function returns it unchanged. - * - * This function does not run in constant time: it will run on O(n) for n being - * the number of tags. It does use constant memory (O(1) memory requirements). - * - * \sa cbor_value_advance_fixed(), cbor_value_advance() - */ -CborError cbor_value_skip_tag(CborValue *it) -{ - while (cbor_value_is_tag(it)) { - CborError err = cbor_value_advance_fixed(it); - if (err) - return err; - } - return CborNoError; -} - -/** - * \fn bool cbor_value_is_container(const CborValue *it) - * - * Returns true if the \a it value is a container and requires recursion in - * order to decode (maps and arrays), false otherwise. - */ - -/** - * Creates a CborValue iterator pointing to the first element of the container - * represented by \a it and saves it in \a recursed. The \a it container object - * needs to be kept and passed again to cbor_value_leave_container() in order - * to continue iterating past this container. - * - * The \a it CborValue iterator must point to a container. - * - * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance() - */ -CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed) -{ - cbor_static_assert(CborIteratorFlag_ContainerIsMap == (CborMapType & ~CborArrayType)); - cbor_assert(cbor_value_is_container(it)); - *recursed = *it; - - if (it->flags & CborIteratorFlag_UnknownLength) { - recursed->remaining = UINT32_MAX; - ++recursed->ptr; - } else { - uint64_t len; - CborError err = _cbor_value_extract_number(&recursed->ptr, recursed->parser->end, &len); - cbor_assert(err == CborNoError); - - recursed->remaining = (uint32_t)len; - if (recursed->remaining != len || len == UINT32_MAX) { - /* back track the pointer to indicate where the error occurred */ - recursed->ptr = it->ptr; - return CborErrorDataTooLarge; - } - if (recursed->type == CborMapType) { - /* maps have keys and values, so we need to multiply by 2 */ - if (recursed->remaining > UINT32_MAX / 2) { - /* back track the pointer to indicate where the error occurred */ - recursed->ptr = it->ptr; - return CborErrorDataTooLarge; - } - recursed->remaining *= 2; - } - if (len == 0) { - /* the case of the empty container */ - recursed->type = CborInvalidType; - return CborNoError; - } - } - recursed->flags = (recursed->type & CborIteratorFlag_ContainerIsMap); - return preparse_next_value_nodecrement(recursed); -} - -/** - * Updates \a it to point to the next element after the container. The \a - * recursed object needs to point to the element obtained either by advancing - * the last element of the container (via cbor_value_advance(), - * cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the \c - * next pointer from cbor_value_copy_string() or cbor_value_dup_string()). - * - * The \a it and \a recursed parameters must be the exact same as passed to - * cbor_value_enter_container(). - * - * \sa cbor_value_enter_container(), cbor_value_at_end() - */ -CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed) -{ - cbor_assert(cbor_value_is_container(it)); - cbor_assert(recursed->type == CborInvalidType); - it->ptr = recursed->ptr; - return preparse_next_value(it); -} - - -/** - * \fn CborType cbor_value_get_type(const CborValue *value) - * - * Returns the type of the CBOR value that the iterator \a value points to. If - * \a value does not point to a valid value, this function returns \ref - * CborInvalidType. - * - * TinyCBOR also provides functions to test directly if a given CborValue object - * is of a given type, like cbor_value_is_text_string() and cbor_value_is_null(). - * - * \sa cbor_value_is_valid() - */ - -/** - * \fn bool cbor_value_is_null(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR null type. - * - * \sa cbor_value_is_valid(), cbor_value_is_undefined() - */ - -/** - * \fn bool cbor_value_is_undefined(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR undefined type. - * - * \sa cbor_value_is_valid(), cbor_value_is_null() - */ - -/** - * \fn bool cbor_value_is_boolean(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR boolean - * type (true or false). - * - * \sa cbor_value_is_valid(), cbor_value_get_boolean() - */ - -/** - * \fn CborError cbor_value_get_boolean(const CborValue *value, bool *result) - * - * Retrieves the boolean value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to a boolean value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_boolean is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_boolean() - */ - -/** - * \fn bool cbor_value_is_simple_type(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR Simple Type - * type (other than true, false, null and undefined). - * - * \sa cbor_value_is_valid(), cbor_value_get_simple_type() - */ - -/** - * \fn CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) - * - * Retrieves the CBOR Simple Type value that \a value points to and stores it - * in \a result. If the iterator \a value does not point to a simple_type - * value, the behavior is undefined, so checking with \ref cbor_value_get_type - * or with \ref cbor_value_is_simple_type is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_simple_type() - */ - -/** - * \fn bool cbor_value_is_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR integer - * type. - * - * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_uint64, cbor_value_get_raw_integer - */ - -/** - * \fn bool cbor_value_is_unsigned_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR unsigned - * integer type (positive values or zero). - * - * \sa cbor_value_is_valid(), cbor_value_get_uint64() - */ - -/** - * \fn bool cbor_value_is_negative_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR negative - * integer type. - * - * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_raw_integer - */ - -/** - * \fn CborError cbor_value_get_int(const CborValue *value, int *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Note that this function does not do range-checking: integral values that do - * not fit in a variable of type \c{int} are silently truncated to fit. Use - * cbor_value_get_int_checked() if that is not acceptable. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * \fn CborError cbor_value_get_int64(const CborValue *value, int64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Note that this function does not do range-checking: integral values that do - * not fit in a variable of type \c{int64_t} are silently truncated to fit. Use - * cbor_value_get_int64_checked() that is not acceptable. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * \fn CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an unsigned integer - * value, the behavior is undefined, so checking with \ref cbor_value_get_type - * or with \ref cbor_value_is_unsigned_integer is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_unsigned_integer() - */ - -/** - * \fn CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * This function is provided because CBOR negative integers can assume values - * that cannot be represented with normal 64-bit integer variables. - * - * If the integer is unsigned (that is, if cbor_value_is_unsigned_integer() - * returns true), then \a result will contain the actual value. If the integer - * is negative, then \a result will contain the absolute value of that integer, - * minus one. That is, \c {actual = -result - 1}. On architectures using two's - * complement for representation of negative integers, it is equivalent to say - * that \a result will contain the bitwise negation of the actual value. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Unlike \ref cbor_value_get_int64(), this function performs a check to see if the - * stored integer fits in \a result without data loss. If the number is outside - * the valid range for the data type, this function returns the recoverable - * error CborErrorDataTooLarge. In that case, use either - * cbor_value_get_uint64() (if the number is positive) or - * cbor_value_get_raw_integer(). - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64() - */ -CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result) -{ - uint64_t v; - cbor_assert(cbor_value_is_integer(value)); - v = _cbor_value_extract_int64_helper(value); - - /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): - * "[if] the new type is signed and the value cannot be represented in it; either the - * result is implementation-defined or an implementation-defined signal is raised." - * - * The range for int64_t is -2^63 to 2^63-1 (int64_t is required to be - * two's complement, C11 7.20.1.1 paragraph 3), which in CBOR is - * represented the same way, differing only on the "sign bit" (the major - * type). - */ - - if (unlikely(v > (uint64_t)INT64_MAX)) - return CborErrorDataTooLarge; - - *result = v; - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -/** - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Unlike \ref cbor_value_get_int(), this function performs a check to see if the - * stored integer fits in \a result without data loss. If the number is outside - * the valid range for the data type, this function returns the recoverable - * error CborErrorDataTooLarge. In that case, use one of the other integer - * functions to obtain the value. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64(), - * cbor_value_get_uint64(), cbor_value_get_int64_checked(), cbor_value_get_raw_integer() - */ -CborError cbor_value_get_int_checked(const CborValue *value, int *result) -{ - uint64_t v; - cbor_assert(cbor_value_is_integer(value)); - v = _cbor_value_extract_int64_helper(value); - - /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): - * "[if] the new type is signed and the value cannot be represented in it; either the - * result is implementation-defined or an implementation-defined signal is raised." - * - * But we can convert from signed to unsigned without fault (paragraph 2). - * - * The range for int is implementation-defined and int is not guaranteed to use - * two's complement representation (although int32_t is). - */ - - if (value->flags & CborIteratorFlag_NegativeInteger) { - if (unlikely(v > (unsigned) -(INT_MIN + 1))) - return CborErrorDataTooLarge; - - *result = (int)v; - *result = -*result - 1; - } else { - if (unlikely(v > (uint64_t)INT_MAX)) - return CborErrorDataTooLarge; - - *result = (int)v; - } - return CborNoError; - -} - -/** - * \fn bool cbor_value_is_length_known(const CborValue *value) - * - * Returns true if the length of this type is known without calculation. That - * is, if the length of this CBOR string, map or array is encoded in the data - * stream, this function returns true. If the length is not encoded, it returns - * false. - * - * If the length is known, code can call cbor_value_get_string_length(), - * cbor_value_get_array_length() or cbor_value_get_map_length() to obtain the - * length. If the length is not known but is necessary, code can use the - * cbor_value_calculate_string_length() function (no equivalent function is - * provided for maps and arrays). - */ - -/** - * \fn bool cbor_value_is_text_string(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR text - * string. CBOR text strings are UTF-8 encoded and usually contain - * human-readable text. - * - * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), - * cbor_value_copy_text_string(), cbor_value_dup_text_string() - */ - -/** - * \fn bool cbor_value_is_byte_string(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR byte - * string. CBOR byte strings are binary data with no specified encoding or - * format. - * - * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), - * cbor_value_copy_byte_string(), cbor_value_dup_byte_string() - */ - -/** - * \fn CborError cbor_value_get_string_length(const CborValue *value, size_t *length) - * - * Extracts the length of the byte or text string that \a value points to and - * stores it in \a result. If the iterator \a value does not point to a text - * string or a byte string, the behaviour is undefined, so checking with \ref - * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref - * cbor_value_is_byte_string is recommended. - * - * If the length of this string is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * If the length of the string is required but the length was not encoded, use - * cbor_value_calculate_string_length(), but note that that function does not - * run in constant time. - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known(), cbor_value_calculate_string_length() - */ - -/** - * Calculates the length of the byte or text string that \a value points to and - * stores it in \a len. If the iterator \a value does not point to a text - * string or a byte string, the behaviour is undefined, so checking with \ref - * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref - * cbor_value_is_byte_string is recommended. - * - * This function is different from cbor_value_get_string_length() in that it - * calculates the length even for strings sent in chunks. For that reason, this - * function may not run in constant time (it will run in O(n) time on the - * number of chunks). It does use constant memory (O(1)). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known() - */ -CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len) -{ - *len = SIZE_MAX; - return _cbor_value_copy_string(value, NULL, len, NULL); -} - -static inline void prepare_string_iteration(CborValue *it) -{ - if (!cbor_value_is_length_known(it)) { - /* chunked string: we're before the first chunk; - * advance to the first chunk */ - ++it->ptr; - it->flags |= CborIteratorFlag_IteratingStringChunks; - } -} - -CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it) -{ - cbor_assert((it->flags & CborIteratorFlag_IteratingStringChunks) == 0); - prepare_string_iteration(it); - - /* are we at the end? */ - if (it->ptr == it->parser->end) - return CborErrorUnexpectedEOF; - return CborNoError; -} - -static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t *len) -{ - CborError err; - - /* Possible states: - * length known | iterating | meaning - * no | no | before the first chunk of a chunked string - * yes | no | at a non-chunked string - * no | yes | second or later chunk - * yes | yes | after a non-chunked string - */ - if (it->flags & CborIteratorFlag_IteratingStringChunks) { - /* already iterating */ - if (cbor_value_is_length_known(it)) { - /* if the length was known, it wasn't chunked, so finish iteration */ - goto last_chunk; - } - } else { - prepare_string_iteration(it); - } - - /* are we at the end? */ - if (it->ptr == it->parser->end) - return CborErrorUnexpectedEOF; - - if (*it->ptr == BreakByte) { - /* last chunk */ - ++it->ptr; -last_chunk: - *bufferptr = NULL; - *len = 0; - return preparse_next_value(it); - } else if ((uint8_t)(*it->ptr & MajorTypeMask) == it->type) { - err = extract_length(it->parser, &it->ptr, len); - if (err) - return err; - if (*len > (size_t)(it->parser->end - it->ptr)) - return CborErrorUnexpectedEOF; - - *bufferptr = it->ptr; - it->ptr += *len; - } else { - return CborErrorIllegalType; - } - - it->flags |= CborIteratorFlag_IteratingStringChunks; - return CborNoError; -} - -CborError CBOR_INTERNAL_API_CC -_cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, - size_t *len, CborValue *next) -{ - CborValue tmp; - if (!next) - next = &tmp; - *next = *value; - return get_string_chunk(next, bufferptr, len); -} - -/* We return uintptr_t so that we can pass memcpy directly as the iteration - * function. The choice is to optimize for memcpy, which is used in the base - * parser API (cbor_value_copy_string), while memcmp is used in convenience API - * only. */ -typedef uintptr_t (*IterateFunction)(char *, const uint8_t *, size_t); - -static uintptr_t iterate_noop(char *dest, const uint8_t *src, size_t len) -{ - (void)dest; - (void)src; - (void)len; - return true; -} - -static uintptr_t iterate_memcmp(char *s1, const uint8_t *s2, size_t len) -{ - return memcmp(s1, (const char *)s2, len) == 0; -} - -static uintptr_t iterate_memcpy(char *dest, const uint8_t *src, size_t len) -{ - return (uintptr_t)memcpy(dest, src, len); -} - -static CborError iterate_string_chunks(const CborValue *value, char *buffer, size_t *buflen, - bool *result, CborValue *next, IterateFunction func) -{ - CborError err; - CborValue tmp; - size_t total = 0; - const void *ptr; - - cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); - if (!next) - next = &tmp; - *next = *value; - *result = true; - - while (1) { - size_t newTotal; - size_t chunkLen; - err = get_string_chunk(next, &ptr, &chunkLen); - if (err) - return err; - if (!ptr) - break; - - if (unlikely(add_check_overflow(total, chunkLen, &newTotal))) - return CborErrorDataTooLarge; - - if (*result && *buflen >= newTotal) - *result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen); - else - *result = false; - - total = newTotal; - } - - /* is there enough room for the ending NUL byte? */ - if (*result && *buflen > total) { - uint8_t nul[] = { 0 }; - *result = !!func(buffer + total, nul, 1); - } - *buflen = total; - return CborNoError; -} - -/** - * \fn CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next) - * - * Copies the string pointed to by \a value into the buffer provided at \a buffer - * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not - * copy anything and will only update the \a next value. - * - * If the iterator \a value does not point to a text string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_text_string is recommended. - * - * If the provided buffer length was too small, this function returns an error - * condition of \ref CborErrorOutOfMemory. If you need to calculate the length - * of the string in order to preallocate a buffer, use - * cbor_value_calculate_string_length(). - * - * On success, this function sets the number of bytes copied to \c{*buflen}. If - * the buffer is large enough, this function will insert a null byte after the - * last copied byte, to facilitate manipulation of text strings. That byte is - * not included in the returned value of \c{*buflen}. If there was no space for - * the terminating null, no error is returned, so callers must check the value - * of *buflen after the call, before relying on the '\0'; if it has not been - * changed by the call, there is no '\0'-termination on the buffer's contents. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \note This function does not perform UTF-8 validation on the incoming text - * string. - * - * \sa cbor_value_get_text_string_chunk() cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() - */ - -/** - * \fn CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next) - * - * Copies the string pointed by \a value into the buffer provided at \a buffer - * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not - * copy anything and will only update the \a next value. - * - * If the iterator \a value does not point to a byte string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_byte_string is recommended. - * - * If the provided buffer length was too small, this function returns an error - * condition of \ref CborErrorOutOfMemory. If you need to calculate the length - * of the string in order to preallocate a buffer, use - * cbor_value_calculate_string_length(). - * - * On success, this function sets the number of bytes copied to \c{*buflen}. If - * the buffer is large enough, this function will insert a null byte after the - * last copied byte, to facilitate manipulation of null-terminated strings. - * That byte is not included in the returned value of \c{*buflen}. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \sa cbor_value_get_byte_string_chunk(), cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() - */ - -CborError _cbor_value_copy_string(const CborValue *value, void *buffer, - size_t *buflen, CborValue *next) -{ - bool copied_all; - CborError err = iterate_string_chunks(value, (char*)buffer, buflen, &copied_all, next, - buffer ? iterate_memcpy : iterate_noop); - return err ? err : - copied_all ? CborNoError : CborErrorOutOfMemory; -} - -/** - * Compares the entry \a value with the string \a string and stores the result - * in \a result. If the value is different from \a string \a result will - * contain \c false. - * - * The entry at \a value may be a tagged string. If \a value is not a string or - * a tagged string, the comparison result will be false. - * - * CBOR requires text strings to be encoded in UTF-8, but this function does - * not validate either the strings in the stream or the string \a string to be - * matched. Moreover, comparison is done on strict codepoint comparison, - * without any Unicode normalization. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \sa cbor_value_skip_tag(), cbor_value_copy_text_string() - */ -CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result) -{ - size_t len; - CborValue copy = *value; - CborError err = cbor_value_skip_tag(©); - if (err) - return err; - if (!cbor_value_is_text_string(©)) { - *result = false; - return CborNoError; - } - - len = strlen(string); - return iterate_string_chunks(©, CONST_CAST(char *, string), &len, result, NULL, iterate_memcmp); -} - -/** - * \fn bool cbor_value_is_array(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR array. - * - * \sa cbor_value_is_valid(), cbor_value_is_map() - */ - -/** - * \fn CborError cbor_value_get_array_length(const CborValue *value, size_t *length) - * - * Extracts the length of the CBOR array that \a value points to and stores it - * in \a result. If the iterator \a value does not point to a CBOR array, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_array is recommended. - * - * If the length of this array is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known() - */ - -/** - * \fn bool cbor_value_is_map(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR map. - * - * \sa cbor_value_is_valid(), cbor_value_is_array() - */ - -/** - * \fn CborError cbor_value_get_map_length(const CborValue *value, size_t *length) - * - * Extracts the length of the CBOR map that \a value points to and stores it in - * \a result. If the iterator \a value does not point to a CBOR map, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_map is recommended. - * - * If the length of this map is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known() - */ - -/** - * Attempts to find the value in map \a map that corresponds to the text string - * entry \a string. If the iterator \a value does not point to a CBOR map, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_map is recommended. - * - * If the item is found, it is stored in \a result. If no item is found - * matching the key, then \a result will contain an element of type \ref - * CborInvalidType. Matching is performed using - * cbor_value_text_string_equals(), so tagged strings will also match. - * - * This function has a time complexity of O(n) where n is the number of - * elements in the map to be searched. In addition, this function is has O(n) - * memory requirement based on the number of nested containers (maps or arrays) - * found as elements of this map. - * - * \sa cbor_value_is_valid(), cbor_value_text_string_equals(), cbor_value_advance() - */ -CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element) -{ - CborError err; - size_t len = strlen(string); - cbor_assert(cbor_value_is_map(map)); - err = cbor_value_enter_container(map, element); - if (err) - goto error; - - while (!cbor_value_at_end(element)) { - /* find the non-tag so we can compare */ - err = cbor_value_skip_tag(element); - if (err) - goto error; - if (cbor_value_is_text_string(element)) { - bool equals; - size_t dummyLen = len; - err = iterate_string_chunks(element, CONST_CAST(char *, string), &dummyLen, - &equals, element, iterate_memcmp); - if (err) - goto error; - if (equals) - return preparse_value(element); - } else { - /* skip this key */ - err = cbor_value_advance(element); - if (err) - goto error; - } - - /* skip this value */ - err = cbor_value_skip_tag(element); - if (err) - goto error; - err = cbor_value_advance(element); - if (err) - goto error; - } - - /* not found */ - element->type = CborInvalidType; - return CborNoError; - -error: - element->type = CborInvalidType; - return err; -} - -/** - * \fn bool cbor_value_is_float(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * single-precision floating point (32-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_half_float() - */ - -/** - * \fn CborError cbor_value_get_float(const CborValue *value, float *result) - * - * Retrieves the CBOR single-precision floating point (32-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a single-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_float is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_float(), cbor_value_get_double() - */ - -/** - * \fn bool cbor_value_is_double(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * double-precision floating point (64-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_float(), cbor_value_is_half_float() - */ - -/** - * \fn CborError cbor_value_get_double(const CborValue *value, float *result) - * - * Retrieves the CBOR double-precision floating point (64-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a double-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_double is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_double(), cbor_value_get_float() - */ - -/** - * \fn bool cbor_value_is_half_float(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * single-precision floating point (16-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_float() - */ - -/** - * Retrieves the CBOR half-precision floating point (16-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a half-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_half_float is recommended. - * - * Note: since the C language does not have a standard type for half-precision - * floating point, this function takes a \c{void *} as a parameter for the - * storage area, which must be at least 16 bits wide. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_float() - */ -CborError cbor_value_get_half_float(const CborValue *value, void *result) -{ - uint16_t v; - cbor_assert(cbor_value_is_half_float(value)); - - /* size has been computed already */ - v = get16(value->ptr + 1); - memcpy(result, &v, sizeof(v)); - return CborNoError; -} - -/** @} */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser_dup_string.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser_dup_string.c deleted file mode 100644 index 061c5ac..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborparser_dup_string.c +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "compilersupport_p.h" -#include - -/** - * \fn CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, size_t *buflen, CborValue *next) - * - * Allocates memory for the string pointed by \a value and copies it into this - * buffer. The pointer to the buffer is stored in \a buffer and the number of - * bytes copied is stored in \a buflen (those variables must not be NULL). - * - * If the iterator \a value does not point to a text string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_text_string is recommended. - * - * If \c malloc returns a NULL pointer, this function will return error - * condition \ref CborErrorOutOfMemory. - * - * On success, \c{*buffer} will contain a valid pointer that must be freed by - * calling \c{free()}. This is the case even for zero-length strings. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)) in addition to the - * malloc'ed block. - * - * \note This function does not perform UTF-8 validation on the incoming text - * string. - * - * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_text_string(), cbor_value_dup_byte_string() - */ - -/** - * \fn CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, size_t *buflen, CborValue *next) - * - * Allocates memory for the string pointed by \a value and copies it into this - * buffer. The pointer to the buffer is stored in \a buffer and the number of - * bytes copied is stored in \a buflen (those variables must not be NULL). - * - * If the iterator \a value does not point to a byte string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_byte_string is recommended. - * - * If \c malloc returns a NULL pointer, this function will return error - * condition \ref CborErrorOutOfMemory. - * - * On success, \c{*buffer} will contain a valid pointer that must be freed by - * calling \c{free()}. This is the case even for zero-length strings. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)) in addition to the - * malloc'ed block. - * - * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_byte_string(), cbor_value_dup_text_string() - */ -CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *buflen, CborValue *next) -{ - CborError err; - cbor_assert(buffer); - cbor_assert(buflen); - *buflen = SIZE_MAX; - err = _cbor_value_copy_string(value, NULL, buflen, NULL); - if (err) - return err; - - ++*buflen; - *buffer = malloc(*buflen); - if (!*buffer) { - /* out of memory */ - return CborErrorOutOfMemory; - } - err = _cbor_value_copy_string(value, *buffer, buflen, next); - if (err) { - free(*buffer); - return err; - } - return CborNoError; -} diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty.c deleted file mode 100644 index b0a3db8..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty.c +++ /dev/null @@ -1,580 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" -#include "utf8_p.h" - -#include -#include - -/** - * \defgroup CborPretty Converting CBOR to text - * \brief Group of functions used to convert CBOR to text form. - * - * This group contains two functions that can be used to convert a \ref - * CborValue object to a text representation. This module attempts to follow - * the recommendations from RFC 7049 section 6 "Diagnostic Notation", though it - * has a few differences. They are noted below. - * - * TinyCBOR does not provide a way to convert from the text representation back - * to encoded form. To produce a text form meant to be parsed, CborToJson is - * recommended instead. - * - * Either of the functions in this section will attempt to convert exactly one - * CborValue object to text. Those functions may return any error documented - * for the functions for CborParsing. In addition, if the C standard library - * stream functions return with error, the text conversion will return with - * error CborErrorIO. - * - * These functions also perform UTF-8 validation in CBOR text strings. If they - * encounter a sequence of bytes that is not permitted in UTF-8, they will return - * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points - * in UTF-8. - * - * \warning The output type produced by these functions is not guaranteed to - * remain stable. A future update of TinyCBOR may produce different output for - * the same input and parsers may be unable to handle it. - * - * \sa CborParsing, CborToJson, cbor_parser_init() - */ - -/** - * \addtogroup CborPretty - * @{ - *

Text format

- * - * As described in RFC 7049 section 6 "Diagnostic Notation", the format is - * largely borrowed from JSON, but modified to suit CBOR's different data - * types. TinyCBOR makes further modifications to distinguish different, but - * similar values. - * - * CBOR values are currently encoded as follows: - * \par Integrals (unsigned and negative) - * Base-10 (decimal) text representation of the value - * \par Byte strings: - * "h'" followed by the Base16 (hex) representation of the binary data, followed by an ending quote (') - * \par Text strings: - * C-style escaped string in quotes, with C11/C++11 escaping of Unicode codepoints above U+007F. - * \par Tags: - * Tag value, with the tagged value in parentheses. No special encoding of the tagged value is performed. - * \par Simple types: - * "simple(nn)" where \c nn is the simple value - * \par Null: - * \c null - * \par Undefined: - * \c undefined - * \par Booleans: - * \c true or \c false - * \par Floating point: - * If NaN or infinite, the actual words \c NaN or \c infinite. - * Otherwise, the decimal representation with as many digits as necessary to ensure no loss of information. - * By default, float values are suffixed by "f" and half-float values suffixed by "f16" (doubles have no suffix). - * If the CborPrettyNumericEncodingIndicators flag is active, the values instead are encoded following the - * Section 6 recommended encoding indicators: float values are suffixed with "_2" and half-float with "_1". - * A decimal point is always present. - * \par Arrays: - * Comma-separated list of elements, enclosed in square brackets ("[" and "]"). - * \par Maps: - * Comma-separated list of key-value pairs, with the key and value separated - * by a colon (":"), enclosed in curly braces ("{" and "}"). - * - * The CborPrettyFlags enumerator contains flags to control some aspects of the - * encoding: - * \par String fragmentation - * When the CborPrettyShowStringFragments option is active, text and byte - * strings that are transmitted in fragments are shown instead inside - * parentheses ("(" and ")") with no preceding number and each fragment is - * displayed individually. If a tag precedes the string, then the output - * will contain a double set of parentheses. If the option is not active, - * the fragments are merged together and the display will not show any - * difference from a string transmitted with determinate length. - * \par Encoding indicators - * Numbers and lengths in CBOR can be encoded in multiple representations. - * If the CborPrettyIndicateOverlongNumbers option is active, numbers - * and lengths that are transmitted in a longer encoding than necessary - * will be indicated, by appending an underscore ("_") to either the - * number or the opening bracket or brace, followed by a number - * indicating the CBOR additional information: 0 for 1 byte, 1 for 2 - * bytes, 2 for 4 bytes and 3 for 8 bytes. - * If the CborPrettyIndicateIndeterminateLength option is active, maps, - * arrays and strings encoded with indeterminate length will be marked by - * an underscore after the opening bracket or brace or the string (if not - * showing fragments), without a number after it. - */ - -/** - * \enum CborPrettyFlags - * The CborPrettyFlags enum contains flags that control the conversion of CBOR to text format. - * - * \value CborPrettyNumericEncodingIndicators Use numeric encoding indicators instead of textual for float and half-float. - * \value CborPrettyTextualEncodingIndicators Use textual encoding indicators for float ("f") and half-float ("f16"). - * \value CborPrettyIndicateIndeterminateLength (default) Indicate when a map or array has indeterminate length. - * \value CborPrettyIndicateOverlongNumbers Indicate when a number or length was encoded with more bytes than needed. - * \value CborPrettyShowStringFragments If the byte or text string is transmitted in chunks, show each individually. - * \value CborPrettyMergeStringFragment Merge all chunked byte or text strings and display them in a single entry. - * \value CborPrettyDefaultFlags Default conversion flags. - */ - -#ifndef CBOR_NO_FLOATING_POINT -static inline bool convertToUint64(double v, uint64_t *absolute) -{ - double supremum; - v = fabs(v); - - /* C11 standard section 6.3.1.4 "Real floating and integer" says: - * - * 1 When a finite value of real floating type is converted to an integer - * type other than _Bool, the fractional part is discarded (i.e., the - * value is truncated toward zero). If the value of the integral part - * cannot be represented by the integer type, the behavior is undefined. - * - * So we must perform a range check that v <= UINT64_MAX, but we can't use - * UINT64_MAX + 1.0 because the standard continues: - * - * 2 When a value of integer type is converted to a real floating type, if - * the value being converted can be represented exactly in the new type, - * it is unchanged. If the value being converted is in the range of - * values that can be represented but cannot be represented exactly, the - * result is either the nearest higher or nearest lower representable - * value, chosen in an implementation-defined manner. - */ - supremum = -2.0 * INT64_MIN; /* -2 * (- 2^63) == 2^64 */ - if (v >= supremum) - return false; - - /* Now we can convert, these two conversions cannot be UB */ - *absolute = v; - return *absolute == v; -} -#endif - -static void printRecursionLimit(CborStreamFunction stream, void *out) -{ - stream(out, ""); -} - -static CborError hexDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - CborError err = CborNoError; - while (n-- && !err) - err = stream(out, "%02" PRIx8, *buffer++); - - return err; -} - -/* This function decodes buffer as UTF-8 and prints as escaped UTF-16. - * On UTF-8 decoding error, it returns CborErrorInvalidUtf8TextString */ -static CborError utf8EscapedDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - const uint8_t * const end = buffer + n; - CborError err = CborNoError; - - while (buffer < end && !err) { - uint32_t uc = get_utf8(&buffer, end); - if (uc == ~0U) - return CborErrorInvalidUtf8TextString; - - if (uc < 0x80) { - /* single-byte UTF-8 */ - unsigned char escaped = (unsigned char)uc; - if (uc < 0x7f && uc >= 0x20 && uc != '\\' && uc != '"') { - err = stream(out, "%c", (char)uc); - continue; - } - - /* print as an escape sequence */ - switch (uc) { - case '"': - case '\\': - break; - case '\b': - escaped = 'b'; - break; - case '\f': - escaped = 'f'; - break; - case '\n': - escaped = 'n'; - break; - case '\r': - escaped = 'r'; - break; - case '\t': - escaped = 't'; - break; - default: - goto print_utf16; - } - err = stream(out, "\\%c", escaped); - continue; - } - - /* now print the sequence */ - if (uc > 0xffffU) { - /* needs surrogate pairs */ - err = stream(out, "\\u%04" PRIX32 "\\u%04" PRIX32, - (uc >> 10) + 0xd7c0, /* high surrogate */ - (uc % 0x0400) + 0xdc00); - } else { -print_utf16: - /* no surrogate pair needed */ - err = stream(out, "\\u%04" PRIX32, uc); - } - } - return err; -} - -static const char *resolve_indicator(const uint8_t *ptr, const uint8_t *end, int flags) -{ - static const char indicators[8][3] = { - "_0", "_1", "_2", "_3", - "", "", "", /* these are not possible */ - "_" - }; - const char *no_indicator = indicators[5]; /* empty string */ - uint8_t additional_information; - uint8_t expected_information; - uint64_t value; - CborError err; - - if (ptr == end) - return NULL; /* CborErrorUnexpectedEOF */ - - additional_information = (*ptr & SmallValueMask); - if (additional_information < Value8Bit) - return no_indicator; - - /* determine whether to show anything */ - if ((flags & CborPrettyIndicateIndeterminateLength) && - additional_information == IndefiniteLength) - return indicators[IndefiniteLength - Value8Bit]; - if ((flags & CborPrettyIndicateOverlongNumbers) == 0) - return no_indicator; - - err = _cbor_value_extract_number(&ptr, end, &value); - if (err) - return NULL; /* CborErrorUnexpectedEOF */ - - expected_information = Value8Bit - 1; - if (value >= Value8Bit) - ++expected_information; - if (value > 0xffU) - ++expected_information; - if (value > 0xffffU) - ++expected_information; - if (value > 0xffffffffU) - ++expected_information; - return expected_information == additional_information ? - no_indicator : - indicators[additional_information - Value8Bit]; -} - -static const char *get_indicator(const CborValue *it, int flags) -{ - return resolve_indicator(it->ptr, it->parser->end, flags); -} - -static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft); -static CborError container_to_pretty(CborStreamFunction stream, void *out, CborValue *it, CborType containerType, - int flags, int recursionsLeft) -{ - const char *comma = ""; - CborError err = CborNoError; - - if (!recursionsLeft) { - printRecursionLimit(stream, out); - return err; /* do allow the dumping to continue */ - } - - while (!cbor_value_at_end(it) && !err) { - err = stream(out, "%s", comma); - comma = ", "; - - if (!err) - err = value_to_pretty(stream, out, it, flags, recursionsLeft); - - if (containerType == CborArrayType) - continue; - - /* map: that was the key, so get the value */ - if (!err) - err = stream(out, ": "); - if (!err) - err = value_to_pretty(stream, out, it, flags, recursionsLeft); - } - return err; -} - -static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft) -{ - CborError err = CborNoError; - CborType type = cbor_value_get_type(it); - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - const char *indicator = get_indicator(it, flags); - const char *space = *indicator ? " " : indicator; - - err = stream(out, "%c%s%s", type == CborArrayType ? '[' : '{', indicator, space); - if (err) - return err; - - err = cbor_value_enter_container(it, &recursed); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - err = container_to_pretty(stream, out, &recursed, type, flags, recursionsLeft - 1); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; /* parse error */ - - return stream(out, type == CborArrayType ? "]" : "}"); - } - - case CborIntegerType: { - uint64_t val; - cbor_value_get_raw_integer(it, &val); /* can't fail */ - - if (cbor_value_is_unsigned_integer(it)) { - err = stream(out, "%" PRIu64, val); - } else { - /* CBOR stores the negative number X as -1 - X - * (that is, -1 is stored as 0, -2 as 1 and so forth) */ - if (++val) { /* unsigned overflow may happen */ - err = stream(out, "-%" PRIu64, val); - } else { - /* overflown - * 0xffff`ffff`ffff`ffff + 1 = - * 0x1`0000`0000`0000`0000 = 18446744073709551616 (2^64) */ - err = stream(out, "-18446744073709551616"); - } - } - if (!err) - err = stream(out, "%s", get_indicator(it, flags)); - break; - } - - case CborByteStringType: - case CborTextStringType: { - size_t n = 0; - const void *ptr; - bool showingFragments = (flags & CborPrettyShowStringFragments) && !cbor_value_is_length_known(it); - const char *separator = ""; - char close = '\''; - char open[3] = "h'"; - const char *indicator = NULL; - - if (type == CborTextStringType) { - close = open[0] = '"'; - open[1] = '\0'; - } - - if (showingFragments) { - err = stream(out, "(_ "); - if (!err) - err = _cbor_value_prepare_string_iteration(it); - } else { - err = stream(out, "%s", open); - } - - while (!err) { - if (showingFragments || indicator == NULL) { - /* any iteration, except the second for a non-chunked string */ - indicator = resolve_indicator(it->ptr, it->parser->end, flags); - } - - err = _cbor_value_get_string_chunk(it, &ptr, &n, it); - if (err) - return err; - if (!ptr) - break; - - if (!err && showingFragments) - err = stream(out, "%s%s", separator, open); - if (!err) - err = (type == CborByteStringType ? - hexDump(stream, out, ptr, n) : - utf8EscapedDump(stream, out, ptr, n)); - if (!err && showingFragments) { - err = stream(out, "%c%s", close, indicator); - separator = ", "; - } - } - - if (!err) { - if (showingFragments) - err = stream(out, ")"); - else - err = stream(out, "%c%s", close, indicator); - } - return err; - } - - case CborTagType: { - CborTag tag; - cbor_value_get_tag(it, &tag); /* can't fail */ - err = stream(out, "%" PRIu64 "%s(", tag, get_indicator(it, flags)); - if (!err) - err = cbor_value_advance_fixed(it); - if (!err && recursionsLeft) - err = value_to_pretty(stream, out, it, flags, recursionsLeft - 1); - else if (!err) - printRecursionLimit(stream, out); - if (!err) - err = stream(out, ")"); - return err; - } - - case CborSimpleType: { - /* simple types can't fail and can't have overlong encoding */ - uint8_t simple_type; - cbor_value_get_simple_type(it, &simple_type); - err = stream(out, "simple(%" PRIu8 ")", simple_type); - break; - } - - case CborNullType: - err = stream(out, "null"); - break; - - case CborUndefinedType: - err = stream(out, "undefined"); - break; - - case CborBooleanType: { - bool val; - cbor_value_get_boolean(it, &val); /* can't fail */ - err = stream(out, val ? "true" : "false"); - break; - } - -#ifndef CBOR_NO_FLOATING_POINT - case CborDoubleType: { - const char *suffix; - double val; - int r; - uint64_t ival; - - if (false) { - float f; - case CborFloatType: - cbor_value_get_float(it, &f); - val = f; - suffix = flags & CborPrettyNumericEncodingIndicators ? "_2" : "f"; - } else if (false) { - uint16_t f16; - case CborHalfFloatType: -#ifndef CBOR_NO_HALF_FLOAT_TYPE - cbor_value_get_half_float(it, &f16); - val = decode_half(f16); - suffix = flags & CborPrettyNumericEncodingIndicators ? "_1" : "f16"; -#else - (void)f16; - err = CborErrorUnsupportedType; - break; -#endif - } else { - cbor_value_get_double(it, &val); - suffix = ""; - } - - if ((flags & CborPrettyNumericEncodingIndicators) == 0) { - r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) - suffix = ""; - } - - if (convertToUint64(val, &ival)) { - /* this double value fits in a 64-bit integer, so show it as such - * (followed by a floating point suffix, to disambiguate) */ - err = stream(out, "%s%" PRIu64 ".%s", val < 0 ? "-" : "", ival, suffix); - } else { - /* this number is definitely not a 64-bit integer */ - err = stream(out, "%." DBL_DECIMAL_DIG_STR "g%s", val, suffix); - } - break; - } -#else - case CborDoubleType: - case CborFloatType: - case CborHalfFloatType: - err = CborErrorUnsupportedType; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - - case CborInvalidType: - err = stream(out, "invalid"); - if (err) - return err; - return CborErrorUnknownType; - } - - if (!err) - err = cbor_value_advance_fixed(it); - return err; -} - -/** - * Converts the current CBOR type pointed by \a value to its textual - * representation and writes it to the stream by calling the \a streamFunction. - * If an error occurs, this function returns an error code similar to - * \ref CborParsing. - * - * The textual representation can be controlled by the \a flags parameter (see - * \ref CborPrettyFlags for more information). - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * The \a streamFunction function will be called with the \a token value as the - * first parameter and a printf-style format string as the second, with a variable - * number of further parameters. - * - * \sa cbor_value_to_pretty(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags) -{ - return value_to_pretty(streamFunction, token, value, flags, CBOR_PARSER_MAX_RECURSIONS); -} - -/** @} */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty_stdio.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty_stdio.c deleted file mode 100644 index 2013185..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborpretty_stdio.c +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include "cbor.h" -#include -#include - -static CborError cbor_fprintf(void *out, const char *fmt, ...) -{ - int n; - - va_list list; - va_start(list, fmt); - n = vfprintf((FILE *)out, fmt, list); - va_end(list); - - return n < 0 ? CborErrorIO : CborNoError; -} - -/** - * \fn CborError cbor_value_to_pretty(FILE *out, const CborValue *value) - * - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * \sa cbor_value_to_pretty_advance(), cbor_value_to_json_advance() - */ - -/** - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * \sa cbor_value_to_pretty(), cbor_value_to_pretty_stream(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value) -{ - return cbor_value_to_pretty_stream(cbor_fprintf, out, value, CborPrettyDefaultFlags); -} - -/** - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * The textual representation can be controlled by the \a flags parameter (see - * CborPrettyFlags for more information). - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * \sa cbor_value_to_pretty_stream(), cbor_value_to_pretty(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags) -{ - return cbor_value_to_pretty_stream(cbor_fprintf, out, value, flags); -} - diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbortojson.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbortojson.c deleted file mode 100644 index a0f3262..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cbortojson.c +++ /dev/null @@ -1,699 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _GNU_SOURCE 1 -#define _POSIX_C_SOURCE 200809L -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborjson.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include -#include -#include -#include - -/** - * \defgroup CborToJson Converting CBOR to JSON - * \brief Group of functions used to convert CBOR to JSON. - * - * This group contains two functions that can be used to convert a \ref - * CborValue object to an equivalent JSON representation. This module attempts - * to follow the recommendations from RFC 7049 section 4.1 "Converting from - * CBOR to JSON", though it has a few differences. They are noted below. - * - * These functions produce a "minified" JSON output, with no spacing, - * indentation or line breaks. If those are necessary, they need to be applied - * in a post-processing phase. - * - * Note that JSON cannot support all CBOR types with fidelity, so the - * conversion is usually lossy. For that reason, TinyCBOR supports adding a set - * of metadata JSON values that can be used by a JSON-to-CBOR converter to - * restore the original data types. - * - * The TinyCBOR library does not provide a way to convert from JSON - * representation back to encoded form. However, it provides a tool called - * \c json2cbor which can be used for that purpose. That tool supports the - * metadata format that these functions may produce. - * - * Either of the functions in this section will attempt to convert exactly one - * CborValue object to JSON. Those functions may return any error documented - * for the functions for CborParsing. In addition, if the C standard library - * stream functions return with error, the text conversion will return with - * error CborErrorIO. - * - * These functions also perform UTF-8 validation in CBOR text strings. If they - * encounter a sequence of bytes that is not permitted in UTF-8, they will return - * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points - * in UTF-8. - * - * \warning The metadata produced by these functions is not guaranteed to - * remain stable. A future update of TinyCBOR may produce different output for - * the same input and parsers may be unable to handle it. - * - * \sa CborParsing, CborPretty, cbor_parser_init() - */ - -/** - * \addtogroup CborToJson - * @{ - *

Conversion limitations

- * - * When converting from CBOR to JSON, there may be information loss. This - * section lists the possible scenarios. - * - * \par Number precision: - * ALL JSON numbers, due to its JavaScript heritage, are IEEE 754 - * double-precision floating point. This means JSON is not capable of - * representing all integers numbers outside the range [-(253)+1, - * 253-1] and is not capable of representing NaN or infinite. If the - * CBOR data contains a number outside the valid range, the conversion will - * lose precision. If the input was NaN or infinite, the result of the - * conversion will be the JSON null value. In addition, the distinction between - * half-, single- and double-precision is lost. - * - * \par - * If enabled, the original value and original type are stored in the metadata. - * - * \par Non-native types: - * CBOR's type system is richer than JSON's, which means some data values - * cannot be represented when converted to JSON. The conversion silently turns - * them into strings: CBOR simple types become "simple(nn)" where \c nn is the - * simple type's value, with the exception of CBOR undefined, which becomes - * "undefined", while CBOR byte strings are converted to an Base16, Base64, or - * Base64url encoding - * - * \par - * If enabled, the original type is stored in the metadata. - * - * \par Presence of tags: - * JSON has no support for tagged values, so by default tags are dropped when - * converting to JSON. However, if the CborConvertObeyByteStringTags option is - * active (default), then certain known tags are honored and are used to format - * the conversion of the tagged byte string to JSON. - * - * \par - * If the CborConvertTagsToObjects option is active, then the tag and the - * tagged value are converted to a JSON object. Otherwise, if enabled, the - * last (innermost) tag is stored in the metadata. - * - * \par Non-string keys in maps: - * JSON requires all Object keys to be strings, while CBOR does not. By - * default, if a non-string key is found, the conversion fails with error - * CborErrorJsonObjectKeyNotString. If the CborConvertStringifyMapKeys option - * is active, then the conversion attempts to create a string representation - * using CborPretty. Note that the \c json2cbor tool is not able to parse this - * back to the original form. - * - * \par Duplicate keys in maps: - * Neither JSON nor CBOR allow duplicated keys, but current TinyCBOR does not - * validate that this is the case. If there are duplicated keys in the input, - * they will be repeated in the output, which many JSON tools may flag as - * invalid. In addition to that, if the CborConvertStringifyMapKeys option is - * active, it is possible that a non-string key in a CBOR map will be converted - * to a string form that is identical to another key. - * - * \par - * When metadata support is active, the conversion will add extra key-value - * pairs to the JSON output so it can store the metadata. It is possible that - * the keys for the metadata clash with existing keys in the JSON map. - */ - -extern FILE *open_memstream(char **bufptr, size_t *sizeptr); - -enum ConversionStatusFlags { - TypeWasNotNative = 0x100, /* anything but strings, boolean, null, arrays and maps */ - TypeWasTagged = 0x200, - NumberPrecisionWasLost = 0x400, - NumberWasNaN = 0x800, - NumberWasInfinite = 0x1000, - NumberWasNegative = 0x2000, /* only used with NumberWasInifite or NumberWasTooBig */ - - FinalTypeMask = 0xff -}; - -typedef struct ConversionStatus { - CborTag lastTag; - uint64_t originalNumber; - int flags; -} ConversionStatus; - -static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status); - -static CborError dump_bytestring_base16(char **result, CborValue *it) -{ - static const char characters[] = "0123456789abcdef"; - size_t i; - size_t n = 0; - uint8_t *buffer; - CborError err = cbor_value_calculate_string_length(it, &n); - if (err) - return err; - - /* a Base16 (hex) output is twice as big as our buffer */ - buffer = (uint8_t *)malloc(n * 2 + 1); - *result = (char *)buffer; - - /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ - ++n; - err = cbor_value_copy_byte_string(it, buffer + n - 1, &n, it); - cbor_assert(err == CborNoError); - - for (i = 0; i < n; ++i) { - uint8_t byte = buffer[n + i]; - buffer[2*i] = characters[byte >> 4]; - buffer[2*i + 1] = characters[byte & 0xf]; - } - return CborNoError; -} - -static CborError generic_dump_base64(char **result, CborValue *it, const char alphabet[65]) -{ - size_t n = 0, i; - uint8_t *buffer, *out, *in; - CborError err = cbor_value_calculate_string_length(it, &n); - if (err) - return err; - - /* a Base64 output (untruncated) has 4 bytes for every 3 in the input */ - size_t len = (n + 5) / 3 * 4; - out = buffer = (uint8_t *)malloc(len + 1); - *result = (char *)buffer; - - /* we read our byte string at the tail end of the buffer - * so we can do an in-place conversion while iterating forwards */ - in = buffer + len - n; - - /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ - ++n; - err = cbor_value_copy_byte_string(it, in, &n, it); - cbor_assert(err == CborNoError); - - uint_least32_t val = 0; - for (i = 0; n - i >= 3; i += 3) { - /* read 3 bytes x 8 bits = 24 bits */ - if (false) { -#ifdef __GNUC__ - } else if (i) { - __builtin_memcpy(&val, in + i - 1, sizeof(val)); - val = cbor_ntohl(val); -#endif - } else { - val = (in[i] << 16) | (in[i + 1] << 8) | in[i + 2]; - } - - /* write 4 chars x 6 bits = 24 bits */ - *out++ = alphabet[(val >> 18) & 0x3f]; - *out++ = alphabet[(val >> 12) & 0x3f]; - *out++ = alphabet[(val >> 6) & 0x3f]; - *out++ = alphabet[val & 0x3f]; - } - - /* maybe 1 or 2 bytes left */ - if (n - i) { - /* we can read in[i + 1] even if it's past the end of the string because - * we know (by construction) that it's a NUL byte */ -#ifdef __GNUC__ - uint16_t val16; - __builtin_memcpy(&val16, in + i, sizeof(val16)); - val = cbor_ntohs(val16); -#else - val = (in[i] << 8) | in[i + 1]; -#endif - val <<= 8; - - /* the 65th character in the alphabet is our filler: either '=' or '\0' */ - out[4] = '\0'; - out[3] = alphabet[64]; - if (n - i == 2) { - /* write the third char in 3 chars x 6 bits = 18 bits */ - out[2] = alphabet[(val >> 6) & 0x3f]; - } else { - out[2] = alphabet[64]; /* filler */ - } - out[1] = alphabet[(val >> 12) & 0x3f]; - out[0] = alphabet[(val >> 18) & 0x3f]; - } else { - out[0] = '\0'; - } - - return CborNoError; -} - -static CborError dump_bytestring_base64(char **result, CborValue *it) -{ - static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789+/" "="; - return generic_dump_base64(result, it, alphabet); -} - -static CborError dump_bytestring_base64url(char **result, CborValue *it) -{ - static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789-_"; - return generic_dump_base64(result, it, alphabet); -} - -static CborError add_value_metadata(FILE *out, CborType type, const ConversionStatus *status) -{ - int flags = status->flags; - if (flags & TypeWasTagged) { - /* extract the tagged type, which may be JSON native */ - type = flags & FinalTypeMask; - flags &= ~(FinalTypeMask | TypeWasTagged); - - if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag, - flags & ~TypeWasTagged ? "," : "") < 0) - return CborErrorIO; - } - - if (!flags) - return CborNoError; - - /* print at least the type */ - if (fprintf(out, "\"t\":%d", type) < 0) - return CborErrorIO; - - if (flags & NumberWasNaN) - if (fprintf(out, ",\"v\":\"nan\"") < 0) - return CborErrorIO; - if (flags & NumberWasInfinite) - if (fprintf(out, ",\"v\":\"%sinf\"", flags & NumberWasNegative ? "-" : "") < 0) - return CborErrorIO; - if (flags & NumberPrecisionWasLost) - if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", flags & NumberWasNegative ? '-' : '+', - status->originalNumber) < 0) - return CborErrorIO; - if (type == CborSimpleType) - if (fprintf(out, ",\"v\":%d", (int)status->originalNumber) < 0) - return CborErrorIO; - return CborNoError; -} - -static CborError find_tagged_type(CborValue *it, CborTag *tag, CborType *type) -{ - CborError err = CborNoError; - *type = cbor_value_get_type(it); - while (*type == CborTagType) { - cbor_value_get_tag(it, tag); /* can't fail */ - err = cbor_value_advance_fixed(it); - if (err) - return err; - - *type = cbor_value_get_type(it); - } - return err; -} - -static CborError tagged_value_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - CborTag tag; - CborError err; - - if (flags & CborConvertTagsToObjects) { - cbor_value_get_tag(it, &tag); /* can't fail */ - err = cbor_value_advance_fixed(it); - if (err) - return err; - - if (fprintf(out, "{\"tag%" PRIu64 "\":", tag) < 0) - return CborErrorIO; - - CborType type = cbor_value_get_type(it); - err = value_to_json(out, it, flags, type, status); - if (err) - return err; - if (flags & CborConvertAddMetadata && status->flags) { - if (fprintf(out, ",\"tag%" PRIu64 "$cbor\":{", tag) < 0 || - add_value_metadata(out, type, status) != CborNoError || - fputc('}', out) < 0) - return CborErrorIO; - } - if (fputc('}', out) < 0) - return CborErrorIO; - status->flags = TypeWasNotNative | CborTagType; - return CborNoError; - } - - CborType type; - err = find_tagged_type(it, &status->lastTag, &type); - if (err) - return err; - tag = status->lastTag; - - /* special handling of byte strings? */ - if (type == CborByteStringType && (flags & CborConvertByteStringsToBase64Url) == 0 && - (tag == CborNegativeBignumTag || tag == CborExpectedBase16Tag || tag == CborExpectedBase64Tag)) { - char *str; - const char *pre = ""; - - if (tag == CborNegativeBignumTag) { - pre = "~"; - err = dump_bytestring_base64url(&str, it); - } else if (tag == CborExpectedBase64Tag) { - err = dump_bytestring_base64(&str, it); - } else { /* tag == CborExpectedBase16Tag */ - err = dump_bytestring_base16(&str, it); - } - if (err) - return err; - err = fprintf(out, "\"%s%s\"", pre, str) < 0 ? CborErrorIO : CborNoError; - free(str); - status->flags = TypeWasNotNative | TypeWasTagged | CborByteStringType; - return err; - } - - /* no special handling */ - err = value_to_json(out, it, flags, type, status); - status->flags |= TypeWasTagged | type; - return err; -} - -static CborError stringify_map_key(char **key, CborValue *it, int flags, CborType type) -{ - (void)flags; /* unused */ - (void)type; /* unused */ -#ifdef WITHOUT_OPEN_MEMSTREAM - (void)key; /* unused */ - (void)it; /* unused */ - return CborErrorJsonNotImplemented; -#else - size_t size; - - FILE *memstream = open_memstream(key, &size); - if (memstream == NULL) - return CborErrorOutOfMemory; /* could also be EMFILE, but it's unlikely */ - CborError err = cbor_value_to_pretty_advance(memstream, it); - - if (unlikely(fclose(memstream) < 0 || *key == NULL)) - return CborErrorInternalError; - return err; -#endif -} - -static CborError array_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - const char *comma = ""; - while (!cbor_value_at_end(it)) { - if (fprintf(out, "%s", comma) < 0) - return CborErrorIO; - comma = ","; - - CborError err = value_to_json(out, it, flags, cbor_value_get_type(it), status); - if (err) - return err; - } - return CborNoError; -} - -static CborError map_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - const char *comma = ""; - CborError err; - while (!cbor_value_at_end(it)) { - char *key; - if (fprintf(out, "%s", comma) < 0) - return CborErrorIO; - comma = ","; - - CborType keyType = cbor_value_get_type(it); - if (likely(keyType == CborTextStringType)) { - size_t n = 0; - err = cbor_value_dup_text_string(it, &key, &n, it); - } else if (flags & CborConvertStringifyMapKeys) { - err = stringify_map_key(&key, it, flags, keyType); - } else { - return CborErrorJsonObjectKeyNotString; - } - if (err) - return err; - - /* first, print the key */ - if (fprintf(out, "\"%s\":", key) < 0) { - free(key); - return CborErrorIO; - } - - /* then, print the value */ - CborType valueType = cbor_value_get_type(it); - err = value_to_json(out, it, flags, valueType, status); - - /* finally, print any metadata we may have */ - if (flags & CborConvertAddMetadata) { - if (!err && keyType != CborTextStringType) { - if (fprintf(out, ",\"%s$keycbordump\":true", key) < 0) - err = CborErrorIO; - } - if (!err && status->flags) { - if (fprintf(out, ",\"%s$cbor\":{", key) < 0 || - add_value_metadata(out, valueType, status) != CborNoError || - fputc('}', out) < 0) - err = CborErrorIO; - } - } - - free(key); - if (err) - return err; - } - return CborNoError; -} - -static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status) -{ - CborError err; - status->flags = 0; - - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - err = cbor_value_enter_container(it, &recursed); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - if (fputc(type == CborArrayType ? '[' : '{', out) < 0) - return CborErrorIO; - - err = (type == CborArrayType) ? - array_to_json(out, &recursed, flags, status) : - map_to_json(out, &recursed, flags, status); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - - if (fputc(type == CborArrayType ? ']' : '}', out) < 0) - return CborErrorIO; - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; /* parse error */ - - status->flags = 0; /* reset, there are never conversion errors for us */ - return CborNoError; - } - - case CborIntegerType: { - double num; /* JS numbers are IEEE double precision */ - uint64_t val; - cbor_value_get_raw_integer(it, &val); /* can't fail */ - num = (double)val; - - if (cbor_value_is_negative_integer(it)) { - num = -num - 1; /* convert to negative */ - if ((uint64_t)(-num - 1) != val) { - status->flags = NumberPrecisionWasLost | NumberWasNegative; - status->originalNumber = val; - } - } else { - if ((uint64_t)num != val) { - status->flags = NumberPrecisionWasLost; - status->originalNumber = val; - } - } - if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */ - return CborErrorIO; - break; - } - - case CborByteStringType: - case CborTextStringType: { - char *str; - if (type == CborByteStringType) { - err = dump_bytestring_base64url(&str, it); - status->flags = TypeWasNotNative; - } else { - size_t n = 0; - err = cbor_value_dup_text_string(it, &str, &n, it); - } - if (err) - return err; - err = (fprintf(out, "\"%s\"", str) < 0) ? CborErrorIO : CborNoError; - free(str); - return err; - } - - case CborTagType: - return tagged_value_to_json(out, it, flags, status); - - case CborSimpleType: { - uint8_t simple_type; - cbor_value_get_simple_type(it, &simple_type); /* can't fail */ - status->flags = TypeWasNotNative; - status->originalNumber = simple_type; - if (fprintf(out, "\"simple(%" PRIu8 ")\"", simple_type) < 0) - return CborErrorIO; - break; - } - - case CborNullType: - if (fprintf(out, "null") < 0) - return CborErrorIO; - break; - - case CborUndefinedType: - status->flags = TypeWasNotNative; - if (fprintf(out, "\"undefined\"") < 0) - return CborErrorIO; - break; - - case CborBooleanType: { - bool val; - cbor_value_get_boolean(it, &val); /* can't fail */ - if (fprintf(out, val ? "true" : "false") < 0) - return CborErrorIO; - break; - } - -#ifndef CBOR_NO_FLOATING_POINT - case CborDoubleType: { - double val; - if (false) { - float f; - case CborFloatType: - status->flags = TypeWasNotNative; - cbor_value_get_float(it, &f); - val = f; - } else if (false) { - uint16_t f16; - case CborHalfFloatType: -# ifndef CBOR_NO_HALF_FLOAT_TYPE - status->flags = TypeWasNotNative; - cbor_value_get_half_float(it, &f16); - val = decode_half(f16); -# else - (void)f16; - err = CborErrorUnsupportedType; - break; -# endif - } else { - cbor_value_get_double(it, &val); - } - - int r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) { - if (fprintf(out, "null") < 0) - return CborErrorIO; - status->flags |= r == FP_NAN ? NumberWasNaN : - NumberWasInfinite | (val < 0 ? NumberWasNegative : 0); - } else { - uint64_t ival = (uint64_t)fabs(val); - if ((double)ival == fabs(val)) { - /* print as integer so we get the full precision */ - r = fprintf(out, "%s%" PRIu64, val < 0 ? "-" : "", ival); - status->flags |= TypeWasNotNative; /* mark this integer number as a double */ - } else { - /* this number is definitely not a 64-bit integer */ - r = fprintf(out, "%." DBL_DECIMAL_DIG_STR "g", val); - } - if (r < 0) - return CborErrorIO; - } - break; - } -#else - case CborDoubleType: - case CborFloatType: - case CborHalfFloatType: - err = CborErrorUnsupportedType; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - - case CborInvalidType: - return CborErrorUnknownType; - } - - return cbor_value_advance_fixed(it); -} - -/** - * \enum CborToJsonFlags - * The CborToJsonFlags enum contains flags that control the conversion of CBOR to JSON. - * - * \value CborConvertAddMetadata Adds metadata to facilitate restoration of the original CBOR data. - * \value CborConvertTagsToObjects Converts CBOR tags to JSON objects - * \value CborConvertIgnoreTags (default) Ignore CBOR tags, except for byte strings - * \value CborConvertObeyByteStringTags (default) Honor formatting of CBOR byte strings if so tagged - * \value CborConvertByteStringsToBase64Url Force the conversion of all CBOR byte strings to Base64url encoding, despite any tags - * \value CborConvertRequireMapStringKeys (default) Require CBOR map keys to be strings, failing the conversion if they are not - * \value CborConvertStringifyMapKeys Convert non-string keys in CBOR maps to a string form - * \value CborConvertDefaultFlags Default conversion flags. - */ - -/** - * \fn CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) - * - * Converts the current CBOR type pointed to by \a value to JSON and writes that - * to the \a out stream. If an error occurs, this function returns an error - * code similar to CborParsing. The \a flags parameter indicates one or more of - * the flags from CborToJsonFlags that control the conversion. - * - * \sa cbor_value_to_json_advance(), cbor_value_to_pretty() - */ - -/** - * Converts the current CBOR type pointed to by \a value to JSON and writes that - * to the \a out stream. If an error occurs, this function returns an error - * code similar to CborParsing. The \a flags parameter indicates one or more of - * the flags from CborToJsonFlags that control the conversion. - * - * If no error ocurred, this function advances \a value to the next element. - * - * \sa cbor_value_to_json(), cbor_value_to_pretty_advance() - */ -CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) -{ - ConversionStatus status; - return value_to_json(out, value, flags, cbor_value_get_type(value), &status); -} - -/** @} */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborvalidation.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborvalidation.c deleted file mode 100644 index 6c9d383..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/cborvalidation.c +++ /dev/null @@ -1,670 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" -#include "utf8_p.h" - -#include - -#ifndef CBOR_NO_FLOATING_POINT -# include -# include -#endif - - -#ifndef CBOR_PARSER_MAX_RECURSIONS -# define CBOR_PARSER_MAX_RECURSIONS 1024 -#endif - -/** - * \addtogroup CborParsing - * @{ - */ - -/** - * \enum CborValidationFlags - * The CborValidationFlags enum contains flags that control the validation of a - * CBOR stream. - * - * \value CborValidateBasic Validates only the syntactic correctedness of the stream. - * \value CborValidateCanonical Validates that the stream is in canonical format, according to - * RFC 7049 section 3.9. - * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10. - * \value CborValidateStrictest Attempt to perform the strictest validation we know of. - * - * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are - * enconded in their shortest form possible. - * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded - * in their shortest form possible. - * \value CborValidateShortestNumbers (Canonical) Validate both integral and floating-point numbers - * are in their shortest form possible. - * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses - * indeterminate length encoding. - * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in - * sorted order. - * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique. - * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the - * correct types. This does not validate that the content of - * those types is syntactically correct. For example, this - * option validates that tag 1 (DateTimeString) is used with - * a Text String, but it does not validate that the string is - * a valid date/time representation. - * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately - * encoded in UTF-8. - * \value CborValidateMapKeysAreString Validate that all map keys are text strings. - * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present. - * \value CborValidateNoTags Validate that no tags are used. - * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or - * infinities are allowed). - * \value CborValidateCompleteData Validate that the stream is complete and there is no more data - * in the buffer. - * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered - * with IANA. - * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA. - * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA. - * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags - * are registered with IANA (see below for limitations). - * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA - * (see below for limitations). - * - * \par Simple type registry - * The CBOR specification requires that registration for use of the first 19 - * simple types must be done by way of Standards Action. The rest of the simple - * types only require a specification. The official list can be obtained from - * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml. - * - * \par - * There are no registered simple types recognized by this release of TinyCBOR - * (beyond those defined by RFC 7049). - * - * \par Tag registry - * The CBOR specification requires that registration for use of the first 23 - * tags must be done by way of Standards Action. The next up to tag 255 only - * require a specification. Finally, all other tags can be registered on a - * first-come-first-serve basis. The official list can be ontained from - * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml. - * - * \par - * Given the variability of this list, TinyCBOR cannot recognize all tags - * registered with IANA. Instead, the implementation only recognizes tags - * that are backed by an RFC. - * - * \par - * These are the tags known to the current TinyCBOR release: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TagData ItemSemantics
0UTF-8 text stringStandard date/time string
1integerEpoch-based date/time
2byte stringPositive bignum
3byte stringNegative bignum
4arrayDecimal fraction
5arrayBigfloat
16arrayCOSE Single Recipient Encrypted Data Object (RFC 8152)
17arrayCOSE Mac w/o Recipients Object (RFC 8152)
18arrayCOSE Single Signer Data Object (RFC 8162)
21byte string, array, mapExpected conversion to base64url encoding
22byte string, array, mapExpected conversion to base64 encoding
23byte string, array, mapExpected conversion to base16 encoding
24byte stringEncoded CBOR data item
32UTF-8 text stringURI
33UTF-8 text stringbase64url
34UTF-8 text stringbase64
35UTF-8 text stringRegular expression
36UTF-8 text stringMIME message
96arrayCOSE Encrypted Data Object (RFC 8152)
97arrayCOSE MACed Data Object (RFC 8152)
98arrayCOSE Signed Data Object (RFC 8152)
55799anySelf-describe CBOR
- */ - -struct KnownTagData { uint32_t tag; uint32_t types; }; -static const struct KnownTagData knownTagData[] = { - { 0, (uint32_t)CborTextStringType }, - { 1, (uint32_t)(CborIntegerType+1) }, - { 2, (uint32_t)CborByteStringType }, - { 3, (uint32_t)CborByteStringType }, - { 4, (uint32_t)CborArrayType }, - { 5, (uint32_t)CborArrayType }, - { 16, (uint32_t)CborArrayType }, - { 17, (uint32_t)CborArrayType }, - { 18, (uint32_t)CborArrayType }, - { 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 24, (uint32_t)CborByteStringType }, - { 32, (uint32_t)CborTextStringType }, - { 33, (uint32_t)CborTextStringType }, - { 34, (uint32_t)CborTextStringType }, - { 35, (uint32_t)CborTextStringType }, - { 36, (uint32_t)CborTextStringType }, - { 96, (uint32_t)CborArrayType }, - { 97, (uint32_t)CborArrayType }, - { 98, (uint32_t)CborArrayType }, - { 55799, 0U } -}; - -static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft); - -static inline CborError validate_utf8_string(const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - const uint8_t * const end = buffer + n; - while (buffer < end) { - uint32_t uc = get_utf8(&buffer, end); - if (uc == ~0U) - return CborErrorInvalidUtf8TextString; - } - return CborNoError; -} - -static inline CborError validate_simple_type(uint8_t simple_type, uint32_t flags) -{ - /* At current time, all known simple types are those from RFC 7049, - * which are parsed by the parser into different CBOR types. - * That means that if we've got here, the type is unknown */ - if (simple_type < 32) - return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError; - return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ? - CborErrorUnknownSimpleType : CborNoError; -} - -static inline CborError validate_number(const CborValue *it, CborType type, uint32_t flags) -{ - CborError err = CborNoError; - const uint8_t *ptr = it->ptr; - size_t bytesUsed, bytesNeeded; - uint64_t value; - - if ((flags & CborValidateShortestIntegrals) == 0) - return err; - if (type >= CborHalfFloatType && type <= CborDoubleType) - return err; /* checked elsewhere */ - - err = _cbor_value_extract_number(&ptr, it->parser->end, &value); - if (err) - return err; - - bytesUsed = (size_t)(ptr - it->ptr - 1); - bytesNeeded = 0; - if (value >= Value8Bit) - ++bytesNeeded; - if (value > 0xffU) - ++bytesNeeded; - if (value > 0xffffU) - bytesNeeded += 2; - if (value > 0xffffffffU) - bytesNeeded += 4; - if (bytesNeeded < bytesUsed) - return CborErrorOverlongEncoding; - return CborNoError; -} - -static inline CborError validate_tag(CborValue *it, CborTag tag, uint32_t flags, int recursionLeft) -{ - CborType type = cbor_value_get_type(it); - const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]); - const struct KnownTagData *tagData = knownTagData; - const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount; - - if (!recursionLeft) - return CborErrorNestingTooDeep; - if (flags & CborValidateNoTags) - return CborErrorExcludedType; - - /* find the tag data, if any */ - for ( ; tagData != knownTagDataEnd; ++tagData) { - if (tagData->tag < tag) - continue; - if (tagData->tag > tag) - tagData = NULL; - break; - } - if (tagData == knownTagDataEnd) - tagData = NULL; - - if (flags & CborValidateNoUnknownTags && !tagData) { - /* tag not found */ - if (flags & CborValidateNoUnknownTagsSA && tag < 24) - return CborErrorUnknownTag; - if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256) - return CborErrorUnknownTag; - if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags) - return CborErrorUnknownTag; - } - - if (flags & CborValidateTagUse && tagData && tagData->types) { - uint32_t allowedTypes = tagData->types; - - /* correct Integer so it's not zero */ - if (type == CborIntegerType) - type = (CborType)(type + 1); - - while (allowedTypes) { - if ((uint8_t)(allowedTypes & 0xff) == type) - break; - allowedTypes >>= 8; - } - if (!allowedTypes) - return CborErrorInappropriateTagForType; - } - - return validate_value(it, flags, recursionLeft); -} - -#ifndef CBOR_NO_FLOATING_POINT -static inline CborError validate_floating_point(CborValue *it, CborType type, uint32_t flags) -{ - CborError err; - int r; - double val; - float valf; - uint16_t valf16; - - if (type != CborDoubleType) { - if (type == CborFloatType) { - err = cbor_value_get_float(it, &valf); - val = valf; - } else { -# ifdef CBOR_NO_HALF_FLOAT_TYPE - (void)valf16; - return CborErrorUnsupportedType; -# else - err = cbor_value_get_half_float(it, &valf16); - val = decode_half(valf16); -# endif - } - } else { - err = cbor_value_get_double(it, &val); - } - cbor_assert(err == CborNoError); /* can't fail */ - - r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) { - if (flags & CborValidateFiniteFloatingPoint) - return CborErrorExcludedValue; - if (flags & CborValidateShortestFloatingPoint) { - if (type == CborDoubleType) - return CborErrorOverlongEncoding; -# ifndef CBOR_NO_HALF_FLOAT_TYPE - if (type == CborFloatType) - return CborErrorOverlongEncoding; - if (r == FP_NAN && valf16 != 0x7e00) - return CborErrorImproperValue; - if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00) - return CborErrorImproperValue; -# endif - } - } - - if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) { - if (type == CborDoubleType) { - valf = (float)val; - if ((double)valf == val) - return CborErrorOverlongEncoding; - } -# ifndef CBOR_NO_HALF_FLOAT_TYPE - if (type == CborFloatType) { - valf16 = encode_half(valf); - if (valf == decode_half(valf16)) - return CborErrorOverlongEncoding; - } -# endif - } - - return CborNoError; -} -#endif - -static CborError validate_container(CborValue *it, int containerType, uint32_t flags, int recursionLeft) -{ - CborError err; - const uint8_t *previous = NULL; - const uint8_t *previous_end = NULL; - - if (!recursionLeft) - return CborErrorNestingTooDeep; - - while (!cbor_value_at_end(it)) { - const uint8_t *current = cbor_value_get_next_byte(it); - - if (containerType == CborMapType) { - if (flags & CborValidateMapKeysAreString) { - CborType type = cbor_value_get_type(it); - if (type == CborTagType) { - /* skip the tags */ - CborValue copy = *it; - err = cbor_value_skip_tag(©); - if (err) - return err; - type = cbor_value_get_type(©); - } - if (type != CborTextStringType) - return CborErrorMapKeyNotString; - } - } - - err = validate_value(it, flags, recursionLeft); - if (err) - return err; - - if (containerType != CborMapType) - continue; - - if (flags & CborValidateMapIsSorted) { - if (previous) { - uint64_t len1, len2; - const uint8_t *ptr; - - /* extract the two lengths */ - ptr = previous; - _cbor_value_extract_number(&ptr, it->parser->end, &len1); - ptr = current; - _cbor_value_extract_number(&ptr, it->parser->end, &len2); - - if (len1 > len2) - return CborErrorMapNotSorted; - if (len1 == len2) { - size_t bytelen1 = (size_t)(previous_end - previous); - size_t bytelen2 = (size_t)(it->ptr - current); - int r = memcmp(previous, current, bytelen1 <= bytelen2 ? bytelen1 : bytelen2); - - if (r == 0 && bytelen1 != bytelen2) - r = bytelen1 < bytelen2 ? -1 : +1; - if (r > 0) - return CborErrorMapNotSorted; - if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique) - return CborErrorMapKeysNotUnique; - } - } - - previous = current; - previous_end = it->ptr; - } - - /* map: that was the key, so get the value */ - err = validate_value(it, flags, recursionLeft); - if (err) - return err; - } - return CborNoError; -} - -static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft) -{ - CborError err; - CborType type = cbor_value_get_type(it); - - if (cbor_value_is_length_known(it)) { - err = validate_number(it, type, flags); - if (err) - return err; - } else { - if (flags & CborValidateNoIndeterminateLength) - return CborErrorUnknownLength; - } - - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - err = cbor_value_enter_container(it, &recursed); - if (!err) - err = validate_container(&recursed, type, flags, recursionLeft - 1); - if (err) { - it->ptr = recursed.ptr; - return err; - } - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; - return CborNoError; - } - - case CborIntegerType: { - uint64_t val; - err = cbor_value_get_raw_integer(it, &val); - cbor_assert(err == CborNoError); /* can't fail */ - - break; - } - - case CborByteStringType: - case CborTextStringType: { - size_t n = 0; - const void *ptr; - - err = _cbor_value_prepare_string_iteration(it); - if (err) - return err; - - while (1) { - CborValue next; - err = _cbor_value_get_string_chunk(it, &ptr, &n, &next); - if (err) - return err; - if (ptr) { - err = validate_number(it, type, flags); - if (err) - return err; - } - - *it = next; - if (!ptr) - break; - - if (type == CborTextStringType && flags & CborValidateUtf8) { - err = validate_utf8_string(ptr, n); - if (err) - return err; - } - } - - return CborNoError; - } - - case CborTagType: { - CborTag tag; - err = cbor_value_get_tag(it, &tag); - cbor_assert(err == CborNoError); /* can't fail */ - - err = cbor_value_advance_fixed(it); - if (err) - return err; - err = validate_tag(it, tag, flags, recursionLeft - 1); - if (err) - return err; - - return CborNoError; - } - - case CborSimpleType: { - uint8_t simple_type; - err = cbor_value_get_simple_type(it, &simple_type); - cbor_assert(err == CborNoError); /* can't fail */ - err = validate_simple_type(simple_type, flags); - if (err) - return err; - break; - } - - case CborNullType: - case CborBooleanType: - break; - - case CborUndefinedType: - if (flags & CborValidateNoUndefined) - return CborErrorExcludedType; - break; - - case CborHalfFloatType: - case CborFloatType: - case CborDoubleType: { -#ifdef CBOR_NO_FLOATING_POINT - return CborErrorUnsupportedType; -#else - err = validate_floating_point(it, type, flags); - if (err) - return err; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - } - - case CborInvalidType: - return CborErrorUnknownType; - } - - err = cbor_value_advance_fixed(it); - return err; -} - -/** - * Performs a full validation, controlled by the \a flags options, of the CBOR - * stream pointed by \a it and returns the error it found. If no error was - * found, it returns CborNoError and the application can iterate over the items - * with certainty that no errors will appear during parsing. - * - * If \a flags is CborValidateBasic, the result should be the same as - * cbor_value_validate_basic(). - * - * This function has the same timing and memory requirements as - * cbor_value_advance() and cbor_value_validate_basic(). - * - * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance() - */ -CborError cbor_value_validate(const CborValue *it, uint32_t flags) -{ - CborValue value = *it; - CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS); - if (err) - return err; - if (flags & CborValidateCompleteData && it->ptr != it->parser->end) - return CborErrorGarbageAtEnd; - return CborNoError; -} - -/** - * @} - */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/compilersupport_p.h b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/compilersupport_p.h deleted file mode 100644 index 0879801..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/compilersupport_p.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef COMPILERSUPPORT_H -#define COMPILERSUPPORT_H - -#include "cbor.h" - -#ifndef _BSD_SOURCE -# define _BSD_SOURCE -#endif -#ifndef _DEFAULT_SOURCE -# define _DEFAULT_SOURCE -#endif -#ifndef assert -# include -#endif -#include -#include -#include - -#ifndef __cplusplus -# include -#endif - -#if __STDC_VERSION__ >= 201112L || (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__cpp_static_assert) && __cpp_static_assert >= 200410) -# define cbor_static_assert(x) static_assert(x, #x) -#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L) -# define cbor_static_assert(x) _Static_assert(x, #x) -#else -# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1])) -#endif -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -/* inline is a keyword */ -#else -/* use the definition from cbor.h */ -# define inline CBOR_INLINE -#endif - -#ifdef NDEBUG -# define cbor_assert(cond) do { if (!(cond)) unreachable(); } while (0) -#else -# define cbor_assert(cond) assert(cond) -#endif - -#ifndef STRINGIFY -#define STRINGIFY(x) STRINGIFY2(x) -#endif -#define STRINGIFY2(x) #x - -#if !defined(UINT32_MAX) || !defined(INT64_MAX) -/* C89? We can define UINT32_MAX portably, but not INT64_MAX */ -# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX" -#endif - -#ifndef DBL_DECIMAL_DIG -/* DBL_DECIMAL_DIG is C11 */ -# define DBL_DECIMAL_DIG 17 -#endif -#define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG) - -#if defined(__GNUC__) && defined(__i386__) && !defined(__iamcu__) -# define CBOR_INTERNAL_API_CC __attribute__((regparm(3))) -#elif defined(_MSC_VER) && defined(_M_IX86) -# define CBOR_INTERNAL_API_CC __fastcall -#else -# define CBOR_INTERNAL_API_CC -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif - -#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \ - (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32)) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define cbor_ntohll __builtin_bswap64 -# define cbor_htonll __builtin_bswap64 -# define cbor_ntohl __builtin_bswap32 -# define cbor_htonl __builtin_bswap32 -# ifdef __INTEL_COMPILER -# define cbor_ntohs _bswap16 -# define cbor_htons _bswap16 -# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16) -# define cbor_ntohs __builtin_bswap16 -# define cbor_htons __builtin_bswap16 -# else -# define cbor_ntohs(x) (((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8)) -# define cbor_htons cbor_ntohs -# endif -# else -# define cbor_ntohll -# define cbor_htonll -# define cbor_ntohl -# define cbor_htonl -# define cbor_ntohs -# define cbor_htons -# endif -#elif defined(__sun) -# include -#elif defined(_MSC_VER) -/* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */ -# include -# define cbor_ntohll _byteswap_uint64 -# define cbor_htonll _byteswap_uint64 -# define cbor_ntohl _byteswap_ulong -# define cbor_htonl _byteswap_ulong -# define cbor_ntohs _byteswap_ushort -# define cbor_htons _byteswap_ushort -#endif -#ifndef cbor_ntohs -# include -# define cbor_ntohs ntohs -# define cbor_htons htons -#endif -#ifndef cbor_ntohl -# include -# define cbor_ntohl ntohl -# define cbor_htonl htonl -#endif -#ifndef cbor_ntohll -# define cbor_ntohll ntohll -# define cbor_htonll htonll -/* ntohll isn't usually defined */ -# ifndef ntohll -# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ - (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \ - (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \ - defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__) -# define ntohll -# define htonll -# elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ - (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) || \ - defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ - defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) -# define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32))) -# define htonll ntohll -# else -# error "Unable to determine byte order!" -# endif -# endif -#endif - - -#ifdef __cplusplus -# define CONST_CAST(t, v) const_cast(v) -#else -/* C-style const_cast without triggering a warning with -Wcast-qual */ -# define CONST_CAST(t, v) (t)(uintptr_t)(v) -#endif - -#ifdef __GNUC__ -#ifndef likely -# define likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef unlikely -# define unlikely(x) __builtin_expect(!!(x), 0) -#endif -# define unreachable() __builtin_unreachable() -#elif defined(_MSC_VER) -# define likely(x) (x) -# define unlikely(x) (x) -# define unreachable() __assume(0) -#else -# define likely(x) (x) -# define unlikely(x) (x) -# define unreachable() do {} while (0) -#endif - -static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r) -{ -#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow) - return __builtin_add_overflow(v1, v2, r); -#else - /* unsigned additions are well-defined */ - *r = v1 + v2; - return v1 > v1 + v2; -#endif -} - -#endif /* COMPILERSUPPORT_H */ - diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/open_memstream.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/open_memstream.c deleted file mode 100644 index 6765e63..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/open_memstream.c +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _GNU_SOURCE 1 - -//#include -#include -#include -#include -#include - -// #if defined(__unix__) || defined(__APPLE__) -// # include -// #endif -// #ifdef __APPLE__ -typedef int RetType; -typedef int LenType; -// #elif __linux__ -// typedef int RetType; -// typedef int LenType; -// #else -// # error "Cannot implement open_memstream!" -// #endif -#define EFBIG 27 /* File too large */ -#include "compilersupport_p.h" - -struct Buffer -{ - char **ptr; - size_t *len; - size_t alloc; -}; - -FILE *open_memstream(char **bufptr, size_t *lenptr) -{ - struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer)); - if (b == NULL) - return NULL; - b->alloc = 0; - b->len = lenptr; - b->ptr = bufptr; - *bufptr = NULL; - *lenptr = 0; - -#ifdef __APPLE__ - return funopen(b, NULL, write_to_buffer, NULL, close_buffer); -#elif __linux__ - static const cookie_io_functions_t vtable = { - NULL, - write_to_buffer, - NULL, - close_buffer - }; - return fopencookie(b, "w", vtable); -#else - return NULL; -#endif -} - diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/parsetags.pl b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/parsetags.pl deleted file mode 100755 index fbb1829..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/parsetags.pl +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/perl -l -## Copyright (C) 2017 Intel Corporation -## -## Permission is hereby granted, free of charge, to any person obtaining a copy -## of this software and associated documentation files (the "Software"), to deal -## in the Software without restriction, including without limitation the rights -## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -## copies of the Software, and to permit persons to whom the Software is -## furnished to do so, subject to the following conditions: -## -## The above copyright notice and this permission notice shall be included in -## all copies or substantial portions of the Software. -## -## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -## THE SOFTWARE. -## -use strict; -my $fname = shift @ARGV - or die("Usage: parsetags.pl tags.txt"); -open TAGS, "<", $fname - or die("Cannot open $fname: $!"); - -my %typedescriptions = ( - "Integer" => "integer", - "ByteString" => "byte string", - "TextString" => "UTF-8 text string", - "Array" => "array", - "Map" => "map", - "Tag" => "tag", # shouldn't happen - "Simple" => "any simple type", - "Boolean" => "boolean", - "Null" => "null", - "Undefined" => "undefined", - "HalfFloat" => "IEEE 754 half-precision floating point", - "Float" => "IEEE 754 single-precision floating point", - "Double" => "IEEE 754 double-precision floating point" -); - -my %tags; -while () { - s/\s*#.*$//; - next if /^$/; - chomp; - - die("Could not parse line \"$_\"") - unless /^(\d+);(\w+);([\w,]*);(.*)$/; - $tags{$1}{id} = $2; - $tags{$1}{semantic} = $4; - my @types = split(',', $3); - $tags{$1}{types} = \@types; -} -close TAGS or die; - -my @tagnumbers = sort { $a <=> $b } keys %tags; - -print "==== HTML listing ===="; -print "\n \n \n \n \n "; -for my $n (@tagnumbers) { - print " "; - print " "; - - my @types = @{$tags{$n}{types}}; - @types = map { $typedescriptions{$_}; } @types; - unshift @types, "any" - if (scalar @types == 0); - printf " \n", join(', ', @types); - printf " \n", $tags{$n}{semantic}; - print " "; -} -print "
TagData ItemSemantics
$n%s%s
"; - -print "\n==== enum listing for cbor.h ====\n"; -printf "typedef enum CborKnownTags {"; -my $comma = ""; -for my $n (@tagnumbers) { - printf "%s\n Cbor%sTag%s = %d", $comma, - $tags{$n}{id}, - ' ' x (23 - length($tags{$n}{id})), - $n; - $comma = ","; -} -print "\n} CborKnownTags;"; -print "\n/* #define the constants so we can check with #ifdef */"; -for my $n (@tagnumbers) { - printf "#define Cbor%sTag Cbor%sTag\n", $tags{$n}{id}, $tags{$n}{id}; -} - -print "\n==== search table ====\n"; -print "struct KnownTagData { uint32_t tag; uint32_t types; };"; -printf "static const struct KnownTagData knownTagData[] = {"; -$comma = ""; -for my $n (@tagnumbers) { - my @types = @{$tags{$n}{types}}; - - my $typemask; - my $shift = 0; - for my $type (@types) { - die("Too many match types for tag $n") if $shift == 32; - my $actualtype = "Cbor${type}Type"; - $actualtype = "($actualtype+1)" if $type eq "Integer"; - $typemask .= " | " if $typemask ne ""; - $typemask .= "((uint32_t)$actualtype << $shift)" if $shift; - $typemask .= "(uint32_t)$actualtype" unless $shift; - $shift += 8; - } - $typemask = "0U" if $typemask eq ""; - - printf "%s\n { %d, %s }", $comma, $n, $typemask; - $comma = ","; -} -print "\n};"; diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/src.pri b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/src.pri deleted file mode 100644 index 01887aa..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/src.pri +++ /dev/null @@ -1,16 +0,0 @@ -SOURCES += \ - $$PWD/cborencoder.c \ - $$PWD/cborencoder_close_container_checked.c \ - $$PWD/cborerrorstrings.c \ - $$PWD/cborparser.c \ - $$PWD/cborparser_dup_string.c \ - $$PWD/cborpretty.c \ - $$PWD/cbortojson.c \ - $$PWD/cborvalidation.c \ - -HEADERS += $$PWD/cbor.h $$PWD/tinycbor-version.h - -QMAKE_CFLAGS *= $$QMAKE_CFLAGS_SPLIT_SECTIONS -QMAKE_LFLAGS *= $$QMAKE_LFLAGS_GCSECTIONS -INCLUDEPATH += $$PWD -CONFIG(release, debug|release): DEFINES += NDEBUG diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tags.txt b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tags.txt deleted file mode 100644 index ef78cfb..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tags.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Tag number; Tag ID; Applicable types (comma-separated); Semantics -0;DateTimeString;TextString;Standard date/time string -1;UnixTime_t;Integer;Epoch-based date/time -2;PositiveBignum;ByteString;Positive bignum -3;NegativeBignum;ByteString;Negative bignum -4;Decimal;Array;Decimal fraction -5;Bigfloat;Array;Bigfloat -16;COSE_Encrypt0;Array;COSE Single Recipient Encrypted Data Object (RFC 8152) -17;COSE_Mac0;Array;COSE Mac w/o Recipients Object (RFC 8152) -18;COSE_Sign1;Array;COSE Single Signer Data Object (RFC 8162) -21;ExpectedBase64url;ByteString,Array,Map;Expected conversion to base64url encoding -22;ExpectedBase64;ByteString,Array,Map;Expected conversion to base64 encoding -23;ExpectedBase16;ByteString,Array,Map;Expected conversion to base16 encoding -24;EncodedCbor;ByteString;Encoded CBOR data item -32;Url;TextString;URI -33;Base64url;TextString;base64url -34;Base64;TextString;base64 -35;RegularExpression;TextString;Regular expression -36;MimeMessage;TextString;MIME message -96;COSE_Encrypt;Array;COSE Encrypted Data Object (RFC 8152) -97;COSE_Mac;Array;COSE MACed Data Object (RFC 8152) -98;COSE_Sign;Array;COSE Signed Data Object (RFC 8152) -55799;Signature;;Self-describe CBOR diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor-version.h b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor-version.h deleted file mode 100644 index 270c915..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor-version.h +++ /dev/null @@ -1,3 +0,0 @@ -#define TINYCBOR_VERSION_MAJOR 0 -#define TINYCBOR_VERSION_MINOR 5 -#define TINYCBOR_VERSION_PATCH 4 diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor.pro deleted file mode 100644 index 980dfd1..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/tinycbor.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = lib -CONFIG += static -CONFIG -= qt -DESTDIR = ../lib - -include(src.pri) diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/utf8_p.h b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/utf8_p.h deleted file mode 100644 index ca43835..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/src/utf8_p.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBOR_UTF8_H -#define CBOR_UTF8_H - -#include "compilersupport_p.h" - -#include - -static inline uint32_t get_utf8(const uint8_t **buffer, const uint8_t *end) -{ - int charsNeeded; - uint32_t uc, min_uc; - uint8_t b; - ptrdiff_t n = end - *buffer; - if (n == 0) - return ~0U; - - uc = *(*buffer)++; - if (uc < 0x80) { - /* single-byte UTF-8 */ - return uc; - } - - /* multi-byte UTF-8, decode it */ - if (unlikely(uc <= 0xC1)) - return ~0U; - if (uc < 0xE0) { - /* two-byte UTF-8 */ - charsNeeded = 2; - min_uc = 0x80; - uc &= 0x1f; - } else if (uc < 0xF0) { - /* three-byte UTF-8 */ - charsNeeded = 3; - min_uc = 0x800; - uc &= 0x0f; - } else if (uc < 0xF5) { - /* four-byte UTF-8 */ - charsNeeded = 4; - min_uc = 0x10000; - uc &= 0x07; - } else { - return ~0U; - } - - if (n < charsNeeded) - return ~0U; - - /* first continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - - if (charsNeeded > 2) { - /* second continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - - if (charsNeeded > 3) { - /* third continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - } - } - - /* overlong sequence? surrogate pair? out or range? */ - if (uc < min_uc || uc - 0xd800U < 2048U || uc > 0x10ffff) - return ~0U; - - return uc; -} - -#endif /* CBOR_UTF8_H */ diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/.gitignore b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/.gitignore deleted file mode 100644 index e65577d..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -Makefile -debug -moc_predefs.h -release -target_wrapper.* - -# The executables -cpp/cpp -cpp/cpp.exe -encoder/encoder -encoder/encoder.exe -parser/parser -parser/parser.exe -tojson/tojson -tojson/tojson.exe diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/c90.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/c90.pro deleted file mode 100644 index 59166b4..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/c90.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase parallel_test console -CONFIG -= qt app_bundle -gcc: QMAKE_CFLAGS += -std=c90 -pedantic-errors -Wall -Wextra -Werror -darwin: QMAKE_CFLAGS += -Wno-long-long - -SOURCES += tst_c90.c -INCLUDEPATH += ../../src diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/tst_c90.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/tst_c90.c deleted file mode 100644 index edb49ab..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/c90/tst_c90.c +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include "cbor.h" - -int main() -{ - return 0; -} diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/cpp.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/cpp.pro deleted file mode 100644 index 5e9e608..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/cpp.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase parallel_test c++11 -QT = core testlib - -SOURCES = tst_cpp.cpp -INCLUDEPATH += ../../src diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/tst_cpp.cpp b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/tst_cpp.cpp deleted file mode 100644 index dcf3d1f..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/cpp/tst_cpp.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include "../../src/cborencoder.c" -#include "../../src/cborerrorstrings.c" -#include "../../src/cborparser.c" -#include "../../src/cborparser_dup_string.c" -#include "../../src/cborvalidation.c" - -#include - -// This is a compilation-only test. -// All it does is verify that the four source files above -// compile as C++ without errors. -class tst_Cpp : public QObject -{ - Q_OBJECT -}; - -QTEST_MAIN(tst_Cpp) -#include "tst_cpp.moc" diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/encoder.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/encoder.pro deleted file mode 100644 index 62d9b7e..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/encoder.pro +++ /dev/null @@ -1,9 +0,0 @@ -SOURCES += tst_encoder.cpp - -CONFIG += testcase parallel_test c++11 -QT = core testlib - -INCLUDEPATH += ../../src -msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib -else: POST_TARGETDEPS += ../../lib/libtinycbor.a -LIBS += $$POST_TARGETDEPS diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp deleted file mode 100644 index 4a1b146..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp +++ /dev/null @@ -1,734 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include -#include "cbor.h" - -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) -#include -#endif - -Q_DECLARE_METATYPE(CborError) -namespace QTest { -template<> char *toString(const CborError &err) -{ - return qstrdup(cbor_error_string(err)); -} -} - -class tst_Encoder : public QObject -{ - Q_OBJECT -private slots: - void fixed_data(); - void fixed(); - void strings_data(); - void strings() { fixed(); } - void arraysAndMaps_data(); - void arraysAndMaps() { fixed(); } - void tags_data(); - void tags(); - void arrays_data() { tags_data(); } - void arrays(); - void maps_data() { tags_data(); } - void maps(); - - void shortBuffer_data() { tags_data(); } - void shortBuffer(); - void tooShortArrays_data() { tags_data(); } - void tooShortArrays(); - void tooShortMaps_data() { tags_data(); } - void tooShortMaps(); - void tooBigArrays_data() { tags_data(); } - void tooBigArrays(); - void tooBigMaps_data() { tags_data(); } - void tooBigMaps(); - void illegalSimpleType_data(); - void illegalSimpleType(); -}; - -#include "tst_encoder.moc" - -static float myNaNf() -{ - uint32_t v = 0x7fc00000; - float f; - memcpy(&f, &v, sizeof(f)); - Q_ASSERT(qIsNaN(f)); - return f; -} - -static float myInff() -{ - uint32_t v = 0x7f800000; - float f; - memcpy(&f, &v, sizeof(f)); - Q_ASSERT(qIsInf(f)); - return f; -} - -static float myNInff() -{ - uint32_t v = 0xff800000; - float f; - memcpy(&f, &v, sizeof(f)); - Q_ASSERT(qIsInf(f)); - return f; -} - -static double myNaN() -{ - uint64_t v = UINT64_C(0x7ff8000000000000); - double f; - memcpy(&f, &v, sizeof(f)); - Q_ASSERT(qIsNaN(f)); - return f; -} - -static double myInf() -{ - uint64_t v = UINT64_C(0x7ff0000000000000); - double f; - memcpy(&f, &v, sizeof(f)); - Q_ASSERT(qIsInf(f)); - return f; -} - -static double myNInf() -{ - uint64_t v = UINT64_C(0xfff0000000000000); - double f; - memcpy(&f, &v, sizeof(f)); - Q_ASSERT(qIsInf(f)); - return f; -} - -template QByteArray raw(const char (&data)[N]) -{ - return QByteArray::fromRawData(data, N - 1); -} - -struct NegativeInteger { quint64 abs; }; -Q_DECLARE_METATYPE(NegativeInteger) - -struct SimpleType { uint8_t type; }; -Q_DECLARE_METATYPE(SimpleType) - -struct Float16Standin { uint16_t val; }; -Q_DECLARE_METATYPE(Float16Standin) - -struct Tag { CborTag tag; QVariant tagged; }; -Q_DECLARE_METATYPE(Tag) - -template -QVariant make_list(const Args &... args) -{ - return QVariantList{args...}; -} - -typedef QVector> Map; -Q_DECLARE_METATYPE(Map) -QVariant make_map(const std::initializer_list> &list) -{ - return QVariant::fromValue(Map(list)); -} - -struct IndeterminateLengthArray : QVariantList { using QVariantList::QVariantList; }; -struct IndeterminateLengthMap : Map { using Map::Map; }; -Q_DECLARE_METATYPE(IndeterminateLengthArray) -Q_DECLARE_METATYPE(IndeterminateLengthMap) - -QVariant make_ilarray(const std::initializer_list &list) -{ - return QVariant::fromValue(IndeterminateLengthArray(list)); -} - -QVariant make_ilmap(const std::initializer_list> &list) -{ - return QVariant::fromValue(IndeterminateLengthMap(list)); -} - -static inline bool isOomError(CborError err) -{ - return err == CborErrorOutOfMemory; -} - -CborError encodeVariant(CborEncoder *encoder, const QVariant &v) -{ - int type = v.userType(); - switch (type) { - case QVariant::Int: - case QVariant::LongLong: - return cbor_encode_int(encoder, v.toLongLong()); - - case QVariant::UInt: - case QVariant::ULongLong: - return cbor_encode_uint(encoder, v.toULongLong()); - - case QVariant::Bool: - return cbor_encode_boolean(encoder, v.toBool()); - - case QVariant::Invalid: - return cbor_encode_undefined(encoder); - - case QMetaType::VoidStar: - return cbor_encode_null(encoder); - - case QVariant::Double: - return cbor_encode_double(encoder, v.toDouble()); - - case QMetaType::Float: - return cbor_encode_float(encoder, v.toFloat()); - - case QVariant::String: { - QByteArray string = v.toString().toUtf8(); - return cbor_encode_text_string(encoder, string.constData(), string.length()); - } - - case QVariant::ByteArray: { - QByteArray string = v.toByteArray(); - return cbor_encode_byte_string(encoder, reinterpret_cast(string.constData()), string.length()); - } - - default: - if (type == qMetaTypeId()) - return cbor_encode_negative_int(encoder, v.value().abs); - if (type == qMetaTypeId()) - return cbor_encode_simple_value(encoder, v.value().type); -#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0) - if (type == qMetaTypeId()) - return cbor_encode_half_float(encoder, v.constData()); -#else - if (type == qMetaTypeId()) - return cbor_encode_half_float(encoder, v.constData()); -#endif - if (type == qMetaTypeId()) { - CborError err = cbor_encode_tag(encoder, v.value().tag); - if (err && !isOomError(err)) - return err; - return static_cast(err | encodeVariant(encoder, v.value().tagged)); - } - if (type == QVariant::List || type == qMetaTypeId()) { - CborEncoder sub; - QVariantList list = v.toList(); - size_t len = list.length(); - if (type == qMetaTypeId()) { - len = CborIndefiniteLength; - list = v.value(); - } - CborError err = cbor_encoder_create_array(encoder, &sub, len); - if (err && !isOomError(err)) - return err; - foreach (const QVariant &v2, list) { - err = static_cast(err | encodeVariant(&sub, v2)); - if (err && !isOomError(err)) - return err; - } - return cbor_encoder_close_container_checked(encoder, &sub); - } - if (type == qMetaTypeId() || type == qMetaTypeId()) { - CborEncoder sub; - Map map = v.value(); - size_t len = map.length(); - if (type == qMetaTypeId()) { - len = CborIndefiniteLength; - map = v.value(); - } - CborError err = cbor_encoder_create_map(encoder, &sub, len); - if (err && !isOomError(err)) - return err; - for (auto pair : map) { - err = static_cast(err | encodeVariant(&sub, pair.first)); - if (err && !isOomError(err)) - return err; - err = static_cast(err | encodeVariant(&sub, pair.second)); - if (err && !isOomError(err)) - return err; - } - return cbor_encoder_close_container_checked(encoder, &sub); - } - } - return CborErrorUnknownType; -} - -void compare(const QVariant &input, const QByteArray &output) -{ - QByteArray buffer(output.length(), Qt::Uninitialized); - uint8_t *bufptr = reinterpret_cast(buffer.data()); - CborEncoder encoder; - cbor_encoder_init(&encoder, bufptr, buffer.length(), 0); - - QCOMPARE(encodeVariant(&encoder, input), CborNoError); - QCOMPARE(encoder.remaining, size_t(1)); - QCOMPARE(cbor_encoder_get_extra_bytes_needed(&encoder), size_t(0)); - - buffer.resize(int(cbor_encoder_get_buffer_size(&encoder, bufptr))); - QCOMPARE(buffer, output); -} - -void addColumns() -{ - QTest::addColumn("output"); - QTest::addColumn("input"); -} - -void addFixedData() -{ - // unsigned integers - QTest::newRow("0U") << raw("\x00") << QVariant(0U); - QTest::newRow("1U") << raw("\x01") << QVariant(1U); - QTest::newRow("10U") << raw("\x0a") << QVariant(10U); - QTest::newRow("23U") << raw("\x17") << QVariant(23U); - QTest::newRow("24U") << raw("\x18\x18") << QVariant(24U); - QTest::newRow("255U") << raw("\x18\xff") << QVariant(255U); - QTest::newRow("256U") << raw("\x19\x01\x00") << QVariant(256U); - QTest::newRow("65535U") << raw("\x19\xff\xff") << QVariant(65535U); - QTest::newRow("65536U") << raw("\x1a\0\1\x00\x00") << QVariant(65536U); - QTest::newRow("4294967295U") << raw("\x1a\xff\xff\xff\xff") << QVariant(4294967295U); - QTest::newRow("4294967296U") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_UINT64_C(4294967296)); - QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << QVariant(std::numeric_limits::max()); - - // signed integers containing non-negative numbers - QTest::newRow("0") << raw("\x00") << QVariant(0); - QTest::newRow("1") << raw("\x01") << QVariant(1); - QTest::newRow("10") << raw("\x0a") << QVariant(10); - QTest::newRow("23") << raw("\x17") << QVariant(23); - QTest::newRow("24") << raw("\x18\x18") << QVariant(24); - QTest::newRow("255") << raw("\x18\xff") << QVariant(255); - QTest::newRow("256") << raw("\x19\x01\x00") << QVariant(256); - QTest::newRow("65535") << raw("\x19\xff\xff") << QVariant(65535); - QTest::newRow("65536") << raw("\x1a\0\1\x00\x00") << QVariant(65536); - QTest::newRow("4294967295") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295)); - QTest::newRow("4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296)); - - // signed integers containing negative numbers - QTest::newRow("-1") << raw("\x20") << QVariant(-1); - QTest::newRow("-2") << raw("\x21") << QVariant(-2); - QTest::newRow("-24") << raw("\x37") << QVariant(-24); - QTest::newRow("-25") << raw("\x38\x18") << QVariant(-25); - QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(-256); - QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(-257); - QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(-65536); - QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(-65537); - QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296)); - QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297)); - - // negative integers - auto neg = [](quint64 v) { return QVariant::fromValue({v}); }; - QTest::newRow("negative1") << raw("\x20") << neg(1); - QTest::newRow("negative2") << raw("\x21") << neg(2); - QTest::newRow("negative24") << raw("\x37") << neg(24); - QTest::newRow("negative25") << raw("\x38\x18") << neg(25); - QTest::newRow("negativeUINT8_MAX") << raw("\x38\xff") << neg(256); - QTest::newRow("negativeUINT8_MAX-1") << raw("\x39\x01\x00") << neg(257); - QTest::newRow("negativeUINT16_MAX") << raw("\x39\xff\xff") << neg(65536); - QTest::newRow("negativeUINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << neg(65537); - QTest::newRow("negativeUINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << neg(Q_UINT64_C(4294967296)); - QTest::newRow("negativeUINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << neg(Q_UINT64_C(4294967297)); - QTest::newRow("negativeUINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe") - << neg(std::numeric_limits::max()); - QTest::newRow("negativeUINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") << neg(0); - - QTest::newRow("simple0") << raw("\xe0") << QVariant::fromValue(SimpleType{0}); - QTest::newRow("simple19") << raw("\xf3") << QVariant::fromValue(SimpleType{19}); - QTest::newRow("false") << raw("\xf4") << QVariant(false); - QTest::newRow("true") << raw("\xf5") << QVariant(true); - QTest::newRow("null") << raw("\xf6") << QVariant::fromValue(nullptr); - QTest::newRow("undefined") << raw("\xf7") << QVariant(); - QTest::newRow("simple32") << raw("\xf8\x20") << QVariant::fromValue(SimpleType{32}); - QTest::newRow("simple255") << raw("\xf8\xff") << QVariant::fromValue(SimpleType{255}); - - // floating point -#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0) - QTest::newRow("0.f16") << raw("\xf9\0\0") << QVariant::fromValue(Float16Standin{0x0000}); -#else - QTest::newRow("0.f16") << raw("\xf9\0\0") << QVariant::fromValue(qfloat16(0)); - QTest::newRow("-1.f16") << raw("\xf9\xbc\0") << QVariant::fromValue(qfloat16(-1)); - QTest::newRow("1.5f16") << raw("\xf9\x3e\0") << QVariant::fromValue(qfloat16(1.5)); - QTest::newRow("nan_f16") << raw("\xf9\x7e\0") << QVariant::fromValue(myNaNf()); - QTest::newRow("-inf_f16") << raw("\xf9\xfc\0") << QVariant::fromValue(myNInff()); - QTest::newRow("+inf_f16") << raw("\xf9\x7c\0") << QVariant::fromValue(myInff()); -#endif - - QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << QVariant::fromValue(0.f); - QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << QVariant(0.); - QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << QVariant::fromValue(-1.f); - QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << QVariant(-1.); - QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << QVariant::fromValue(16777215.f); - QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << QVariant::fromValue(16777215.); - QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << QVariant(-16777215.f); - QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << QVariant::fromValue(-16777215.); - - QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << QVariant::fromValue(myNaNf()); - QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << QVariant(myNaN()); - QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << QVariant::fromValue(myNInff()); - QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << QVariant(myNInf()); - QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << QVariant::fromValue(myInff()); - QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << QVariant(myInf()); -} - -void addStringsData() -{ - // byte strings - QTest::newRow("emptybytestring") << raw("\x40") << QVariant(QByteArray("")); - QTest::newRow("bytestring1") << raw("\x41 ") << QVariant(QByteArray(" ")); - QTest::newRow("bytestring1-nul") << raw("\x41\0") << QVariant(QByteArray("", 1)); - QTest::newRow("bytestring5") << raw("\x45Hello") << QVariant(QByteArray("Hello")); - QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") - << QVariant(QByteArray("123456789012345678901234")); - QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3') - << QVariant(QByteArray(256, '3')); - - // text strings - QTest::newRow("emptytextstring") << raw("\x60") << QVariant(""); - QTest::newRow("textstring1") << raw("\x61 ") << QVariant(" "); - QTest::newRow("textstring1-nul") << raw("\x61\0") << QVariant(QString::fromLatin1("", 1)); - QTest::newRow("textstring5") << raw("\x65Hello") << QVariant("Hello"); - QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") - << QVariant("123456789012345678901234"); - QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') - << QVariant(QString(256, '3')); -} - -void addArraysAndMaps() -{ - QTest::newRow("emptyarray") << raw("\x80") << make_list(); - QTest::newRow("emptymap") << raw("\xa0") << make_map({}); - - QTest::newRow("array-0") << raw("\x81\0") << make_list(0); - QTest::newRow("array-{0-0}") << raw("\x82\0\0") << make_list(0, 0); - QTest::newRow("array-Hello") << raw("\x81\x65Hello") << make_list("Hello"); - QTest::newRow("array-array-0") << raw("\x81\x81\0") << make_list(make_list(0)); - QTest::newRow("array-array-{0-0}") << raw("\x81\x82\0\0") << make_list(make_list(0, 0)); - QTest::newRow("array-array-0-0") << raw("\x82\x81\0\0") << make_list(make_list(0),0); - QTest::newRow("array-array-Hello") << raw("\x81\x81\x65Hello") << make_list(make_list("Hello")); - - QTest::newRow("map-0:0") << raw("\xa1\0\0") << make_map({{0,0}}); - QTest::newRow("map-0:0-1:1") << raw("\xa2\0\0\1\1") << make_map({{0,0}, {1,1}}); - QTest::newRow("map-0:{map-0:0-1:1}") << raw("\xa1\0\xa2\0\0\1\1") << make_map({{0, make_map({{0,0}, {1,1}})}}); - - QTest::newRow("array-map1") << raw("\x81\xa1\0\0") << make_list(make_map({{0,0}})); - QTest::newRow("array-map2") << raw("\x82\xa1\0\0\xa1\1\1") << make_list(make_map({{0,0}}), make_map({{1,1}})); - - QTest::newRow("map-array1") << raw("\xa1\x62oc\x81\0") << make_map({{"oc", make_list(0)}}); - QTest::newRow("map-array2") << raw("\xa1\x62oc\x84\0\1\2\3") << make_map({{"oc", make_list(0, 1, 2, 3)}}); - QTest::newRow("map-array3") << raw("\xa2\x62oc\x82\0\1\2\3") << make_map({{"oc", make_list(0, 1)}, {2, 3}}); - - // indeterminate length - QTest::newRow("_emptyarray") << raw("\x9f\xff") << QVariant::fromValue(IndeterminateLengthArray{}); - QTest::newRow("_emptymap") << raw("\xbf\xff") << make_ilmap({}); - - QTest::newRow("_array-0") << raw("\x9f\0\xff") << make_ilarray({0}); - QTest::newRow("_array-{0-0}") << raw("\x9f\0\0\xff") << make_ilarray({0, 0}); - QTest::newRow("_array-Hello") << raw("\x9f\x65Hello\xff") << make_ilarray({"Hello"}); - QTest::newRow("_array-array-0") << raw("\x9f\x81\0\xff") << make_ilarray({make_list(0)}); - QTest::newRow("_array-_array-0") << raw("\x9f\x9f\0\xff\xff") << make_ilarray({make_ilarray({0})}); - QTest::newRow("_array-_array-{0-0}") << raw("\x9f\x9f\0\0\xff\xff") << make_ilarray({make_ilarray({0, 0})}); - QTest::newRow("_array-_array-0-0") << raw("\x9f\x9f\0\xff\0\xff") << make_ilarray({make_ilarray({0}),0}); - QTest::newRow("_array-_array-Hello") << raw("\x9f\x9f\x65Hello\xff\xff") << make_ilarray({make_ilarray({"Hello"})}); - - QTest::newRow("_map-0:0") << raw("\xbf\0\0\xff") << make_ilmap({{0,0}}); - QTest::newRow("_map-0:0-1:1") << raw("\xbf\0\0\1\1\xff") << make_ilmap({{0,0}, {1,1}}); - QTest::newRow("_map-0:{map-0:0-1:1}") << raw("\xbf\0\xa2\0\0\1\1\xff") << make_ilmap({{0, make_map({{0,0}, {1,1}})}}); - QTest::newRow("_map-0:{_map-0:0-1:1}") << raw("\xbf\0\xbf\0\0\1\1\xff\xff") << make_ilmap({{0, make_ilmap({{0,0}, {1,1}})}}); - - QTest::newRow("_array-map1") << raw("\x9f\xa1\0\0\xff") << make_ilarray({make_map({{0,0}})}); - QTest::newRow("_array-_map1") << raw("\x9f\xbf\0\0\xff\xff") << make_ilarray({make_ilmap({{0,0}})}); - QTest::newRow("_array-map2") << raw("\x9f\xa1\0\0\xa1\1\1\xff") << make_ilarray({make_map({{0,0}}), make_map({{1,1}})}); - QTest::newRow("_array-_map2") << raw("\x9f\xbf\0\0\xff\xbf\1\1\xff\xff") << make_ilarray({make_ilmap({{0,0}}), make_ilmap({{1,1}})}); - - QTest::newRow("_map-array1") << raw("\xbf\x62oc\x81\0\xff") << make_ilmap({{"oc", make_list(0)}}); - QTest::newRow("_map-_array1") << raw("\xbf\x62oc\x9f\0\xff\xff") << make_ilmap({{"oc", make_ilarray({0})}}); - QTest::newRow("_map-array2") << raw("\xbf\x62oc\x84\0\1\2\3\xff") << make_ilmap({{"oc", make_list(0, 1, 2, 3)}}); - QTest::newRow("_map-_array2") << raw("\xbf\x62oc\x9f\0\1\2\3\xff\xff") << make_ilmap({{"oc", make_ilarray({0, 1, 2, 3})}}); - QTest::newRow("_map-array3") << raw("\xbf\x62oc\x82\0\1\2\3\xff") << make_ilmap({{"oc", make_list(0, 1)}, {2, 3}}); - QTest::newRow("_map-_array3") << raw("\xbf\x62oc\x9f\0\1\xff\2\3\xff") << make_ilmap({{"oc", make_ilarray({0, 1})}, {2, 3}}); - - // tagged - QTest::newRow("array-1(0)") << raw("\x81\xc1\0") << make_list(QVariant::fromValue(Tag{1, 0})); - QTest::newRow("array-1(map)") << raw("\x81\xc1\xa0") << make_list(QVariant::fromValue(Tag{1, make_map({})})); - QTest::newRow("map-1(2):3(4)") << raw("\xa1\xc1\2\xc3\4") << make_map({{QVariant::fromValue(Tag{1, 2}), QVariant::fromValue(Tag{3, 4})}}); -} - -void tst_Encoder::fixed_data() -{ - addColumns(); - addFixedData(); -} - -void tst_Encoder::fixed() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - compare(input, output); -} - -void tst_Encoder::strings_data() -{ - addColumns(); - addStringsData(); -} - -void tst_Encoder::arraysAndMaps_data() -{ - addColumns(); - addArraysAndMaps(); -} - -void tst_Encoder::tags_data() -{ - addColumns(); - addFixedData(); - addStringsData(); - addArraysAndMaps(); -} - -void tst_Encoder::tags() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - - compare(QVariant::fromValue(Tag{1, input}), "\xc1" + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{24, input}), "\xd8\x18" + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{255, input}), "\xd8\xff" + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{256, input}), raw("\xd9\1\0") + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{CborSignatureTag, input}), raw("\xd9\xd9\xf7") + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{65535, input}), raw("\xd9\xff\xff") + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{65536, input}), raw("\xda\0\1\0\0") + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{UINT32_MAX, input}), raw("\xda\xff\xff\xff\xff") + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{UINT32_MAX + Q_UINT64_C(1), input}), raw("\xdb\0\0\0\1\0\0\0\0") + output); - if (QTest::currentTestFailed()) return; - - compare(QVariant::fromValue(Tag{UINT64_MAX, input}), raw("\xdb\xff\xff\xff\xff\xff\xff\xff\xff") + output); - if (QTest::currentTestFailed()) return; - - // nested tags - compare(QVariant::fromValue(Tag{1, QVariant::fromValue(Tag{1, input})}), "\xc1\xc1" + output); -} - -void tst_Encoder::arrays() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - - compare(make_list(input), "\x81" + output); - if (QTest::currentTestFailed()) return; - - compare(make_list(input, input), "\x82" + output + output); - if (QTest::currentTestFailed()) return; - - { - QVariantList list{input}; - QByteArray longoutput = output; - - // make a list with 32 elements (1 << 5) - for (int i = 0; i < 5; ++i) { - list += list; - longoutput += longoutput; - } - compare(list, "\x98\x20" + longoutput); - if (QTest::currentTestFailed()) return; - - // now 256 elements (32 << 3) - for (int i = 0; i < 3; ++i) { - list += list; - longoutput += longoutput; - } - compare(list, raw("\x99\1\0") + longoutput); - if (QTest::currentTestFailed()) return; - } - - // nested lists - compare(make_list(make_list(input)), "\x81\x81" + output); - if (QTest::currentTestFailed()) return; - - compare(make_list(make_list(input, input)), "\x81\x82" + output + output); - if (QTest::currentTestFailed()) return; - - compare(make_list(make_list(input), input), "\x82\x81" + output + output); - if (QTest::currentTestFailed()) return; - - compare(make_list(make_list(input), make_list(input)), "\x82\x81" + output + "\x81" + output); -} - -void tst_Encoder::maps() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - - compare(make_map({{1, input}}), "\xa1\1" + output); - if (QTest::currentTestFailed()) return; - - compare(make_map({{1, input}, {input, 24}}), "\xa2\1" + output + output + "\x18\x18"); - if (QTest::currentTestFailed()) return; - - compare(make_map({{input, input}}), "\xa1" + output + output); - if (QTest::currentTestFailed()) return; - - { - Map map{{1, input}}; - QByteArray longoutput = "\1" + output; - - // make a map with 32 elements (1 << 5) - for (int i = 0; i < 5; ++i) { - map += map; - longoutput += longoutput; - } - compare(QVariant::fromValue(map), "\xb8\x20" + longoutput); - if (QTest::currentTestFailed()) return; - - // now 256 elements (32 << 3) - for (int i = 0; i < 3; ++i) { - map += map; - longoutput += longoutput; - } - compare(QVariant::fromValue(map), raw("\xb9\1\0") + longoutput); - if (QTest::currentTestFailed()) return; - } - - // nested maps - compare(make_map({{1, make_map({{2, input}})}}), "\xa1\1\xa1\2" + output); - if (QTest::currentTestFailed()) return; - - compare(make_map({{1, make_map({{2, input}, {input, false}})}}), "\xa1\1\xa2\2" + output + output + "\xf4"); - if (QTest::currentTestFailed()) return; - - compare(make_map({{1, make_map({{2, input}})}, {input, false}}), "\xa2\1\xa1\2" + output + output + "\xf4"); - if (QTest::currentTestFailed()) return; -} - -void tst_Encoder::shortBuffer() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - QByteArray buffer(output.length(), Qt::Uninitialized); - - for (int len = 0; len < output.length(); ++len) { - CborEncoder encoder; - cbor_encoder_init(&encoder, reinterpret_cast(buffer.data()), len, 0); - QCOMPARE(encodeVariant(&encoder, input), CborErrorOutOfMemory); - QVERIFY(cbor_encoder_get_extra_bytes_needed(&encoder) != 0); - QCOMPARE(len + cbor_encoder_get_extra_bytes_needed(&encoder), size_t(output.length())); - } -} - -void tst_Encoder::tooShortArrays() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - QByteArray buffer(output.length() + 1, Qt::Uninitialized); - - CborEncoder encoder, container; - cbor_encoder_init(&encoder, reinterpret_cast(buffer.data()), buffer.length(), 0); - QCOMPARE(cbor_encoder_create_array(&encoder, &container, 2), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(container.remaining, size_t(2)); - QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooFewItems); -} - -void tst_Encoder::tooShortMaps() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - QByteArray buffer(output.length() + 1, Qt::Uninitialized); - - CborEncoder encoder, container; - cbor_encoder_init(&encoder, reinterpret_cast(buffer.data()), buffer.length(), 0); - QCOMPARE(cbor_encoder_create_map(&encoder, &container, 2), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(container.remaining, size_t(4)); - QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooFewItems); -} - -void tst_Encoder::tooBigArrays() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - QByteArray buffer(output.length() * 2 + 1, Qt::Uninitialized); - - CborEncoder encoder, container; - cbor_encoder_init(&encoder, reinterpret_cast(buffer.data()), buffer.length(), 0); - QCOMPARE(cbor_encoder_create_array(&encoder, &container, 1), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(container.remaining, size_t(0)); - QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooManyItems); -} - -void tst_Encoder::tooBigMaps() -{ - QFETCH(QVariant, input); - QFETCH(QByteArray, output); - QByteArray buffer(output.length() * 3 + 1, Qt::Uninitialized); - - CborEncoder encoder, container; - cbor_encoder_init(&encoder, reinterpret_cast(buffer.data()), buffer.length(), 0); - QCOMPARE(cbor_encoder_create_map(&encoder, &container, 1), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(encodeVariant(&container, input), CborNoError); - QCOMPARE(container.remaining, size_t(0)); - QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooManyItems); -} - -void tst_Encoder::illegalSimpleType_data() -{ - QTest::addColumn("type"); - QTest::newRow("half-float") << 25; - QTest::newRow("float") << 26; - QTest::newRow("double") << 27; - QTest::newRow("28") << 28; - QTest::newRow("29") << 29; - QTest::newRow("30") << 30; - QTest::newRow("31") << 31; -} - -void tst_Encoder::illegalSimpleType() -{ - QFETCH(int, type); - - quint8 buf[2]; - CborEncoder encoder; - cbor_encoder_init(&encoder, buf, sizeof(buf), 0); - QCOMPARE(cbor_encode_simple_value(&encoder, type), CborErrorIllegalSimpleType); -} - -QTEST_MAIN(tst_Encoder) diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/parser.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/parser.pro deleted file mode 100644 index a61291a..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/parser.pro +++ /dev/null @@ -1,10 +0,0 @@ -SOURCES += tst_parser.cpp ../../src/cborparser.c - -CONFIG += testcase parallel_test c++11 -QT = core testlib -DEFINES += CBOR_PARSER_MAX_RECURSIONS=16 - -INCLUDEPATH += ../../src -msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib -else: POST_TARGETDEPS += ../../lib/libtinycbor.a -LIBS += $$POST_TARGETDEPS diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/tst_parser.cpp b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/tst_parser.cpp deleted file mode 100644 index 28967cc..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/parser/tst_parser.cpp +++ /dev/null @@ -1,2204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _XOPEN_SOURCE 700 -#define _DARWIN_C_SOURCE 1 /* need MAP_ANON */ -#include -#include "cbor.h" -#include -#include - -#if defined(Q_OS_UNIX) -# include -# include -#elif defined(Q_OS_WIN) -# define WIN32_LEAN_AND_MEAN 1 -# define NOMINMAX 1 -# include -#endif - -Q_DECLARE_METATYPE(CborError) - -namespace QTest { -template<> char *toString(const CborError &err) -{ - return qstrdup(cbor_error_string(err)); -} -} - -class tst_Parser : public QObject -{ - Q_OBJECT -private slots: - void initParserEmpty(); - - // parsing API - void integers_data(); - void integers(); - void fixed_data(); - void fixed(); - void strings_data(); - void strings() { fixed(); } - void tags_data(); - void tags() { fixed(); } - void tagTags_data() { tags_data(); } - void tagTags(); - void emptyContainers_data(); - void emptyContainers(); - void arrays_data(); - void arrays(); - void undefLengthArrays_data() { arrays_data(); } - void undefLengthArrays(); - void nestedArrays_data() { arrays_data(); } - void nestedArrays(); - void maps_data(); - void maps(); - void undefLengthMaps_data() { maps_data(); } - void undefLengthMaps(); - void nestedMaps_data() { maps_data(); } - void nestedMaps(); - void mapMixed_data(); - void mapMixed() { arrays(); } - void mapsAndArrays_data() { arrays_data(); } - void mapsAndArrays(); - - // chunked string API - void chunkedString_data(); - void chunkedString(); - void chunkedStringInUndefArray_data() { chunkedString_data(); } - void chunkedStringInUndefArray(); - - // convenience API - void stringLength_data(); - void stringLength(); - void stringCompare_data(); - void stringCompare(); - void mapFind_data(); - void mapFind(); - - // validation & errors - void checkedIntegers_data(); - void checkedIntegers(); - void validation_data(); - void validation(); - void strictValidation_data(); - void strictValidation(); - void resumeParsing_data(); - void resumeParsing(); - void endPointer_data(); - void endPointer(); - void recursionLimit_data(); - void recursionLimit(); -}; - -struct ParserWrapper -{ - void *realdata = nullptr; - uint8_t *data; - size_t len; - CborParser parser; - CborValue first; - - ~ParserWrapper() { freeMemory(); } - - CborError init(const QByteArray &ba, uint32_t flags = 0) - { - return init(ba.constData(), ba.size(), flags); - } - CborError init(const char *ptr, int n, uint32_t flags = 0) - { - freeMemory(); - data = allocateMemory(n); - memcpy(data, ptr, len); - return cbor_parser_init(data, len, flags, &parser, &first); - } - uint8_t *begin() { return data; } - uint8_t *end() { return data + len; } - - uint8_t *allocateMemory(size_t); - void freeMemory(); - - static const size_t PageSize = 4096; - static inline size_t mmapAllocation(size_t n) - { - // round up and add one page - return (n + 2*PageSize) & ~(PageSize - 1); - } - static bool shouldUseMmap(); -}; - -bool ParserWrapper::shouldUseMmap() -{ - static int v = qEnvironmentVariableIntValue("PARSER_NO_MMAP"); - return !v; -} - -uint8_t *ParserWrapper::allocateMemory(size_t n) -{ - len = n; - if (shouldUseMmap()) { - size_t alloc = mmapAllocation(n); -#if defined(Q_OS_UNIX) - realdata = mmap(nullptr, alloc, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - Q_ASSERT_X(realdata != MAP_FAILED, "allocateMemory", "mmap failed!"); - - // mark last page inaccessible - uint8_t *ptr = static_cast(realdata); - ptr += alloc - PageSize; - mprotect(ptr, PageSize, PROT_NONE); - - ptr -= n; - return ptr; -#elif defined(Q_OS_WIN) - DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE; - DWORD flProtect = PAGE_READWRITE; - realdata = VirtualAlloc(nullptr, alloc, flAllocationType, flProtect); - Q_ASSERT_X(realdata, "allocateMemory", "VirtualAlloc failed!"); - - // mark last page inaccessible - uint8_t *ptr = static_cast(realdata); - ptr += alloc - PageSize; - VirtualProtect(ptr, PageSize, PAGE_NOACCESS, nullptr); - - ptr -= n; - return ptr; -#endif - } - realdata = malloc(n); - return static_cast(realdata); -} - -void ParserWrapper::freeMemory() -{ - if (shouldUseMmap()) { - if (realdata) { -#if defined(Q_OS_UNIX) - size_t alloc = mmapAllocation(len); - munmap(realdata, alloc); -#elif defined(Q_OS_WIN) - VirtualFree(realdata, 0, MEM_RELEASE); -#endif - } - return; - } - - free(realdata); -} - -static CborError qstring_printf(void *out, const char *fmt, ...) -{ - auto str = static_cast(out); - va_list va; - va_start(va, fmt); - *str += QString::vasprintf(fmt, va); - va_end(va); - return CborNoError; -}; - -CborError parseOne(CborValue *it, QString *parsed) -{ - int flags = CborPrettyShowStringFragments | CborPrettyIndicateIndeterminateLength | - CborPrettyIndicateOverlongNumbers; - - parsed->clear(); - return cbor_value_to_pretty_stream(qstring_printf, parsed, it, flags); -} - -template QByteArray raw(const char (&data)[N]) -{ - return QByteArray::fromRawData(data, N - 1); -} - -void tst_Parser::initParserEmpty() -{ - CborParser parser; - CborValue first; - CborError err = cbor_parser_init((const quint8 *)"", 0, 0, &parser, &first); - QCOMPARE(err, CborErrorUnexpectedEOF); -} - -void addColumns() -{ - QTest::addColumn("data"); - QTest::addColumn("expected"); - QTest::addColumn("n"); // some aux integer, not added in all columns -} - -bool compareFailed = true; -void compareOne_real(const QByteArray &data, const QString &expected, int line, int n = -1) -{ - compareFailed = true; - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\""); - - if (cbor_value_get_type(&w.first) == CborArrayType) { - size_t len; - if (n >= 0) { - QVERIFY(cbor_value_is_length_known(&w.first)); - QCOMPARE(cbor_value_get_array_length(&w.first, &len), CborNoError); - QCOMPARE(len, size_t(len)); - } else { - QVERIFY(!cbor_value_is_length_known(&w.first)); - QCOMPARE(cbor_value_get_array_length(&w.first, &len), CborErrorUnknownLength); - } - } else if (cbor_value_get_type(&w.first) == CborMapType) { - size_t len; - if (n >= 0) { - QVERIFY(cbor_value_is_length_known(&w.first)); - QCOMPARE(cbor_value_get_map_length(&w.first, &len), CborNoError); - QCOMPARE(len, size_t(len)); - } else { - QVERIFY(!cbor_value_is_length_known(&w.first)); - QCOMPARE(cbor_value_get_map_length(&w.first, &len), CborErrorUnknownLength); - } - } else if (cbor_value_is_text_string(&w.first) || cbor_value_is_byte_string(&w.first)) { - size_t len; - QCOMPARE(cbor_value_calculate_string_length(&w.first, &len), CborNoError); - if (cbor_value_is_length_known(&w.first)) { - size_t len2; - QCOMPARE(cbor_value_get_string_length(&w.first, &len2), CborNoError); - QCOMPARE(len2, len); - } else { - QCOMPARE(cbor_value_get_string_length(&w.first, &len), CborErrorUnknownLength); - } - } - - CborError err2 = cbor_value_validate_basic(&w.first); - - QString decoded; - err = parseOne(&w.first, &decoded); - QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + - "\"; decoded stream:\n" + decoded.toLatin1()); - QCOMPARE(decoded, expected); - - // check that the errors are the same - QCOMPARE(err2, err); - - // check that we consumed everything - QCOMPARE((void*)cbor_value_get_next_byte(&w.first), (void*)w.end()); - - compareFailed = false; -} -#define compareOne(data, expected) compareOne_real(data, expected, __LINE__) -#define compareOneSize(n, data, expected) compareOne_real(data, expected, __LINE__, n) - -void addFixedData() -{ - // unsigned integers - QTest::newRow("0") << raw("\x00") << "0"; - QTest::newRow("1") << raw("\x01") << "1"; - QTest::newRow("10") << raw("\x0a") << "10"; - QTest::newRow("23") << raw("\x17") << "23"; - QTest::newRow("24") << raw("\x18\x18") << "24"; - QTest::newRow("UINT8_MAX") << raw("\x18\xff") << "255"; - QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << "256"; - QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << "65535"; - QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << "65536"; - QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << "4294967295"; - QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << "4294967296"; - QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << QString::number(std::numeric_limits::max()); - - // negative integers - QTest::newRow("-1") << raw("\x20") << "-1"; - QTest::newRow("-2") << raw("\x21") << "-2"; - QTest::newRow("-24") << raw("\x37") << "-24"; - QTest::newRow("-25") << raw("\x38\x18") << "-25"; - QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << "-256"; - QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << "-257"; - QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << "-65536"; - QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << "-65537"; - QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << "-4294967296"; - QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << "-4294967297"; - QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe") - << QString::number(std::numeric_limits::min() + 1); - QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff") - << QString::number(std::numeric_limits::min()); - QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809"; - QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe") - << '-' + QString::number(std::numeric_limits::max()); - QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << "-18446744073709551616"; - - // overlongs - QTest::newRow("0*1") << raw("\x18\x00") << "0_0"; - QTest::newRow("0*2") << raw("\x19\x00\x00") << "0_1"; - QTest::newRow("0*4") << raw("\x1a\0\0\0\0") << "0_2"; - QTest::newRow("0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << "0_3"; - QTest::newRow("-1*1") << raw("\x38\x00") << "-1_0"; - QTest::newRow("-1*2") << raw("\x39\x00\x00") << "-1_1"; - QTest::newRow("-1*4") << raw("\x3a\0\0\0\0") << "-1_2"; - QTest::newRow("-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << "-1_3"; - - QTest::newRow("simple0") << raw("\xe0") << "simple(0)"; - QTest::newRow("simple19") << raw("\xf3") << "simple(19)"; - QTest::newRow("false") << raw("\xf4") << "false"; - QTest::newRow("true") << raw("\xf5") << "true"; - QTest::newRow("null") << raw("\xf6") << "null"; - QTest::newRow("undefined") << raw("\xf7") << "undefined"; - QTest::newRow("simple32") << raw("\xf8\x20") << "simple(32)"; - QTest::newRow("simple255") << raw("\xf8\xff") << "simple(255)"; - - // floating point - - QTest::newRow("0.f16") << raw("\xf9\0\0") << "0.f16"; - QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "0.f"; - QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << "0."; - QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "-1.f16"; - QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "-1.f"; - QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "-1."; - QTest::newRow("65504.f16") << raw("\xf9\x7b\xff") << "65504.f16"; - QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f"; - QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "16777215."; - QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "-16777215.f"; - QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "-16777215."; - - QTest::newRow("0.5f16") << raw("\xf9\x38\0") << "0.5f16"; - QTest::newRow("0.5f") << raw("\xfa\x3f\0\0\0") << "0.5f"; - QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << "0.5"; - QTest::newRow("2.f16^11-1") << raw("\xf9\x67\xff") << "2047.f16"; - QTest::newRow("2.f^24-1") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f"; - QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "9007199254740991."; - QTest::newRow("2.f^64-epsilon") << raw("\xfa\x5f\x7f\xff\xff") << "18446742974197923840.f"; - QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "18446744073709549568."; - QTest::newRow("2.f^64") << raw("\xfa\x5f\x80\0\0") << "1.8446744073709552e+19f"; - QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << "1.8446744073709552e+19"; - - QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "nan"; - QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "nan"; - QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "nan"; - QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "-inf"; - QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "-inf"; - QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "-inf"; - QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "inf"; - QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "inf"; - QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "inf"; - -} - -static void addIntegers() -{ - QTest::addColumn("data"); - QTest::addColumn("expectedRaw"); - QTest::addColumn("expectedValue"); - QTest::addColumn("isNegative"); - QTest::addColumn("inInt64Range"); - - // unsigned integers - QTest::newRow("0") << raw("\x00") << Q_UINT64_C(0) << Q_INT64_C(0) << false << true; - QTest::newRow("1") << raw("\x01") << Q_UINT64_C(1) << Q_INT64_C(1) << false << true; - QTest::newRow("10") << raw("\x0a") << Q_UINT64_C(10) << Q_INT64_C(10) << false << true; - QTest::newRow("23") << raw("\x17") << Q_UINT64_C(23) << Q_INT64_C(23) << false << true; - QTest::newRow("24") << raw("\x18\x18") << Q_UINT64_C(24) << Q_INT64_C(24) << false << true; - QTest::newRow("UINT8_MAX") << raw("\x18\xff") << Q_UINT64_C(255) << Q_INT64_C(255) << false << true; - QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(256) << false << true; - QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(65535) << false << true; - QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(65536) << false << true; - QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(4294967295) << false << true; - QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(4294967296) << false << true; - QTest::newRow("INT64_MAX") << raw("\x1b" "\x7f\xff\xff\xff" "\xff\xff\xff\xff") - << quint64(std::numeric_limits::max()) - << std::numeric_limits::max() << false << true; - QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << std::numeric_limits::max() << qint64(-123456) << false << false; - - // negative integers - QTest::newRow("-1") << raw("\x20") << Q_UINT64_C(0) << Q_INT64_C(-1) << true << true; - QTest::newRow("-2") << raw("\x21") << Q_UINT64_C(1) << Q_INT64_C(-2) << true << true; - QTest::newRow("-24") << raw("\x37") << Q_UINT64_C(23) << Q_INT64_C(-24) << true << true; - QTest::newRow("-25") << raw("\x38\x18") << Q_UINT64_C(24) << Q_INT64_C(-25) << true << true; - QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << Q_UINT64_C(255) << Q_INT64_C(-256) << true << true; - QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(-257) << true << true; - QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(-65536) << true << true; - QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(-65537) << true << true; - QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(-4294967296) << true << true; - QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(-4294967297) << true << true; - QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe") - << quint64(std::numeric_limits::max() - 1) - << (std::numeric_limits::min() + 1) - << true << true; - QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff") - << quint64(std::numeric_limits::max()) - << std::numeric_limits::min() - << true << true; - QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << Q_UINT64_C(9223372036854775808) << qint64(-123456) << true << false; - QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe") - << (std::numeric_limits::max() - 1) << qint64(-123456) << true << false; - QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << std::numeric_limits::max() << qint64(-123456) << true << false; -} - -void tst_Parser::integers_data() -{ - addIntegers(); -} - -void tst_Parser::integers() -{ - QFETCH(QByteArray, data); - QFETCH(bool, isNegative); - QFETCH(quint64, expectedRaw); - QFETCH(qint64, expectedValue); - QFETCH(bool, inInt64Range); - - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QVERIFY(cbor_value_is_integer(&w.first)); - - uint64_t raw; - cbor_value_get_raw_integer(&w.first, &raw); - QCOMPARE(quint64(raw), expectedRaw); - - if (isNegative) { - QVERIFY(cbor_value_is_negative_integer(&w.first)); - QVERIFY(!cbor_value_is_unsigned_integer(&w.first)); - } else { - QVERIFY(!cbor_value_is_negative_integer(&w.first)); - QVERIFY(cbor_value_is_unsigned_integer(&w.first)); - } - - int64_t value; - if (inInt64Range) { - cbor_value_get_int64(&w.first, &value); - QCOMPARE(qint64(value), expectedValue); - } - - err = cbor_value_get_int64_checked(&w.first, &value); - QCOMPARE(err, inInt64Range ? CborNoError : CborErrorDataTooLarge); - - int ivalue; - bool inIntRange = inInt64Range && (expectedValue == int(expectedValue)); - err = cbor_value_get_int_checked(&w.first, &ivalue); - QCOMPARE(err, inIntRange ? CborNoError : CborErrorDataTooLarge); -} - -void tst_Parser::fixed_data() -{ - addColumns(); - addFixedData(); -} - -void tst_Parser::fixed() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne(data, expected); -} - -void addStringsData() -{ - // byte strings - QTest::newRow("emptybytestring") << raw("\x40") << "h''"; - QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'"; - QTest::newRow("bytestring1-nul") << raw("\x41\0") << "h'00'"; - QTest::newRow("bytestring5") << raw("\x45Hello") << "h'48656c6c6f'"; - QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") - << "h'313233343536373839303132333435363738393031323334'"; - QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3') - << "h'" + QString(256 * 2, '3') + '\''; - - // text strings - QTest::newRow("emptytextstring") << raw("\x60") << "\"\""; - QTest::newRow("textstring1") << raw("\x61 ") << "\" \""; - QTest::newRow("textstring1-nul") << raw("\x61\0") << "\"\\u0000\""; - QTest::newRow("textstring5") << raw("\x65Hello") << "\"Hello\""; - QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") - << "\"123456789012345678901234\""; - QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') - << '"' + QString(256, '3') + '"'; - - // some strings with UTF-8 content - // we had a bug in the pretty dumper - see issue #54 - QTest::newRow("textstringutf8-2char") << raw("\x62\xc2\xa0") << "\"\\u00A0\""; - QTest::newRow("textstringutf8-2char2") << raw("\x64\xc2\xa0\xc2\xa9") << "\"\\u00A0\\u00A9\""; - QTest::newRow("textstringutf8-3char") << raw("\x63\xe2\x88\x80") << "\"\\u2200\""; - QTest::newRow("textstringutf8-4char") << raw("\x64\xf0\x90\x88\x83") << "\"\\uD800\\uDE03\""; - - // strings with overlong length - QTest::newRow("emptybytestring*1") << raw("\x58\x00") << "h''_0"; - QTest::newRow("emptytextstring*1") << raw("\x78\x00") << "\"\"_0"; - QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << "h''_1"; - QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << "\"\"_1"; - QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << "h''_2"; - QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << "\"\"_2"; - QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << "h''_3"; - QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << "\"\"_3"; - QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << "h'48656c6c6f'_0"; - QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << "\"Hello\"_0"; - QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << "h'48656c6c6f'_1"; - QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << "\"Hello\"_1"; - QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << "h'48656c6c6f'_2"; - QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << "\"Hello\"_2"; - QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << "h'48656c6c6f'_3"; - QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << "\"Hello\"_3"; - - // strings with undefined length - QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "(_ )"; - QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "(_ )"; - QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "(_ h'')"; - QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "(_ \"\")"; - QTest::newRow("_emptybytestring2*1") << raw("\x5f\x58\x00\xff") << "(_ h''_0)"; - QTest::newRow("_emptytextstring2*1") << raw("\x7f\x78\x00\xff") << "(_ \"\"_0)"; - QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "(_ h'', h'')"; - QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "(_ \"\", \"\")"; - QTest::newRow("_emptybytestring3*2") << raw("\x5f\x59\x00\x00\x40\xff") << "(_ h''_1, h'')"; - QTest::newRow("_emptytextstring3*2") << raw("\x7f\x79\x00\x00\x60\xff") << "(_ \"\"_1, \"\")"; - QTest::newRow("_bytestring5x2") << raw("\x5f\x43Hel\x42lo\xff") << "(_ h'48656c', h'6c6f')"; - QTest::newRow("_textstring5x2") << raw("\x7f\x63Hel\x62lo\xff") << "(_ \"Hel\", \"lo\")"; - QTest::newRow("_bytestring5x2*8*4") << raw("\x5f\x5b\0\0\0\0\0\0\0\3Hel\x5a\0\0\0\2lo\xff") << "(_ h'48656c'_3, h'6c6f'_2)"; - QTest::newRow("_textstring5x2*8*4") << raw("\x7f\x7b\0\0\0\0\0\0\0\3Hel\x7a\0\0\0\2lo\xff") << "(_ \"Hel\"_3, \"lo\"_2)"; - QTest::newRow("_bytestring5x5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'6c', h'6c', h'6f')"; - QTest::newRow("_textstring5x5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"l\", \"o\")"; - QTest::newRow("_bytestring5x6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'', h'6c', h'6c', h'6f')"; - QTest::newRow("_textstring5x6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"\", \"l\", \"o\")"; -} - -void tst_Parser::strings_data() -{ - addColumns(); - addStringsData(); -} - -void addTagsData() -{ - // since parseOne() works recursively for tags, we can't test lone tags - QTest::newRow("tag0") << raw("\xc0\x00") << "0(0)"; - QTest::newRow("tag1") << raw("\xc1\x00") << "1(0)"; - QTest::newRow("tag24") << raw("\xd8\x18\x00") << "24(0)"; - QTest::newRow("tag255") << raw("\xd8\xff\x00") << "255(0)"; - QTest::newRow("tag256") << raw("\xd9\1\0\x00") << "256(0)"; - QTest::newRow("tag65535") << raw("\xd9\xff\xff\x00") << "65535(0)"; - QTest::newRow("tag65536") << raw("\xda\0\1\0\0\x00") << "65536(0)"; - QTest::newRow("tagUINT32_MAX-1") << raw("\xda\xff\xff\xff\xff\x00") << "4294967295(0)"; - QTest::newRow("tagUINT32_MAX") << raw("\xdb\0\0\0\1\0\0\0\0\x00") << "4294967296(0)"; - QTest::newRow("tagUINT64_MAX") << raw("\xdb" "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00") - << QString::number(std::numeric_limits::max()) + "(0)"; - - // overlong tags - QTest::newRow("tag0*1") << raw("\xd8\0\x00") << "0_0(0)"; - QTest::newRow("tag0*2") << raw("\xd9\0\0\x00") << "0_1(0)"; - QTest::newRow("tag0*4") << raw("\xda\0\0\0\0\x00") << "0_2(0)"; - QTest::newRow("tag0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x00") << "0_3(0)"; - - // tag other things - QTest::newRow("unixtime") << raw("\xc1\x1a\x55\x4b\xbf\xd3") << "1(1431027667)"; - QTest::newRow("rfc3339date") << raw("\xc0\x78\x19" "2015-05-07 12:41:07-07:00") - << "0(\"2015-05-07 12:41:07-07:00\")"; - QTest::newRow("tag6+false") << raw("\xc6\xf4") << "6(false)"; - QTest::newRow("tag25+true") << raw("\xd8\x19\xf5") << "25(true)"; - QTest::newRow("tag256+null") << raw("\xd9\1\0\xf6") << "256(null)"; - QTest::newRow("tag65536+simple32") << raw("\xda\0\1\0\0\xf8\x20") << "65536(simple(32))"; - QTest::newRow("float+unixtime") << raw("\xc1\xfa\x4e\xaa\x97\x80") << "1(1431027712.f)"; - QTest::newRow("double+unixtime") << raw("\xc1\xfb" "\x41\xd5\x52\xef" "\xf4\xc7\xce\xfe") - << "1(1431027667.1220088)"; -} - -void tst_Parser::tags_data() -{ - addColumns(); - addTagsData(); -} - -void tst_Parser::tagTags() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne("\xd9\xd9\xf7" + data, "55799(" + expected + ')'); - if (!compareFailed) - compareOne("\xd9\xd9\xf7" "\xd9\xd9\xf7" + data, "55799(55799(" + expected + "))"); -} - -void addEmptyContainersData() -{ - QTest::newRow("emptyarray") << raw("\x80") << "[]" << 0; - QTest::newRow("emptymap") << raw("\xa0") << "{}" << 0; - QTest::newRow("_emptyarray") << raw("\x9f\xff") << "[_ ]" << -1; - QTest::newRow("_emptymap") << raw("\xbf\xff") << "{_ }" << -1; -} - -void tst_Parser::emptyContainers_data() -{ - addColumns(); - addEmptyContainersData(); -} - -void tst_Parser::emptyContainers() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - QFETCH(int, n); - - compareOneSize(n, data, expected); -} - -void tst_Parser::arrays_data() -{ - addColumns(); - addFixedData(); - addStringsData(); - addTagsData(); -} - -void tst_Parser::arrays() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOneSize(1, "\x81" + data, '[' + expected + ']'); - if (compareFailed) return; - - compareOneSize(2, "\x82" + data + data, '[' + expected + ", " + expected + ']'); - if (compareFailed) return; - - // overlong length - compareOneSize(1, "\x98\1" + data, "[_0 " + expected + ']'); - if (compareFailed) return; - compareOneSize(1, raw("\x99\0\1") + data, "[_1 " + expected + ']'); - if (compareFailed) return; - compareOneSize(1, raw("\x9a\0\0\0\1") + data, "[_2 " + expected + ']'); - if (compareFailed) return; - compareOneSize(1, raw("\x9b\0\0\0\0\0\0\0\1") + data, "[_3 " + expected + ']'); - if (compareFailed) return; - - // medium-sized array: 32 elements (1 << 5) - expected += ", "; - for (int i = 0; i < 5; ++i) { - data += data; - expected += expected; - } - expected.chop(2); // remove the last ", " - compareOneSize(32, "\x98\x20" + data, '[' + expected + ']'); - if (compareFailed) return; - - // large array: 256 elements (32 << 3) - expected += ", "; - for (int i = 0; i < 3; ++i) { - data += data; - expected += expected; - } - expected.chop(2); // remove the last ", " - compareOneSize(256, raw("\x99\1\0") + data, '[' + expected + ']'); - if (compareFailed) return; -} - -void tst_Parser::undefLengthArrays() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne("\x9f" + data + "\xff", "[_ " + expected + ']'); - if (compareFailed) return; - - compareOne("\x9f" + data + data + "\xff", "[_ " + expected + ", " + expected + ']'); -} - -void tst_Parser::nestedArrays() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOneSize(1, "\x81\x81" + data, "[[" + expected + "]]"); - if (compareFailed) return; - - compareOneSize(1, "\x81\x81\x81" + data, "[[[" + expected + "]]]"); - if (compareFailed) return; - - compareOneSize(1, "\x81\x82" + data + data, "[[" + expected + ", " + expected + "]]"); - if (compareFailed) return; - - compareOneSize(2, "\x82\x81" + data + data, "[[" + expected + "], " + expected + "]"); - if (compareFailed) return; - - compareOneSize(2, "\x82\x81" + data + '\x81' + data, "[[" + expected + "], [" + expected + "]]"); - if (compareFailed) return; - - // undefined length - compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\xff", "[_ [_ " + expected + ", " + expected + "]]"); - if (compareFailed) return; - - compareOneSize(-1, "\x9f\x9f" + data + "\xff\x9f" + data + "\xff\xff", "[_ [_ " + expected + "], [_ " + expected + "]]"); - if (compareFailed) return; - - compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\x9f" + data + "\xff\xff", - "[_ [_ " + expected + ", " + expected + "], [_ " + expected + "]]"); - if (compareFailed) return; - - // mix them - compareOneSize(1, "\x81\x9f" + data + "\xff", "[[_ " + expected + "]]"); - if (compareFailed) return; - - compareOneSize(-1, "\x9f\x81" + data + "\xff", "[_ [" + expected + "]]"); -} - -void tst_Parser::maps_data() -{ - arrays_data(); -} - -void tst_Parser::maps() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - // integer key - compareOneSize(1, "\xa1\1" + data, "{1: " + expected + '}'); - if (compareFailed) return; - - // string key - compareOneSize(1, "\xa1\x65" "Hello" + data, "{\"Hello\": " + expected + '}'); - if (compareFailed) return; - - // map to self - compareOneSize(1, "\xa1" + data + data, '{' + expected + ": " + expected + '}'); - if (compareFailed) return; - - // two integer keys - compareOneSize(2, "\xa2\1" + data + "\2" + data, "{1: " + expected + ", 2: " + expected + '}'); - if (compareFailed) return; - - // OneSize integer and OneSize string key - compareOneSize(2, "\xa2\1" + data + "\x65" "Hello" + data, "{1: " + expected + ", \"Hello\": " + expected + '}'); - if (compareFailed) return; -} - -void tst_Parser::undefLengthMaps() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - // integer key - compareOne("\xbf\1" + data + '\xff', "{_ 1: " + expected + '}'); - if (compareFailed) return; - - compareOne("\xbf\1" + data + '\2' + data + '\xff', "{_ 1: " + expected + ", 2: " + expected + '}'); - if (compareFailed) return; - - compareOne("\xbf\1" + data + "\x65Hello" + data + '\xff', "{_ 1: " + expected + ", \"Hello\": " + expected + '}'); - if (compareFailed) return; - - compareOne("\xbf\x65Hello" + data + '\1' + data + '\xff', "{_ \"Hello\": " + expected + ", 1: " + expected + '}'); -} - -void tst_Parser::nestedMaps() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - // nested maps as values - compareOneSize(1, "\xa1\1\xa1\2" + data, "{1: {2: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(1, "\xa1\x65Hello\xa1\2" + data, "{\"Hello\": {2: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(1, "\xa1\1\xa2\2" + data + '\x20' + data, "{1: {2: " + expected + ", -1: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(2, "\xa2\1\xa1\2" + data + "\2\xa1\x20" + data, "{1: {2: " + expected + "}, 2: {-1: " + expected + "}}"); - if (compareFailed) return; - - // nested maps as keys - compareOneSize(1, "\xa1\xa1\xf4" + data + "\xf5", "{{false: " + expected + "}: true}"); - if (compareFailed) return; - - compareOneSize(1, "\xa1\xa1" + data + data + "\xa1" + data + data, - "{{" + expected + ": " + expected + "}: {" + expected + ": " + expected + "}}"); - if (compareFailed) return; - - // undefined length - compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\xff", "{_ 1: {_ 2: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\1\xbf\2" + data + '\x20' + data + "\xff\xff", "{_ 1: {_ 2: " + expected + ", -1: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\2\xbf\x20" + data + "\xff\xff", - "{_ 1: {_ 2: " + expected + "}, 2: {_ -1: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\xbf" + data + data + "\xff\xbf" + data + data + "\xff\xff", - "{_ {_ " + expected + ": " + expected + "}: {_ " + expected + ": " + expected + "}}"); - if (compareFailed) return; - - // mix them - compareOneSize(1, "\xa1\1\xbf\2" + data + "\xff", "{1: {_ 2: " + expected + "}}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\1\xa1\2" + data + "\xff", "{_ 1: {2: " + expected + "}}"); - if (compareFailed) return; -} - -void addMapMixedData() -{ - QTest::newRow("map-0-24") << raw("\xa1\0\x18\x18") << "{0: 24}" << 1; - QTest::newRow("map-0*1-24") << raw("\xa1\x18\0\x18\x18") << "{0_0: 24}" << 1; - QTest::newRow("map-0*1-24*2") << raw("\xa1\x18\0\x19\0\x18") << "{0_0: 24_1}" << 1; - QTest::newRow("map-0*4-24*2") << raw("\xa1\x1a\0\0\0\0\x19\0\x18") << "{0_2: 24_1}" << 1; - QTest::newRow("map-24-0") << raw("\xa1\x18\x18\0") << "{24: 0}" << 1; - QTest::newRow("map-24-0*1") << raw("\xa1\x18\x18\x18\0") << "{24: 0_0}" << 1; - QTest::newRow("map-255-65535") << raw("\xa1\x18\xff\x19\xff\xff") << "{255: 65535}" << 1; - - QTest::newRow("_map-0-24") << raw("\xbf\0\x18\x18\xff") << "{_ 0: 24}" << 1; - QTest::newRow("_map-0*1-24") << raw("\xbf\x18\0\x18\x18\xff") << "{_ 0_0: 24}" << 1; - QTest::newRow("_map-0*1-24*2") << raw("\xbf\x18\0\x19\0\x18\xff") << "{_ 0_0: 24_1}" << 1; - QTest::newRow("_map-0*4-24*2") << raw("\xbf\x1a\0\0\0\0\x19\0\x18\xff") << "{_ 0_2: 24_1}" << 1; - QTest::newRow("_map-24-0") << raw("\xbf\x18\x18\0\xff") << "{_ 24: 0}" << 1; - QTest::newRow("_map-24-0*1") << raw("\xbf\x18\x18\x18\0\xff") << "{_ 24: 0_0}" << 1; - QTest::newRow("_map-255-65535") << raw("\xbf\x18\xff\x19\xff\xff\xff") << "{_ 255: 65535}" << 1; -} - -void tst_Parser::mapMixed_data() -{ - addColumns(); - addMapMixedData(); -} - -void tst_Parser::mapsAndArrays() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - // arrays of maps - compareOneSize(1, "\x81\xa1\1" + data, "[{1: " + expected + "}]"); - if (compareFailed) return; - - compareOneSize(2, "\x82\xa1\1" + data + "\xa1\2" + data, "[{1: " + expected + "}, {2: " + expected + "}]"); - if (compareFailed) return; - - compareOneSize(1, "\x81\xa2\1" + data + "\2" + data, "[{1: " + expected + ", 2: " + expected + "}]"); - if (compareFailed) return; - - compareOneSize(-1, "\x9f\xa1\1" + data + "\xff", "[_ {1: " + expected + "}]"); - if (compareFailed) return; - - compareOneSize(1, "\x81\xbf\1" + data + "\xff", "[{_ 1: " + expected + "}]"); - if (compareFailed) return; - - compareOneSize(-1, "\x9f\xbf\1" + data + "\xff\xff", "[_ {_ 1: " + expected + "}]"); - if (compareFailed) return; - - // maps of arrays - compareOneSize(1, "\xa1\1\x81" + data, "{1: [" + expected + "]}"); - if (compareFailed) return; - - compareOneSize(1, "\xa1\1\x82" + data + data, "{1: [" + expected + ", " + expected + "]}"); - if (compareFailed) return; - - compareOneSize(2, "\xa2\1\x81" + data + "\x65Hello\x81" + data, "{1: [" + expected + "], \"Hello\": [" + expected + "]}"); - if (compareFailed) return; - - compareOneSize(1, "\xa1\1\x9f" + data + "\xff", "{1: [_ " + expected + "]}"); - if (compareFailed) return; - - compareOneSize(1, "\xa1\1\x9f" + data + data + "\xff", "{1: [_ " + expected + ", " + expected + "]}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\1\x81" + data + "\xff", "{_ 1: [" + expected + "]}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\xff", "{_ 1: [_ " + expected + "]}"); - if (compareFailed) return; - - compareOneSize(-1, "\xbf\1\x9f" + data + data + "\xff\xff", "{_ 1: [_ " + expected + ", " + expected + "]}"); - if (compareFailed) return; - - // mixed with indeterminate length strings - compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\x65Hello\xbf" + data + "\x7f\xff\xff\xff", - "{_ 1: [_ " + expected + "], \"Hello\": {_ " + expected + ": (_ )}}"); -} - -void tst_Parser::chunkedString_data() -{ - QTest::addColumn("data"); - QTest::addColumn("concatenated"); - QTest::addColumn("chunks"); - - // non-chunked: - QTest::newRow("emptybytestring") << raw("\x40") << "h''" << QStringList{"h''"}; - QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'" << QStringList{"h'20'"}; - QTest::newRow("emptytextstring") << raw("\x60") << "\"\"" << QStringList{"\"\""}; - QTest::newRow("textstring1") << raw("\x61 ") << "\" \"" << QStringList{"\" \""}; - - // empty chunked: - QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "h''" << QStringList{}; - QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "\"\"" << QStringList{}; - QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "h''" << QStringList{"h''"}; - QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "\"\"" << QStringList{"\"\""}; - QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "h''" << QStringList{"h''", "h''"}; - QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "\"\"" << QStringList{"\"\"", "\"\""}; - - // regular chunks - QTest::newRow("_bytestring1") << raw("\x5f\x41 \xff") << "h'20'" << QStringList{"h'20'"}; - QTest::newRow("_bytestring2") << raw("\x5f\x41 \x41z\xff") << "h'207a'" << QStringList{"h'20'", "h'7a'"}; - QTest::newRow("_bytestring3") << raw("\x5f\x41 \x58\x18""123456789012345678901234\x41z\xff") - << "h'203132333435363738393031323334353637383930313233347a'" - << QStringList{"h'20'", "h'313233343536373839303132333435363738393031323334'", "h'7a'"}; - - QTest::newRow("_textstring1") << raw("\x7f\x61 \xff") << "\" \"" << QStringList{"\" \""}; - QTest::newRow("_textstring2") << raw("\x7f\x61 \x61z\xff") << "\" z\"" << QStringList{"\" \"", "\"z\""}; - QTest::newRow("_textstring3") << raw("\x7f\x61 \x78\x18""123456789012345678901234\x61z\xff") - << "\" 123456789012345678901234z\"" - << QStringList{"\" \"", "\"123456789012345678901234\"", "\"z\""}; -} - -static void chunkedStringTest(const QByteArray &data, const QString &concatenated, - QStringList &chunks, CborType ourType) -{ - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - CborValue value; - QVERIFY(cbor_value_is_array(&w.first)); - err = cbor_value_enter_container(&w.first, &value); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QVERIFY(cbor_value_is_byte_string(&value) || cbor_value_is_text_string(&value)); - - CborValue copy = value; - - Q_UNUSED(chunks); // for future API - QCOMPARE(cbor_value_advance(&value), CborNoError); - - // compare to the concatenated data - { - size_t n; - err = cbor_value_calculate_string_length(©, &n); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - QByteArray buffer(n, Qt::Uninitialized); - QString formatted; - if (cbor_value_is_byte_string(©)) { - err = cbor_value_copy_byte_string(©, (uint8_t *)buffer.data(), &n, nullptr); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE(int(n), buffer.size()); - - formatted = QString::fromLatin1("h'" + buffer.toHex() + '\''); - } else { - err = cbor_value_copy_text_string(©, buffer.data(), &n, nullptr); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE(int(n), buffer.size()); - - formatted = '"' + QString::fromUtf8(buffer.data(), n) + '"'; - } - QCOMPARE(formatted, concatenated); - } - - // confirm that the extra string we appended is still here - QVERIFY(!cbor_value_at_end(&value)); - QCOMPARE(cbor_value_get_type(&value), ourType); - size_t len; - err = cbor_value_get_string_length(&value, &len); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE(len, size_t(0)); - - err = cbor_value_advance(&value); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - // confirm EOF - QVERIFY(cbor_value_at_end(&value)); - - err = cbor_value_leave_container(&w.first, &value); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE((void*)cbor_value_get_next_byte(&w.first), (void*)w.end()); -} - -void tst_Parser::chunkedString() -{ - QFETCH(QByteArray, data); - QFETCH(QString, concatenated); - QFETCH(QStringList, chunks); - - // Make this an array of two entries, with the second an empty byte or text string - CborType ourType = CborType(data.at(0) & 0xe0); - data.prepend(char(0x82)); - data.append(ourType); - - chunkedStringTest(data, concatenated, chunks, ourType); -} - -void tst_Parser::chunkedStringInUndefArray() -{ - QFETCH(QByteArray, data); - QFETCH(QString, concatenated); - QFETCH(QStringList, chunks); - - // Make this an array of undefined length entries, with the second entry an empty byte or text string - CborType ourType = CborType(data.at(0) & 0xe0); - data.prepend(char(0x9f)); - data.append(ourType); - data.append(char(0xff)); - - chunkedStringTest(data, concatenated, chunks, ourType); -} - -void tst_Parser::stringLength_data() -{ - QTest::addColumn("data"); - QTest::addColumn("expected"); - - QTest::newRow("emptybytestring") << raw("\x40") << 0; - QTest::newRow("bytestring1") << raw("\x41 ") << 1; - QTest::newRow("bytestring1-nul") << raw("\x41\0") << 1; - QTest::newRow("bytestring5") << raw("\x45Hello") << 5; - QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") << 24; - QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3') << 256; - - // text strings - QTest::newRow("emptytextstring") << raw("\x60") << 0; - QTest::newRow("textstring1") << raw("\x61 ") << 1; - QTest::newRow("textstring1-nul") << raw("\x61\0") << 1; - QTest::newRow("textstring5") << raw("\x65Hello") << 5; - QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") << 24; - QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') << 256; - - // strings with overlong length - QTest::newRow("emptybytestring*1") << raw("\x58\x00") << 0; - QTest::newRow("emptytextstring*1") << raw("\x78\x00") << 0; - QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << 0; - QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << 0; - QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << 0; - QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << 0; - QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << 0; - QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << 0; - QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << 5; - QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << 5; - QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << 5; - QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << 5; - QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << 5; - QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << 5; - QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << 5; - QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << 5; - - // strings with undefined length - QTest::newRow("_emptybytestring") << raw("\x5f\xff") << 0; - QTest::newRow("_emptytextstring") << raw("\x7f\xff") << 0; - QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << 0; - QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << 0; - QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << 0; - QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << 0; - QTest::newRow("_bytestring5*2") << raw("\x5f\x43Hel\x42lo\xff") << 5; - QTest::newRow("_textstring5*2") << raw("\x7f\x63Hel\x62lo\xff") << 5; - QTest::newRow("_bytestring5*5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << 5; - QTest::newRow("_textstring5*5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << 5; - QTest::newRow("_bytestring5*6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << 5; - QTest::newRow("_textstring5*6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << 5; -} - -void tst_Parser::stringLength() -{ - QFETCH(QByteArray, data); - QFETCH(int, expected); - - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - size_t result; - err = cbor_value_calculate_string_length(&w.first, &result); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE(result, size_t(expected)); - - if (cbor_value_is_length_known(&w.first)) { - QCOMPARE(cbor_value_get_string_length(&w.first, &result), CborNoError); - QCOMPARE(result, size_t(expected)); - } - -} - -void tst_Parser::stringCompare_data() -{ - QTest::addColumn("data"); - QTest::addColumn("string"); - QTest::addColumn("expected"); - - // compare empty to empty - QTest::newRow("empty-empty") << raw("\x60") << QString() << true; - QTest::newRow("_empty-empty") << raw("\x7f\xff") << QString() << true; - QTest::newRow("_empty*1-empty") << raw("\x7f\x60\xff") << QString() << true; - QTest::newRow("_empty*2-empty") << raw("\x7f\x60\x60\xff") << QString() << true; - - // compare empty to non-empty - QTest::newRow("empty-nonempty") << raw("\x60") << "Hello" << false; - QTest::newRow("_empty-nonempty") << raw("\x7f\xff") << "Hello" << false; - QTest::newRow("_empty*1-nonempty") << raw("\x7f\x60\xff") << "Hello" << false; - QTest::newRow("_empty*2-nonempty") << raw("\x7f\x60\x60\xff") << "Hello" << false; - - // compare same strings - QTest::newRow("same-short-short") << raw("\x65Hello") << "Hello" << true; - QTest::newRow("same-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello" << true; - QTest::newRow("same-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello" << true; - QTest::newRow("same-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello" << true; - QTest::newRow("same-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello" << true; - QTest::newRow("same-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight") - << "Good morning, good afternoon and goodnight" << true; - QTest::newRow("same-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff") - << "Good morning, good afternoon and goodnight" << true; - QTest::newRow("same-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff") - << "Good morning, good afternoon and goodnight" << true; - - // compare different strings (same length) - QTest::newRow("diff-same-length-short-short") << raw("\x65Hello") << "World" << false; - QTest::newRow("diff-same-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "World" << false; - QTest::newRow("diff-same-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "World" << false; - QTest::newRow("diff-same-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "World" << false; - QTest::newRow("diff-same-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "World" << false; - QTest::newRow("diff-same-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight") - << "Good morning, good afternoon and goodnight, world" << false; - QTest::newRow("diff-same-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff") - << "Good morning, good afternoon and goodnight, world" << false; - QTest::newRow("diff-same-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff") - << "Good morning, good afternoon and goodnight, world" << false; - - // compare different strings (different length) - QTest::newRow("diff-diff-length-short-short") << raw("\x65Hello") << "Hello World" << false; - QTest::newRow("diff-diff-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello World" << false; - QTest::newRow("diff-diff-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello World" << false; - QTest::newRow("diff-diff-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello World" << false; - QTest::newRow("diff-diff-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello World" << false; - QTest::newRow("diff-diff-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight") - << "Good morning, good afternoon and goodnight World" << false; - QTest::newRow("diff-diff-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff") - << "Good morning, good afternoon and goodnight World" << false; - QTest::newRow("diff-diff-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff") - << "Good morning, good afternoon and goodnight World" << false; - - // compare against non-strings - QTest::newRow("unsigned") << raw("\0") << "0" << false; - QTest::newRow("negative") << raw("\x20") << "-1" << false; - QTest::newRow("emptybytestring") << raw("\x40") << "" << false; - QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "" << false; - QTest::newRow("shortbytestring") << raw("\x45Hello") << "Hello" << false; - QTest::newRow("longbytestring") << raw("\x58\x2aGood morning, good afternoon and goodnight") - << "Good morning, good afternoon and goodnight" << false; - QTest::newRow("emptyarray") << raw("\x80") << "" << false; - QTest::newRow("emptymap") << raw("\xa0") << "" << false; - QTest::newRow("array") << raw("\x81\x65Hello") << "Hello" << false; - QTest::newRow("map") << raw("\xa1\x65Hello\x65World") << "Hello World" << false; - QTest::newRow("false") << raw("\xf4") << "false" << false; - QTest::newRow("true") << raw("\xf5") << "true" << false; - QTest::newRow("null") << raw("\xf6") << "null" << false; -} - -void compareOneString(const QByteArray &data, const QString &string, bool expected, int line) -{ - compareFailed = true; - - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\""); - - bool result; - QByteArray bastring = string.toUtf8(); - err = cbor_value_text_string_equals(&w.first, bastring.constData(), &result); - QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\""); - QCOMPARE(result, expected); - - if (expected) { - size_t len; - cbor_value_skip_tag(&w.first); - if (cbor_value_is_length_known(&w.first)) { - QCOMPARE(cbor_value_get_string_length(&w.first, &len), CborNoError); - QCOMPARE(int(len), bastring.size()); - } - QCOMPARE(cbor_value_calculate_string_length(&w.first, &len), CborNoError); - QCOMPARE(int(len), bastring.size()); - } - - compareFailed = false; -} -#define compareOneString(data, string, expected) compareOneString(data, string, expected, __LINE__) - -void tst_Parser::stringCompare() -{ - QFETCH(QByteArray, data); - QFETCH(QString, string); - QFETCH(bool, expected); - - compareOneString(data, string, expected); - if (compareFailed) return; - - // tag it - compareOneString("\xc1" + data, string, expected); - if (compareFailed) return; - - compareOneString("\xc1\xc2" + data, string, expected); -} - -void tst_Parser::mapFind_data() -{ - // Rules: - // we are searching for string "needle" - // if present, the value should be the string "haystack" (with tag 42) - - QTest::addColumn("data"); - QTest::addColumn("expected"); - - QTest::newRow("emptymap") << raw("\xa0") << false; - QTest::newRow("_emptymap") << raw("\xbf\xff") << false; - - // maps not containing our items - QTest::newRow("absent-unsigned-unsigned") << raw("\xa1\0\0") << false; - QTest::newRow("absent-taggedunsigned-unsigned") << raw("\xa1\xc0\0\0") << false; - QTest::newRow("absent-unsigned-taggedunsigned") << raw("\xa1\0\xc0\0") << false; - QTest::newRow("absent-taggedunsigned-taggedunsigned") << raw("\xa1\xc0\0\xc0\0") << false; - QTest::newRow("absent-string-unsigned") << raw("\xa1\x68haystack\0") << false; - QTest::newRow("absent-taggedstring-unsigned") << raw("\xa1\xc0\x68haystack\0") << false; - QTest::newRow("absent-string-taggedunsigned") << raw("\xa1\x68haystack\xc0\0") << false; - QTest::newRow("absent-taggedstring-taggedunsigned") << raw("\xa1\xc0\x68haystack\xc0\0") << false; - QTest::newRow("absent-string-string") << raw("\xa1\x68haystack\x66needle") << false; - QTest::newRow("absent-string-taggedstring") << raw("\xa1\x68haystack\xc0\x66needle") << false; - QTest::newRow("absent-taggedstring-string") << raw("\xa1\xc0\x68haystack\x66needle") << false; - QTest::newRow("absent-string-taggedstring") << raw("\xa1\xc0\x68haystack\xc0\x66needle") << false; - - QTest::newRow("absent-string-emptyarray") << raw("\xa1\x68haystack\x80") << false; - QTest::newRow("absent-string-_emptyarray") << raw("\xa1\x68haystack\x9f\xff") << false; - QTest::newRow("absent-string-array1") << raw("\xa1\x68haystack\x81\0") << false; - QTest::newRow("absent-string-array2") << raw("\xa1\x68haystack\x85\0\1\2\3\4") << false; - QTest::newRow("absent-string-array3") << raw("\xa1\x68haystack\x85\x63one\x63two\x65three\x64""four\x64""five") << false; - - QTest::newRow("absent-string-emptymap") << raw("\xa1\x68haystack\xa0") << false; - QTest::newRow("absent-string-_emptymap") << raw("\xa1\x68haystack\xbf\xff") << false; - QTest::newRow("absent-string-map") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle") << false; - QTest::newRow("absent-string-map2") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle\61z\62yx") << false; - - // maps containing our items - QTest::newRow("alone") << raw("\xa1\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("tagged") << raw("\xa1\xc1\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("doubletagged") << raw("\xa1\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("chunked") << raw("\xa1\x7f\x66needle\xff\xd8\x2a\x68haystack") << true; - QTest::newRow("chunked*2") << raw("\xa1\x7f\x60\x66needle\xff\xd8\x2a\x68haystack") << true; - QTest::newRow("chunked*2bis") << raw("\xa1\x7f\x66needle\x60\xff\xd8\x2a\x68haystack") << true; - QTest::newRow("chunked*3") << raw("\xa1\x7f\x62ne\x62""ed\x62le\xff\xd8\x2a\x68haystack") << true; - QTest::newRow("chunked*8") << raw("\xa1\x7f\x61n\x61""e\x60\x61""e\x61""d\x60\x62le\x60\xff\xd8\x2a\x68haystack") << true; - - QTest::newRow("1before") << raw("\xa2\x68haystack\x66needle\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("tagged-1before") << raw("\xa2\xc1\x68haystack\x66needle\xc1\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("doubletagged-1before2") << raw("\xa2\xc1\xc2\x68haystack\x66needle\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true; - - QTest::newRow("arraybefore") << raw("\xa2\x61z\x80\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("nestedarraybefore") << raw("\xa2\x61z\x81\x81\0\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("arrayarraybefore") << raw("\xa2\x82\1\2\x80\x66needle\xd8\x2a\x68haystack") << true; - - QTest::newRow("mapbefore") << raw("\xa2\x61z\xa0\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("nestedmapbefore") << raw("\xa2\x61z\xa1\0\x81\0\x66needle\xd8\x2a\x68haystack") << true; - QTest::newRow("mapmapbefore") << raw("\xa2\xa1\1\2\xa0\x66needle\xd8\x2a\x68haystack") << true; -} - -void tst_Parser::mapFind() -{ - QFETCH(QByteArray, data); - QFETCH(bool, expected); - - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - CborValue element; - err = cbor_value_map_find_value(&w.first, "needle", &element); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - if (expected) { - QCOMPARE(int(element.type), int(CborTagType)); - - CborTag tag; - err = cbor_value_get_tag(&element, &tag); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE(int(tag), 42); - - bool equals; - err = cbor_value_text_string_equals(&element, "haystack", &equals); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QVERIFY(equals); - } else { - QCOMPARE(int(element.type), int(CborInvalidType)); - } -} - -void tst_Parser::checkedIntegers_data() -{ - QTest::addColumn("data"); - QTest::addColumn("result"); // QVariant so we can note numbers out of int64_t range - - QTest::newRow("0") << raw("\x00") << QVariant(Q_INT64_C(0)); - QTest::newRow("1") << raw("\x01") << QVariant(Q_INT64_C(1)); - QTest::newRow("10") << raw("\x0a") << QVariant(Q_INT64_C(10)); - QTest::newRow("23") << raw("\x17") << QVariant(Q_INT64_C(23)); - QTest::newRow("24") << raw("\x18\x18") << QVariant(Q_INT64_C(24)); - QTest::newRow("UINT8_MAX") << raw("\x18\xff") << QVariant(Q_INT64_C(255)); - QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << QVariant(Q_INT64_C(256)); - QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << QVariant(Q_INT64_C(65535)); - QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << QVariant(Q_INT64_C(65536)); - QTest::newRow("INT32_MAX") << raw("\x1a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(2147483647)); - QTest::newRow("INT32_MAX+1") << raw("\x1a\x80\x00\x00\x00") << QVariant(Q_INT64_C(2147483648)); - QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295)); - QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296)); - QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << QVariant(); // out of range - - // negative integers - QTest::newRow("-1") << raw("\x20") << QVariant(Q_INT64_C(-1)); - QTest::newRow("-2") << raw("\x21") << QVariant(Q_INT64_C(-2)); - QTest::newRow("-24") << raw("\x37") << QVariant(Q_INT64_C(-24)); - QTest::newRow("-25") << raw("\x38\x18") << QVariant(Q_INT64_C(-25)); - QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(Q_INT64_C(-256)); - QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(Q_INT64_C(-257)); - QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(Q_INT64_C(-65536)); - QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(Q_INT64_C(-65537)); - QTest::newRow("INT32_MIN") << raw("\x3a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(-2147483648)); - QTest::newRow("INT32_MIN-1") << raw("\x3a\x80\x00\x00\x00") << QVariant(Q_INT64_C(-2147483649)); - QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296)); - QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297)); - QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe") - << QVariant(std::numeric_limits::min() + 1); - QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff") - << QVariant(std::numeric_limits::min()); - QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << QVariant(); // out of range - QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe") - << QVariant(); // out of range - QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << QVariant(); // out of range -} - -void tst_Parser::checkedIntegers() -{ - QFETCH(QByteArray, data); - QFETCH(QVariant, result); - int64_t expected = result.toLongLong(); - - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - int64_t v; - err = cbor_value_get_int64_checked(&w.first, &v); - if (result.isNull()) { - QCOMPARE(err, CborErrorDataTooLarge); - } else { - QCOMPARE(v, expected); - } - - int v2; - err = cbor_value_get_int_checked(&w.first, &v2); - if (result.isNull() || expected < std::numeric_limits::min() || expected > std::numeric_limits::max()) { - QCOMPARE(err, CborErrorDataTooLarge); - } else { - QCOMPARE(int64_t(v2), expected); - } -} - -static void addValidationColumns() -{ - QTest::addColumn("data"); - QTest::addColumn("flags"); // future - QTest::addColumn("expectedError"); -} - -static void addValidationData() -{ - // illegal numbers are future extension points - QTest::newRow("illegal-number-in-unsigned-1") << raw("\x81\x1c") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-unsigned-2") << raw("\x81\x1d") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-unsigned-3") << raw("\x81\x1e") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-unsigned-4") << raw("\x81\x1f") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-negative-1") << raw("\x81\x3c") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-negative-2") << raw("\x81\x3d") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-negative-3") << raw("\x81\x3e") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-negative-4") << raw("\x81\x3f") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-bytearray-length-1") << raw("\x81\x5c") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-bytearray-length-2") << raw("\x81\x5d") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-bytearray-length-3") << raw("\x81\x5e") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-string-length-1") << raw("\x81\x7c") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-string-length-2") << raw("\x81\x7d") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-string-length-3") << raw("\x81\x7e") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-array-length-1") << raw("\x81\x9c") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-array-length-2") << raw("\x81\x9d") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-array-length-3") << raw("\x81\x9e") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-map-length-1") << raw("\x81\xbc") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-map-length-2") << raw("\x81\xbd") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-map-length-3") << raw("\x81\xbe") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-tag-1") << raw("\x81\xdc") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-tag-2") << raw("\x81\xdd") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-tag-3") << raw("\x81\xde") << 0 << CborErrorIllegalNumber; - QTest::newRow("illegal-number-in-tag-4") << raw("\x81\xdf") << 0 << CborErrorIllegalNumber; - - QTest::newRow("unsigned-too-short-1-0") << raw("\x81\x18") << 0 << CborErrorUnexpectedEOF; // requires 1 byte, 0 given - QTest::newRow("unsigned-too-short-2-0") << raw("\x81\x19") << 0 << CborErrorUnexpectedEOF; // requires 2 bytes, 0 given - QTest::newRow("unsigned-too-short-2-1") << raw("\x81\x19\x01") << 0 << CborErrorUnexpectedEOF; // etc - QTest::newRow("unsigned-too-short-4-0") << raw("\x81\x1a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("unsigned-too-short-4-3") << raw("\x81\x1a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("unsigned-too-short-8-0") << raw("\x81\x1b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("unsigned-too-short-8-7") << raw("\x81\x1b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-1-0") << raw("\x81\x38") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-2-0") << raw("\x81\x39") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-2-1") << raw("\x81\x39\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-4-0") << raw("\x81\x3a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-4-3") << raw("\x81\x3a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-8-0") << raw("\x81\x3b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("negative-length-too-short-8-7") << raw("\x81\x3b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-1-0") << raw("\x81\x58") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-2-0") << raw("\x81\x59") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-2-1") << raw("\x81\x59\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-4-0") << raw("\x81\x5a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-4-3") << raw("\x81\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-8-0") << raw("\x81\x5b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-length-too-short-8-7") << raw("\x81\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-1-0") << raw("\x81\x78") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-2-0") << raw("\x81\x79") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-2-1") << raw("\x81\x79\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-4-0") << raw("\x81\x7a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-4-3") << raw("\x81\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-8-0") << raw("\x81\x7b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-length-too-short-8-7") << raw("\x81\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-1-0") << raw("\x81\x5f\x58") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-2-0") << raw("\x81\x5f\x59") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-2-1") << raw("\x81\x5f\x59\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-4-0") << raw("\x81\x5f\x5a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-4-3") << raw("\x81\x5f\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-8-0") << raw("\x81\x5f\x5b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-length-too-short-8-7") << raw("\x81\x5f\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-1-0") << raw("\x81\x7f\x78") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-2-0") << raw("\x81\x7f\x79") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-2-1") << raw("\x81\x7f\x79\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-4-0") << raw("\x81\x7f\x7a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-4-3") << raw("\x81\x7f\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-8-0") << raw("\x81\x7f\x7b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-length-too-short-8-7") << raw("\x81\x7f\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-1-0") << raw("\x81\x5f\x40\x58") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-2-0") << raw("\x81\x5f\x40\x59") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-2-1") << raw("\x81\x5f\x40\x59\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-4-0") << raw("\x81\x5f\x40\x5a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-4-3") << raw("\x81\x5f\x40\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-8-0") << raw("\x81\x5f\x40\x5b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-2-length-too-short-8-7") << raw("\x81\x5f\x40\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-1-0") << raw("\x81\x7f\x60\x78") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-2-0") << raw("\x81\x7f\x60\x79") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-2-1") << raw("\x81\x7f\x60\x79\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-4-0") << raw("\x81\x7f\x60\x7a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-4-3") << raw("\x81\x7f\x60\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-8-0") << raw("\x81\x7f\x60\x7b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-2-length-too-short-8-7") << raw("\x81\x7f\x60\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-1-0") << raw("\x81\x98") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-2-0") << raw("\x81\x99") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-2-1") << raw("\x81\x99\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-4-0") << raw("\x81\x9a") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-4-3") << raw("\x81\x9a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-8-0") << raw("\x81\x9b") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-length-too-short-8-7") << raw("\x81\x9b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-1-0") << raw("\x81\xb8") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-2-0") << raw("\x81\xb9") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-2-1") << raw("\x81\xb9\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-4-0") << raw("\x81\xba") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-4-3") << raw("\x81\xba\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-8-0") << raw("\x81\xbb") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-length-too-short-8-7") << raw("\x81\xbb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-1-0") << raw("\x81\xd8") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-2-0") << raw("\x81\xd9") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-2-1") << raw("\x81\xd9\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-4-0") << raw("\x81\xda") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-4-3") << raw("\x81\xda\x01\x02\x03") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-8-0") << raw("\x81\xdb") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("tag-too-short-8-7") << raw("\x81\xdb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("fp16-too-short1") << raw("\x81\xf9") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("fp16-too-short2") << raw("\x81\xf9\x00") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("float-too-short1") << raw("\x81\xfa") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("float-too-short2") << raw("\x81\xfa\0\0\0") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("double-too-short1") << raw("\x81\xfb") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("double-too-short2") << raw("\x81\xfb\0\0\0\0\0\0\0") << 0 << CborErrorUnexpectedEOF; - - QTest::newRow("bytearray-too-short1") << raw("\x81\x42z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-too-short2") << raw("\x81\x58\x02z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-too-short3") << raw("\x81\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-too-short4") << raw("\x81\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-too-short1") << raw("\x81\x62z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-too-short2") << raw("\x81\x78\x02z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-too-short3") << raw("\x81\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-too-short4") << raw("\x81\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short1") << raw("\x81\x5f\x42z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short2") << raw("\x81\x5f\x58\x02z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short3") << raw("\x81\x5f\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short4") << raw("\x81\x5f\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short1") << raw("\x81\x7f\x62z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short2") << raw("\x81\x7f\x78\x02z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short3") << raw("\x81\x7f\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short4") << raw("\x81\x7f\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short1x2") << raw("\x81\x5f\x40\x42z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short2x2") << raw("\x81\x5f\x40\x58\x02z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short3x2") << raw("\x81\x5f\x40\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-chunked-too-short4x2") << raw("\x81\x5f\x40\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short1x2") << raw("\x81\x7f\x60\x62z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short2x2") << raw("\x81\x7f\x60\x78\x02z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short3x2") << raw("\x81\x7f\x60\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunked-too-short4x2") << raw("\x81\x7f\x60\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF; - - QTest::newRow("bytearray-no-break1") << raw("\x81\x5f") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("bytearray-no-break2") << raw("\x81\x5f\x40") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-no-break1") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-no-break2") << raw("\x81\x7f\x60") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-no-break1") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("array-no-break2") << raw("\x81\x9f\0") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-no-break1") << raw("\x81\xbf") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-no-break2") << raw("\x81\xbf\0\0") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("map-break-after-key") << raw("\x81\xbf\0\xff") << 0 << CborErrorUnexpectedBreak; - QTest::newRow("map-break-after-second-key") << raw("\x81\xbf\x64xyzw\x04\x00\xff") << 0 << CborErrorUnexpectedBreak; - QTest::newRow("map-break-after-value-tag") << raw("\x81\xbf\0\xc0\xff") << 0 << CborErrorUnexpectedBreak; - QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak; - - // check for pointer additions wrapping over the limit of the address space - CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF; - // on 32-bit systems, this is a -1 - QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; - // on 32-bit systems, a 4GB addition could be dropped - QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; - QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; - // on 64-bit systems, this could be a -1 - QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; - QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; - - // ditto on chunks - QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; - // on 32-bit systems, a 4GB addition could be dropped - QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; - QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; - // on 64-bit systems, this could be a -1 - QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; - QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; - - QTest::newRow("eof-after-array") << raw("\x81") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-array2") << raw("\x81\x78\x20") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-array-element") << raw("\x81\x82\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-object") << raw("\x81\xa1") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-object2") << raw("\x81\xb8\x20") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-object-key") << raw("\x81\xa1\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-object-value") << raw("\x81\xa2\x01\x01") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-tag") << raw("\x81\xc0") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("eof-after-tag2") << raw("\x81\xd8\x20") << 0 << CborErrorUnexpectedEOF; - - // major type 7 has future types - QTest::newRow("future-type-28") << raw("\x81\xfc") << 0 << CborErrorUnknownType; - QTest::newRow("future-type-29") << raw("\x81\xfd") << 0 << CborErrorUnknownType; - QTest::newRow("future-type-30") << raw("\x81\xfe") << 0 << CborErrorUnknownType; - QTest::newRow("unexpected-break") << raw("\x81\xff") << 0 << CborErrorUnexpectedBreak; - QTest::newRow("illegal-simple-0") << raw("\x81\xf8\0") << 0 << CborErrorIllegalSimpleType; - QTest::newRow("illegal-simple-31") << raw("\x81\xf8\x1f") << 0 << CborErrorIllegalSimpleType; - - // not only too big (UINT_MAX or UINT_MAX+1 in size), but also incomplete - if (sizeof(size_t) < sizeof(uint64_t)) { - QTest::newRow("bytearray-too-big1") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge; - QTest::newRow("string-too-big1") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge; - } - QTest::newRow("array-too-big1") << raw("\x81\x9a\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge; - QTest::newRow("array-too-big2") << raw("\x81\x9b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge; - QTest::newRow("object-too-big1") << raw("\x81\xba\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge; - QTest::newRow("object-too-big2") << raw("\x81\xbb\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge; - - QTest::newRow("no-break-for-array0") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("no-break-for-array1") << raw("\x81\x9f\x01") << 0 << CborErrorUnexpectedEOF; - - QTest::newRow("no-break-string0") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("no-break-string1") << raw("\x81\x7f\x61Z") << 0 << CborErrorUnexpectedEOF; - - QTest::newRow("nested-indefinite-length-bytearrays") << raw("\x81\x5f\x5f\xff\xff") << 0 << CborErrorIllegalNumber; - QTest::newRow("nested-indefinite-length-strings") << raw("\x81\x7f\x7f\xff\xff") << 0 << CborErrorIllegalNumber; - - QTest::newRow("string-chunk-unsigned") << raw("\x81\x7f\0\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-negative") << raw("\x81\x7f\x20\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-bytearray") << raw("\x81\x7f\x40\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-array") << raw("\x81\x7f\x80\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-map") << raw("\x81\x7f\xa0\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-tag") << raw("\x81\x7f\xc0\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-tagged-string") << raw("\x81\x7f\xc0\x60\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-simple0") << raw("\x81\x7f\xe0\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-false") << raw("\x81\x7f\xf4\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-true") << raw("\x81\x7f\xf5\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-null") << raw("\x81\x7f\xf6\xff") << 0 << CborErrorIllegalType; - QTest::newRow("string-chunk-undefined") << raw("\x81\x7f\xf7\xff") << 0 << CborErrorIllegalType; - - QTest::newRow("bytearray-chunk-string") << raw("\x81\x5f\x60\xff") << 0 << CborErrorIllegalType; - QTest::newRow("bytearray-chunk-tagged-bytearray") << raw("\x81\x7f\xc0\x40\xff") << 0 << CborErrorIllegalType; - - // RFC 7049 Section 2.2.2 "Indefinite-Length Byte Strings and Text Strings" says - // Text strings with indefinite lengths act the same as byte strings - // with indefinite lengths, except that all their chunks MUST be - // definite-length text strings. Note that this implies that the bytes - // of a single UTF-8 character cannot be spread between chunks: a new - // chunk can only be started at a character boundary. - // This test technically tests the dumper, not the parser. - QTest::newRow("string-utf8-chunk-split") << raw("\x81\x7f\x61\xc2\x61\xa0\xff") << 0 << CborErrorInvalidUtf8TextString; -} - -void tst_Parser::validation_data() -{ - addValidationColumns(); - addValidationData(); -} - -void tst_Parser::validation() -{ - QFETCH(QByteArray, data); - QFETCH(int, flags); - QFETCH(CborError, expectedError); - - QString decoded; - ParserWrapper w; - CborError err = w.init(data, uint32_t(flags)); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - CborError err2 = cbor_value_validate_basic(&w.first); - CborError err3 = cbor_value_validate(&w.first, CborValidateBasic); - err = parseOne(&w.first, &decoded); - QCOMPARE(err, expectedError); - if (!QByteArray(QTest::currentDataTag()).contains("utf8")) { - QCOMPARE(err2, expectedError); - QCOMPARE(err3, expectedError); - } - - // see if we've got a map - if (QByteArray(QTest::currentDataTag()).startsWith("map")) { - w.init(data, uint32_t(flags)); // reinit - QVERIFY(cbor_value_is_array(&w.first)); - - CborValue map; - CborError err = cbor_value_enter_container(&w.first, &map); - if (err == CborNoError) { - QVERIFY(cbor_value_is_map(&map)); - CborValue element; - err = cbor_value_map_find_value(&map, "foobar", &element); - if (err == CborNoError) - QVERIFY(!cbor_value_is_valid(&element)); - } - - QCOMPARE(err, expectedError); - } -} - -void tst_Parser::strictValidation_data() -{ - addValidationColumns(); - - // Canonical validation - fixed types - QTest::newRow("unsigned-0") << raw("\x00") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("unsigned-24") << raw("\x18\x18") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("unsigned-256") << raw("\x19\1\0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("unsigned-65536") << raw("\x1a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("unsigned-4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("overlong-unsigned-0*1") << raw("\x18\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-0*2") << raw("\x19\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-0*4") << raw("\x1a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-24*2") << raw("\x19\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-24*4") << raw("\x1a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-24*8") << raw("\x1b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-256*4") << raw("\x1a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-256*8") << raw("\x1b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-unsigned-65536*8") << raw("\x1b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("negative-1") << raw("\x20") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("negative-25") << raw("\x38\x38") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("negative-257") << raw("\x39\1\0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("negative-65537") << raw("\x3a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("negative-4294967297") << raw("\x3b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("overlong-negative-1*1") << raw("\x38\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-1*2") << raw("\x39\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-1*4") << raw("\x3a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-25*2") << raw("\x39\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-25*4") << raw("\x3a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-25*8") << raw("\x3b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-257*4") << raw("\x3a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-257*8") << raw("\x3b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-negative-65537*8") << raw("\x3b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("simple-0") << raw("\xe0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("false") << raw("\xf4") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("true") << raw("\xf5") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("null") << raw("\xf6") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("undefined") << raw("\xf7") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("simple-32") << raw("\xf8\x20") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("fp-nan") << raw("\xf9\x7e\00") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("fp--inf") << raw("\xf9\xfc\00") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("fp-+inf") << raw("\xf9\x7c\00") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("overlong-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - - // canonical - lengths - QByteArray data24(24, 0x20); // also decodes as -1 - QByteArray data256(256, 0x40); // also decodes as h'' - QByteArray data65536(65536, 0x60);// also decodes as "" - QTest::newRow("bytearray-0") << raw("\x40") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("bytearray-24") << (raw("\x58\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("bytearray-256") << (raw("\x59\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("bytearray-65536") << (raw("\x5a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("_bytearray-0") << raw("\x5f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength; - QTest::newRow("overlong-bytearray-0*1") << raw("\x58\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-0*2") << raw("\x59\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-0*4") << raw("\x5a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-0*8") << raw("\x5b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-24*2") << (raw("\x59\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-24*4") << (raw("\x5a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-24*8") << (raw("\x5b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-256*4") << (raw("\x5a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-256*8") << (raw("\x5b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-bytearray-65536*8") << (raw("\x5b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("string-0") << raw("\x60") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("string-24") << (raw("\x78\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("string-256") << (raw("\x79\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("string-65536") << (raw("\x7a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("_string-0") << raw("\x7f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength; - QTest::newRow("overlong-string-0*1") << raw("\x78\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-0*2") << raw("\x79\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-0*4") << raw("\x7a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-0*8") << raw("\x7b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-24*2") << (raw("\x79\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-24*4") << (raw("\x7a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-24*8") << (raw("\x7b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-256*4") << (raw("\x7a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-256*8") << (raw("\x7b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-string-65536*8") << (raw("\x7b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("array-0") << raw("\x80") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("array-24") << (raw("\x98\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("array-256") << (raw("\x99\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("array-65536") << (raw("\x9a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("_array-0") << raw("\x9f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength; - QTest::newRow("overlong-array-0*1") << raw("\x98\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-0*2") << raw("\x99\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-0*4") << raw("\x9a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-0*8") << raw("\x9b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-24*2") << (raw("\x99\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-24*4") << (raw("\x9a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-24*8") << (raw("\x9b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-256*4") << (raw("\x9a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-256*8") << (raw("\x9b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-array-65536*8") << (raw("\x9b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - - // we need unique, sorted, string keys for map - // we'll make all key-value pairs a total of 4 bytes - char mapentry[] = { 0x62, 0, 0, 0x20 }; - QByteArray mapdata24(24 * sizeof(mapentry), Qt::Uninitialized); - QByteArray mapdata256(256 * sizeof(mapentry), Qt::Uninitialized); - char *mapdata24ptr = mapdata24.data(); - char *mapdata256ptr = mapdata256.data(); - for (int i = 0; i < 256; ++i) { - mapentry[1] = 'A' + (i >> 4); - mapentry[2] = 'a' + (i & 0xf); - memcpy(mapdata256ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry)); - if (i < 24) - memcpy(mapdata24ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry)); - } - QTest::newRow("map-0") << raw("\xa0") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("map-24") << (raw("\xb8\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("map-256") << (raw("\xb9\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("_map-0") << raw("\xbf\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength; - QTest::newRow("overlong-map-0*1") << raw("\xb8\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-0*2") << raw("\xb9\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-0*4") << raw("\xba\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-0*8") << raw("\xbb\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-24*2") << (raw("\xb9\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-24*4") << (raw("\xba\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-24*8") << (raw("\xbb\0\0\0\0\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-256*4") << (raw("\xba\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-map-256*8") << (raw("\xbb\0\0\0\0\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("unsorted-length-map-UU") << raw("\xa2\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-length-map-UUU") << raw("\xa3\1\1\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-length-map-SS") << raw("\xa2\x61z\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-length-map-SSS") << raw("\xa3\x61z\1\x61z\2\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-length-map-SB") << raw("\xa2\x61z\1\x40\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-length-map-AS") << raw("\xa2\x83\0\x20\x45Hello\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-content-map-SS") << raw("\xa2\x61z\1\x61y\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - QTest::newRow("unsorted-content-map-AS") << raw("\xa2\x81\x21\1\x61\x21\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted; - - QTest::newRow("tag-0") << raw("\xc0\x60") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("tag-24") << raw("\xd8\x18\x40") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError; - QTest::newRow("overlong-tag-0*1") << raw("\xd8\x00\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-0*2") << raw("\xd9\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-0*4") << raw("\xda\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-24*2") << raw("\xd9\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-24*4") << raw("\xda\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-24*8") << raw("\xdb\0\0\0\0\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-256*4") << raw("\xda\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-256*8") << raw("\xdb\0\0\0\0\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - QTest::newRow("overlong-tag-65536*8") << raw("\xdb\0\0\0\0\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding; - - // non-canonical: string length in chunked transfer - QTest::newRow("overlong-_bytearray-0*1") << raw("\x5f\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-0*2") << raw("\x5f\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-0*4") << raw("\x5f\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-0*8") << raw("\x5f\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-24*2") << (raw("\x5f\x59\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-24*4") << (raw("\x5f\x5a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-24*8") << (raw("\x5f\x5b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-256*4") << (raw("\x5f\x5a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-256*8") << (raw("\x5f\x5b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearray-65536*8") << (raw("\x5f\x5b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearrayx2-0*1") << raw("\x5f\x40\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearrayx2-0*2") << raw("\x5f\x40\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearrayx2-0*4") << raw("\x5f\x40\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_bytearrayx2-0*8") << raw("\x5f\x40\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-0*1") << raw("\x7f\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-0*2") << raw("\x7f\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-0*4") << raw("\x7f\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-0*8") << raw("\x7f\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-24*2") << (raw("\x7f\x79\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-24*4") << (raw("\x7f\x7a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-24*8") << (raw("\x7f\x7b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-256*4") << (raw("\x7f\x7a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-256*8") << (raw("\x7f\x7b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_string-65536*8") << (raw("\x7f\x7b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_stringx2-0*1") << raw("\x7f\x60\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_stringx2-0*2") << raw("\x7f\x60\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_stringx2-0*4") << raw("\x7f\x60\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - QTest::newRow("overlong-_stringx2-0*8") << raw("\x7f\x60\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding; - - // strict mode - // UTF-8 sequences with invalid continuation bytes - QTest::newRow("invalid-utf8-bad-continuation-1char") << raw("\x61\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-2chars-1") << raw("\x62\xc2\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-2chars-2") << raw("\x62\xc3\xdf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-2chars-3") << raw("\x62\xc7\xf0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-3chars-1") << raw("\x63\xe0\xa0\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-3chars-2") << raw("\x63\xe0\xc0\xa0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-4chars-1") << raw("\x64\xf0\x90\x80\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-4chars-2") << raw("\x64\xf0\x90\xc0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-bad-continuation-4chars-3") << raw("\x64\xf0\xc0\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - // Too short UTF-8 sequences (in an array so there's a byte after that would make it valid UTF-8 if it were part of the string) - QTest::newRow("invalid-utf8-too-short-2chars") << raw("\x82\x61\xc2\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-too-short-3chars-1") << raw("\x82\x61\xe0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-too-short-3chars-2") << raw("\x82\x62\xe0\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-too-short-4chars-1") << raw("\x82\x61\xf0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-too-short-4chars-2") << raw("\x82\x62\xf0\x90\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-too-short-4chars-3") << raw("\x82\x63\xf0\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - // UTF-16 surrogages encoded in UTF-8 - QTest::newRow("invalid-utf8-hi-surrogate") << raw("\x63\xed\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-lo-surrogate") << raw("\x63\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-surrogate-pair") << raw("\x66\xed\xa0\x80\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - // Non-Unicode UTF-8 sequences - QTest::newRow("invalid-utf8-non-unicode-1") << raw("\x64\xf4\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-non-unicode-2") << raw("\x65\xf8\x88\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-non-unicode-3") << raw("\x66\xfc\x84\x80\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-non-unicode-4") << raw("\x66\xfd\xbf\xbf\xbf\xbf\xbf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - // invalid bytes in UTF-8 - QTest::newRow("invalid-utf8-fe") << raw("\x61\xfe") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-ff") << raw("\x61\xff") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - // Overlong sequences - QTest::newRow("invalid-utf8-overlong-1-2") << raw("\x62\xc1\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-1-3") << raw("\x63\xe0\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-1-4") << raw("\x64\xf0\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-1-5") << raw("\x65\xf8\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-1-6") << raw("\x66\xfc\x80\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-2-3") << raw("\x63\xe0\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-2-4") << raw("\x64\xf0\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-2-5") << raw("\x65\xf8\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-2-6") << raw("\x66\xfc\x80\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-3-4") << raw("\x64\xf0\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-3-5") << raw("\x65\xf8\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-3-6") << raw("\x66\xfc\x80\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-4-5") << raw("\x65\xf8\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - QTest::newRow("invalid-utf8-overlong-4-6") << raw("\x66\xfc\x80\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString; - - QTest::newRow("nonunique-content-map-UU") << raw("\xa2\0\1\0\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique; - QTest::newRow("nonunique-content-map-SS") << raw("\xa2\x61z\1\x61z\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique; - QTest::newRow("nonunique-content-map-AA") << raw("\xa2\x81\x65Hello\1\x81\x65Hello\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique; - - QTest::newRow("tag-0-unsigned") << raw("\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-0-bytearray") << raw("\xc0\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-0-string") << raw("\xc0\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-0-tag-0-string") << raw("\xc0\xc0\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-1-unsigned") << raw("\xc1\x00") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-1-negative") << raw("\xc1\x20") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-1-bytearray") << raw("\xc1\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-2-bytearray") << raw("\xc2\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-2-string") << raw("\xc2\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-3-bytearray") << raw("\xc3\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-3-string") << raw("\xc3\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-4-string") << raw("\xc4\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-4-array") << raw("\xc4\x82\0\1") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-5-string") << raw("\xc5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-5-array") << raw("\xc5\x82\0\1") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-21-bytearray") << raw("\xd5\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-21-string") << raw("\xd5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-21-array") << raw("\xd5\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-21-map") << raw("\xd5\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-22-bytearray") << raw("\xd6\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-22-string") << raw("\xd6\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-22-array") << raw("\xd6\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-22-map") << raw("\xd6\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-23-bytearray") << raw("\xd7\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-23-string") << raw("\xd7\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-23-array") << raw("\xd7\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-23-map") << raw("\xd7\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-24-bytearray") << raw("\xd8\x18\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-24-string") << raw("\xd8\x18\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-32-bytearray") << raw("\xd8\x20\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-32-string") << raw("\xd8\x20\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-33-bytearray") << raw("\xd8\x21\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-33-string") << raw("\xd8\x21\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-34-bytearray") << raw("\xd8\x22\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-34-string") << raw("\xd8\x22\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-35-bytearray") << raw("\xd8\x23\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-35-string") << raw("\xd8\x23\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-36-bytearray") << raw("\xd8\x24\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-36-string") << raw("\xd8\x24\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-unsigned") << raw("\xd9\xd9\xf7\x00") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-negative") << raw("\xd9\xd9\xf7\x20") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-bytearray") << raw("\xd9\xd9\xf7\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-string") << raw("\xd9\xd9\xf7\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-array") << raw("\xd9\xd9\xf7\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-map") << raw("\xd9\xd9\xf7\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-tag-0-unsigned") << raw("\xd9\xd9\xf7\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-55799-tag-0-string") << raw("\xd9\xd9\xf7\xc0\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-simple0") << raw("\xd9\xd9\xf7\xe0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-false") << raw("\xd9\xd9\xf7\xf4") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-true") << raw("\xd9\xd9\xf7\xf5") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-null") << raw("\xd9\xd9\xf7\xf6") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-undefined") << raw("\xd9\xd9\xf7\xf7") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-simple32") << raw("\xd9\xd9\xf7\xf8\x20") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-half") << raw("\xd9\xd9\xf7\xf9\0\0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-float") << raw("\xd9\xd9\xf7\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-double") << raw("\xd9\xd9\xf7\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError; - - // excluded non-finite - QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - - // excluded undefined - QTest::newRow("no-undefined") << raw("\xf7") << int(CborValidateNoUndefined) << CborErrorExcludedType; - - // exclude non-finite - QTest::newRow("excluded-fp-nan_f16") << raw("\xf9\x7e\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp--inf_f16") << raw("\xf9\xfc\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-+inf_f16") << raw("\xf9\x7c\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue; - - // exclude non-string keys in maps - QTest::newRow("excluded-map-unsigned") << raw("\xa1\x00\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-negative") << raw("\xa1\x20\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-bytearray") << raw("\xa1\x40\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("map-string") << raw("\xa1\x60\1") << int(CborValidateMapKeysAreString) << CborNoError; - QTest::newRow("map-tag-0-string") << raw("\xa1\xc0\x60\1") << int(CborValidateMapKeysAreString) << CborNoError; - QTest::newRow("excluded-map-array") << raw("\xa1\x80\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-map") << raw("\xa1\xa0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-simple-0") << raw("\xa1\xe0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-false") << raw("\xa1\xf4\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-true") << raw("\xa1\xf5\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-null") << raw("\xa1\xf6\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-undefined") << raw("\xa1\xf7\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-half") << raw("\xa1\xf9\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-float") << raw("\xa1\xfa\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - QTest::newRow("excluded-map-double") << raw("\xa1\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString; - - // unknown simple types - QTest::newRow("unknown-simple-type-0") << raw("\xe0") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType; - QTest::newRow("unknown-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType; - QTest::newRow("allowed-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypesSA) << CborNoError; - - // unknown tags - QTest::newRow("unknown-tag-6") << raw("\xc6\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag; - QTest::newRow("unknown-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag; - QTest::newRow("unknown-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag; - QTest::newRow("unknown-tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag; - QTest::newRow("unknown-tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag; - QTest::newRow("allowed-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTagsSA) << CborNoError; - QTest::newRow("allowed-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTagsSR) << CborNoError; - - // excluded tags - QTest::newRow("excluded-tag-0") << raw("\xc0\x60") << int(CborValidateNoTags) << CborErrorExcludedType; - QTest::newRow("excluded-tag-24") << raw("\xd8\x18\x40") << int(CborValidateNoTags) << CborErrorExcludedType; - QTest::newRow("excluded-tag-55799") << raw("\xd9\xd9\xf7\x60") << int(CborValidateNoTags) << CborErrorExcludedType; - - // complete data - QTest::newRow("garbage-data-0") << raw("\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-1") << raw("\x20\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-2") << raw("\x40\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-3") << raw("\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-4") << raw("\x80\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-5") << raw("\xa0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-6") << raw("\xc0\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-7") << raw("\xf4\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-f16") << raw("\xf9\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-f32") << raw("\xfa\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; - QTest::newRow("garbage-data-f64") << raw("\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd; -} - -void tst_Parser::strictValidation() -{ - QFETCH(QByteArray, data); - QFETCH(int, flags); - QFETCH(CborError, expectedError); - - QString decoded; - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - err = cbor_value_validate(&w.first, flags); - QCOMPARE(err, expectedError); -} - -void tst_Parser::resumeParsing_data() -{ - addColumns(); - addFixedData(); - addStringsData(); - addTagsData(); - addMapMixedData(); -} - -void tst_Parser::resumeParsing() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - for (int len = 0; len < data.length() - 1; ++len) { - ParserWrapper w; - CborError err = w.init(data.constData(), len); - if (!err) { - QString decoded; - err = parseOne(&w.first, &decoded); - } - if (err != CborErrorUnexpectedEOF) - qDebug() << "Length is" << len; - QCOMPARE(err, CborErrorUnexpectedEOF); - } -} - -void tst_Parser::endPointer_data() -{ - QTest::addColumn("data"); - QTest::addColumn("offset"); - - QTest::newRow("number1") << raw("\x81\x01\x01") << 2; - QTest::newRow("number24") << raw("\x81\x18\x18\x01") << 3; - QTest::newRow("string") << raw("\x81\x61Z\x01") << 3; - QTest::newRow("indefinite-string") << raw("\x81\x7f\x61Z\xff\x01") << 5; - QTest::newRow("array") << raw("\x81\x02\x01") << 2; - QTest::newRow("indefinite-array") << raw("\x81\x9f\x02\xff\x01") << 4; - QTest::newRow("object") << raw("\x81\xa1\x03\x02\x01") << 4; - QTest::newRow("indefinite-object") << raw("\x81\xbf\x03\x02\xff\x01") << 5; -} - -void tst_Parser::endPointer() -{ - QFETCH(QByteArray, data); - QFETCH(int, offset); - - QString decoded; - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - err = parseOne(&w.first, &decoded); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - QCOMPARE(int(cbor_value_get_next_byte(&w.first) - w.begin()), offset); -} - -void tst_Parser::recursionLimit_data() -{ - static const int recursions = CBOR_PARSER_MAX_RECURSIONS + 2; - QTest::addColumn("data"); - - QTest::newRow("array") << QByteArray(recursions, '\x81') + '\x20'; - QTest::newRow("_array") << QByteArray(recursions, '\x9f') + '\x20' + QByteArray(recursions, '\xff'); - - QByteArray data; - for (int i = 0; i < recursions; ++i) - data += "\xa1\x65Hello"; - data += '\2'; - QTest::newRow("map-recursive-values") << data; - - data.clear(); - for (int i = 0; i < recursions; ++i) - data += "\xbf\x65World"; - data += '\2'; - for (int i = 0; i < recursions; ++i) - data += "\xff"; - QTest::newRow("_map-recursive-values") << data; - - data = QByteArray(recursions, '\xa1'); - data += '\2'; - for (int i = 0; i < recursions; ++i) - data += "\x7f\x64quux\xff"; - QTest::newRow("map-recursive-keys") << data; - - data = QByteArray(recursions, '\xbf'); - data += '\2'; - for (int i = 0; i < recursions; ++i) - data += "\1\xff"; - QTest::newRow("_map-recursive-keys") << data; - - data.clear(); - for (int i = 0; i < recursions / 2; ++i) - data += "\x81\xa1\1"; - data += '\2'; - QTest::newRow("mixed") << data; -} - -void tst_Parser::recursionLimit() -{ - QFETCH(QByteArray, data); - - ParserWrapper w; - CborError err = w.init(data); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - - // check that it is valid: - CborValue it = w.first; - { - QString dummy; - err = parseOne(&it, &dummy); - QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\""); - } - - it = w.first; - err = cbor_value_advance(&it); - QCOMPARE(err, CborErrorNestingTooDeep); - - it = w.first; - if (cbor_value_is_map(&it)) { - CborValue dummy; - err = cbor_value_map_find_value(&it, "foo", &dummy); - QCOMPARE(err, CborErrorNestingTooDeep); - } -} - -QTEST_MAIN(tst_Parser) -#include "tst_parser.moc" diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tests.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tests.pro deleted file mode 100644 index 6036f0f..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tests.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = parser encoder c90 cpp tojson -msvc: SUBDIRS -= tojson diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tojson.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tojson.pro deleted file mode 100644 index b422652..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tojson.pro +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG += testcase parallel_test c++11 -QT = core testlib - -SOURCES += tst_tojson.cpp -INCLUDEPATH += ../../src -msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib -else: POST_TARGETDEPS += ../../lib/libtinycbor.a -LIBS += $$POST_TARGETDEPS diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tst_tojson.cpp b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tst_tojson.cpp deleted file mode 100644 index 8bf24ef..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tests/tojson/tst_tojson.cpp +++ /dev/null @@ -1,721 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include -#include "cbor.h" -#include "cborjson.h" -#include - -extern "C" FILE *open_memstream(char **bufptr, size_t *sizeptr); - -class tst_ToJson : public QObject -{ - Q_OBJECT -private slots: - void initTestCase(); - - void fixed_data(); - void fixed(); - void textstrings_data(); - void textstrings() { fixed(); } - void nonjson_data(); - void nonjson() { fixed(); } - void bytestrings_data(); - void bytestrings() { fixed(); } - void emptyContainers_data(); - void emptyContainers() { fixed(); } - void arrays_data(); - void arrays(); - void nestedArrays_data() { arrays_data(); } - void nestedArrays(); - void maps_data() { arrays_data(); } - void maps(); - void nestedMaps_data() { maps_data(); } - void nestedMaps(); - void nonStringKeyMaps_data(); - void nonStringKeyMaps(); - - void tagsToObjects_data(); - void tagsToObjects(); - void taggedByteStringsToBase16_data(); - void taggedByteStringsToBase16(); - void taggedByteStringsToBase64_data() { taggedByteStringsToBase16_data(); } - void taggedByteStringsToBase64(); - void taggedByteStringsToBigNum_data() { taggedByteStringsToBase16_data(); } - void taggedByteStringsToBigNum(); - void otherTags_data(); - void otherTags(); - - void metaData_data(); - void metaData(); - void metaDataAndTagsToObjects_data() { tagsToObjects_data(); } - void metaDataAndTagsToObjects(); - void metaDataForKeys_data(); - void metaDataForKeys(); -}; -#include "tst_tojson.moc" - -template QByteArray raw(const char (&data)[N]) -{ - return QByteArray::fromRawData(data, N - 1); -} - -void addColumns() -{ - QTest::addColumn("data"); - QTest::addColumn("expected"); -} - -void addFixedData() -{ - // unsigned integers - QTest::newRow("0") << raw("\x00") << "0"; - QTest::newRow("1") << raw("\x01") << "1"; - QTest::newRow("2^53-1") << raw("\x1b\0\x1f\xff\xff""\xff\xff\xff\xff") << "9007199254740991"; - QTest::newRow("2^64-epsilon") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "18446744073709549568"; - - // negative integers - QTest::newRow("-1") << raw("\x20") << "-1"; - QTest::newRow("-2") << raw("\x21") << "-2"; - QTest::newRow("-2^53+1") << raw("\x3b\0\x1f\xff\xff""\xff\xff\xff\xfe") << "-9007199254740991"; - QTest::newRow("-2^64+epsilon") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "-18446744073709549568"; - - QTest::newRow("false") << raw("\xf4") << "false"; - QTest::newRow("true") << raw("\xf5") << "true"; - QTest::newRow("null") << raw("\xf6") << "null"; - - QTest::newRow("0.f16") << raw("\xf9\0\0") << "0"; - QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "0"; - QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << "0"; - QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "-1"; - QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "-1"; - QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "-1"; - QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "16777215"; - QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "16777215"; - QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "-16777215"; - QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "-16777215"; - - QTest::newRow("0.5f16") << raw("\xf9\x38\0") << "0.5"; - QTest::newRow("0.5f") << raw("\xfa\x3f\0\0\0") << "0.5"; - QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << "0.5"; - QTest::newRow("2.f^24-1") << raw("\xfa\x4b\x7f\xff\xff") << "16777215"; - QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "9007199254740991"; - QTest::newRow("2.f^64-epsilon") << raw("\xfa\x5f\x7f\xff\xff") << "18446742974197923840"; - QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "18446744073709549568"; - QTest::newRow("2.f^64") << raw("\xfa\x5f\x80\0\0") << "1.8446744073709552e+19"; - QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << "1.8446744073709552e+19"; - - // infinities and NaN are not supported in JSON, they convert to null - QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "null"; - QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "null"; - QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "null"; - QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "null"; - QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "null"; - QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "null"; - QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "null"; - QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "null"; - QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "null"; -} - -void addTextStringsData() -{ - QTest::newRow("emptytextstring") << raw("\x60") << "\"\""; - QTest::newRow("textstring1") << raw("\x61 ") << "\" \""; - QTest::newRow("textstring5") << raw("\x65Hello") << "\"Hello\""; - QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") - << "\"123456789012345678901234\""; - QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') - << '"' + QString(256, '3') + '"'; - - // strings with undefined length - QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "\"\""; - QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "\"\""; - QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "\"\""; - QTest::newRow("_textstring5*2") << raw("\x7f\x63Hel\x62lo\xff") << "\"Hello\""; - QTest::newRow("_textstring5*5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "\"Hello\""; - QTest::newRow("_textstring5*6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << "\"Hello\""; -} - -void addNonJsonData() -{ - QTest::newRow("undefined") << raw("\xf7") << "\"undefined\""; - QTest::newRow("simple0") << raw("\xe0") << "\"simple(0)\""; - QTest::newRow("simple19") << raw("\xf3") << "\"simple(19)\""; - QTest::newRow("simple32") << raw("\xf8\x20") << "\"simple(32)\""; - QTest::newRow("simple255") << raw("\xf8\xff") << "\"simple(255)\""; -} - -void addByteStringsData() -{ - QTest::newRow("emptybytestring") << raw("\x40") << "\"\""; - QTest::newRow("bytestring1") << raw("\x41 ") << "\"IA\""; - QTest::newRow("bytestring1-nul") << raw("\x41\0") << "\"AA\""; - QTest::newRow("bytestring2") << raw("\x42Hi") << "\"SGk\""; - QTest::newRow("bytestring3") << raw("\x43Hey") << "\"SGV5\""; - QTest::newRow("bytestring4") << raw("\x44Hola") << "\"SG9sYQ\""; - QTest::newRow("bytestring5") << raw("\x45Hello") << "\"SGVsbG8\""; - QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") - << "\"MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0\""; - - // strings with undefined length - QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "\"\""; - QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "\"\""; - QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "\"\""; - QTest::newRow("_bytestring5*2") << raw("\x5f\x43Hel\x42lo\xff") << "\"SGVsbG8\""; - QTest::newRow("_bytestring5*5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << "\"SGVsbG8\""; - QTest::newRow("_bytestring5*6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << "\"SGVsbG8\""; -} - -void addEmptyContainersData() -{ - QTest::newRow("emptyarray") << raw("\x80") << "[]"; - QTest::newRow("emptymap") << raw("\xa0") << "{}"; - QTest::newRow("_emptyarray") << raw("\x9f\xff") << "[]"; - QTest::newRow("_emptymap") << raw("\xbf\xff") << "{}"; -} - -CborError parseOne(CborValue *it, QString *parsed, int flags) -{ - char *buffer; - size_t size; - - FILE *f = open_memstream(&buffer, &size); - CborError err = cbor_value_to_json_advance(f, it, flags); - fclose(f); - - *parsed = QString::fromLatin1(buffer); - free(buffer); - return err; -} - -bool compareFailed = true; -void compareOne_real(const QByteArray &data, const QString &expected, int flags, int line) -{ - compareFailed = true; - CborParser parser; - CborValue first; - CborError err = cbor_parser_init(reinterpret_cast(data.constData()), data.length(), 0, &parser, &first); - QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\""); - - QString decoded; - err = parseOne(&first, &decoded, flags); - QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + - "\"; decoded stream:\n" + decoded.toLatin1()); - QCOMPARE(decoded, expected); - - // check that we consumed everything - QCOMPARE((void*)first.ptr, (void*)data.constEnd()); - - compareFailed = false; -} -#define compareOne(data, expected, flags) \ - compareOne_real(data, expected, flags, __LINE__); \ - if (compareFailed) return - -void tst_ToJson::initTestCase() -{ - setlocale(LC_ALL, "C"); -} - -void tst_ToJson::fixed_data() -{ - addColumns(); - addFixedData(); -} - -void tst_ToJson::fixed() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne(data, expected, 0); -} - -void tst_ToJson::textstrings_data() -{ - addColumns(); - addTextStringsData(); -} - -void tst_ToJson::nonjson_data() -{ - addColumns(); - addNonJsonData(); -} - -void tst_ToJson::bytestrings_data() -{ - addColumns(); - addByteStringsData(); -} - -void tst_ToJson::emptyContainers_data() -{ - addColumns(); - addEmptyContainersData(); -} - -void tst_ToJson::arrays_data() -{ - addColumns(); - addFixedData(); - addTextStringsData(); - addNonJsonData(); - addByteStringsData(); -} - -void tst_ToJson::arrays() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne("\x81" + data, '[' + expected + ']', 0); - compareOne("\x82" + data + data, '[' + expected + ',' + expected + ']', 0); -} - -void tst_ToJson::nestedArrays() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne("\x81\x81" + data, "[[" + expected + "]]", 0); - compareOne("\x81\x81\x81" + data, "[[[" + expected + "]]]", 0); - compareOne("\x81\x82" + data + data, "[[" + expected + ',' + expected + "]]", 0); - compareOne("\x82\x81" + data + data, "[[" + expected + "]," + expected + "]", 0); - compareOne("\x82\x81" + data + '\x81' + data, "[[" + expected + "],[" + expected + "]]", 0); -} - -void tst_ToJson::maps() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne("\xa1\x65" "Hello" + data, "{\"Hello\":" + expected + '}', 0); -} - -void tst_ToJson::nestedMaps() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne("\xa1\x65Hello\xa1\x65World" + data, "{\"Hello\":{\"World\":" + expected + "}}", 0); -// compareOne("\xa1\x63""foo\xa1\63""bar" + data + "\63""baz\xa1\x64quux" + data, -// "{\"foo\":{\"bar\":" + expected + "},\"baz\":{\"quux\":" + expected + "}", 0); -} - -void tst_ToJson::nonStringKeyMaps_data() -{ - addColumns(); - - QTest::newRow("0") << raw("\x00") << "0"; - QTest::newRow("1") << raw("\x01") << "1"; - QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << "4294967295"; - QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << "4294967296"; - QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << QString::number(std::numeric_limits::max()); - - QTest::newRow("-1") << raw("\x20") << "-1"; - QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << "-4294967296"; - QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << "-4294967297"; - QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe") - << '-' + QString::number(std::numeric_limits::max()); - QTest::newRow("-UINT64_MAX-1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") - << "-18446744073709551616"; - - QTest::newRow("simple0") << raw("\xe0") << "simple(0)"; - QTest::newRow("simple19") << raw("\xf3") << "simple(19)"; - QTest::newRow("false") << raw("\xf4") << "false"; - QTest::newRow("true") << raw("\xf5") << "true"; - QTest::newRow("null") << raw("\xf6") << "null"; - QTest::newRow("undefined") << raw("\xf7") << "undefined"; - QTest::newRow("simple32") << raw("\xf8\x20") << "simple(32)"; - QTest::newRow("simple255") << raw("\xf8\xff") << "simple(255)"; - - QTest::newRow("0.f16") << raw("\xf9\0\0") << "0.f16"; - QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "0.f"; - QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << "0."; - QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "-1.f16"; - QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "-1.f"; - QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "-1."; - QTest::newRow("65504.f16") << raw("\xf9\x7b\xff") << "65504.f16"; - QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f"; - QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "16777215."; - QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "-16777215.f"; - QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "-16777215."; - - QTest::newRow("0.5f16") << raw("\xf9\x38\0") << "0.5f16"; - QTest::newRow("0.5f") << raw("\xfa\x3f\0\0\0") << "0.5f"; - QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << "0.5"; - QTest::newRow("2.f16^11-1") << raw("\xf9\x67\xff") << "2047.f16"; - QTest::newRow("2.f^24-1") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f"; - QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "9007199254740991."; - QTest::newRow("2.f^64-epsilon") << raw("\xfa\x5f\x7f\xff\xff") << "18446742974197923840.f"; - QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "18446744073709549568."; - QTest::newRow("2.f^64") << raw("\xfa\x5f\x80\0\0") << "1.8446744073709552e+19f"; - QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << "1.8446744073709552e+19"; - - QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "nan"; - QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "nan"; - QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "nan"; - QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "-inf"; - QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "-inf"; - QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "-inf"; - QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "inf"; - QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "inf"; - QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "inf"; - - QTest::newRow("emptybytestring") << raw("\x40") << "h''"; - QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'"; - QTest::newRow("bytestring1-nul") << raw("\x41\0") << "h'00'"; - QTest::newRow("bytestring5") << raw("\x45Hello") << "h'48656c6c6f'"; - QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") - << "h'313233343536373839303132333435363738393031323334'"; - - QTest::newRow("tag0") << raw("\xc0\x00") << "0(0)"; - QTest::newRow("tag1") << raw("\xc1\x00") << "1(0)"; - QTest::newRow("tag24") << raw("\xd8\x18\x00") << "24(0)"; - QTest::newRow("tagUINT64_MAX") << raw("\xdb" "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00") - << QString::number(std::numeric_limits::max()) + "(0)"; - - QTest::newRow("emptyarray") << raw("\x80") << "[]"; - QTest::newRow("emptymap") << raw("\xa0") << "{}"; - QTest::newRow("_emptyarray") << raw("\x9f\xff") << "[_ ]"; - QTest::newRow("_emptymap") << raw("\xbf\xff") << "{_ }"; - - QTest::newRow("map-0-24") << raw("\xa1\0\x18\x18") << "{0: 24}"; - QTest::newRow("map-24-0") << raw("\xa1\x18\x18\0") << "{24: 0}"; - QTest::newRow("_map-0-24") << raw("\xbf\0\x18\x18\xff") << "{_ 0: 24}"; - QTest::newRow("_map-24-0") << raw("\xbf\x18\x18\0\xff") << "{_ 24: 0}"; -} - -void tst_ToJson::nonStringKeyMaps() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - data = "\xa1" + data + "\1"; - compareOne(data, "{\"" + expected + "\":1}", CborConvertStringifyMapKeys); - - // and verify that they fail if we use CborConvertRequireMapStringKeys - CborParser parser; - CborValue first; - QString decoded; - cbor_parser_init(reinterpret_cast(data.constData()), data.length(), 0, &parser, &first); - CborError err = parseOne(&first, &decoded, CborConvertRequireMapStringKeys); - QCOMPARE(err, CborErrorJsonObjectKeyNotString); -} - -void tst_ToJson::tagsToObjects_data() -{ - addColumns(); - QTest::newRow("0(0)") << raw("\xc0\0") << "{\"tag0\":0}"; - QTest::newRow("0(-1)") << raw("\xc0\x20") << "{\"tag0\":-1}"; - QTest::newRow("0(\"hello\")") << raw("\xc0\x65hello") << "{\"tag0\":\"hello\"}"; - QTest::newRow("22(h'48656c6c6f')") << raw("\xd6\x45Hello") << "{\"tag22\":\"SGVsbG8\"}"; - QTest::newRow("0([1,2,3])") << raw("\xc0\x83\1\2\3") << "{\"tag0\":[1,2,3]}"; - QTest::newRow("0({\"z\":true,\"y\":1})") << raw("\xc0\xa2\x61z\xf5\x61y\1") << "{\"tag0\":{\"z\":true,\"y\":1}}"; - - // large tags - QTest::newRow("55799(0)") << raw("\xd9\xd9\xf7\0") << "{\"tag55799\":0}"; - QTest::newRow("4294967295") << raw("\xda\xff\xff\xff\xff\0") << "{\"tag4294967295\":0}"; - QTest::newRow("18446744073709551615(0)") << raw("\xdb\xff\xff\xff\xff""\xff\xff\xff\xff\0") - << "{\"tag18446744073709551615\":0}"; - - // nested tags - QTest::newRow("0(1(2))") << raw("\xc0\xc1\2") << "{\"tag0\":{\"tag1\":2}}"; - QTest::newRow("0({\"z\":1(2)})") << raw("\xc0\xa1\x61z\xc1\2") << "{\"tag0\":{\"z\":{\"tag1\":2}}}"; -} - -void tst_ToJson::tagsToObjects() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - compareOne(data, expected, CborConvertTagsToObjects); -} - -void tst_ToJson::taggedByteStringsToBase16_data() -{ - QTest::addColumn("data"); - QTest::addColumn("base64url"); - QTest::addColumn("base64"); - QTest::addColumn("base16"); - - QTest::newRow("emptybytestring") << raw("\x40") << "" << "" << ""; - QTest::newRow("bytestring1") << raw("\x41 ") << "IA" << "IA==" << "20"; - QTest::newRow("bytestring1-nul") << raw("\x41\0") << "AA" << "AA==" << "00"; - QTest::newRow("bytestring1-ff") << raw("\x41\xff") << "_w" << "/w==" << "ff"; - QTest::newRow("bytestring2") << raw("\x42Hi") << "SGk" << "SGk=" << "4869"; - QTest::newRow("bytestring3") << raw("\x43Hey") << "SGV5" << "SGV5" << "486579"; - QTest::newRow("bytestring4") << raw("\x44Hola") << "SG9sYQ" << "SG9sYQ==" << "486f6c61"; - QTest::newRow("bytestring5") << raw("\x45Hello") << "SGVsbG8" << "SGVsbG8=" << "48656c6c6f"; - QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") - << "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0" - << "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0" - << "313233343536373839303132333435363738393031323334"; - - // strings with undefined length - QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "" << "" << ""; - QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "" << "" << ""; - QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "" << "" << ""; - QTest::newRow("_bytestring5*2") << raw("\x5f\x43Hel\x42lo\xff") << "SGVsbG8" << "SGVsbG8=" << "48656c6c6f"; - QTest::newRow("_bytestring5*5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") - << "SGVsbG8" << "SGVsbG8=" << "48656c6c6f"; - QTest::newRow("_bytestring5*6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") - << "SGVsbG8" << "SGVsbG8=" << "48656c6c6f"; -} - -void tst_ToJson::taggedByteStringsToBase16() -{ - QFETCH(QByteArray, data); - QFETCH(QString, base16); - - compareOne('\xd7' + data, '"' + base16 + '"', 0); -} - -void tst_ToJson::taggedByteStringsToBase64() -{ - QFETCH(QByteArray, data); - QFETCH(QString, base64); - - compareOne('\xd6' + data, '"' + base64 + '"', 0); -} - -void tst_ToJson::taggedByteStringsToBigNum() -{ - QFETCH(QByteArray, data); - QFETCH(QString, base64url); - - compareOne('\xc3' + data, "\"~" + base64url + '"', 0); -} - -void tst_ToJson::otherTags_data() -{ - addColumns(); - addFixedData(); - addTextStringsData(); - addNonJsonData(); - addByteStringsData(); - addEmptyContainersData(); -} - -void tst_ToJson::otherTags() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - - // other tags produce no change in output - compareOne("\xc0" + data, expected, 0); - compareOne("\xc1" + data, expected, 0); - compareOne("\xc2" + data, expected, 0); - compareOne("\xc4" + data, expected, 0); - compareOne("\xc5" + data, expected, 0); - compareOne("\xd8\x20" + data, expected, 0); - compareOne("\xd8\x21" + data, expected, 0); - compareOne("\xd8\x22" + data, expected, 0); - compareOne("\xd8\x23" + data, expected, 0); - compareOne("\xd8\x24" + data, expected, 0); - compareOne("\xd9\xd9\xf7" + data, expected, 0); -} - -void tst_ToJson::metaData_data() -{ - addColumns(); - - // booleans, null, strings, double precision numbers, regular maps, arrays and integers that - // didn't get rounded don't have metadata - QTest::newRow("0") << raw("\x00") << QString(); - QTest::newRow("1") << raw("\x01") << QString(); - QTest::newRow("2^53-1") << raw("\x1b\0\x1f\xff\xff""\xff\xff\xff\xff") << QString(); - QTest::newRow("2^64-epsilon") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\x00") << QString(); - QTest::newRow("-1") << raw("\x20") << QString(); - QTest::newRow("-2") << raw("\x21") << QString(); - QTest::newRow("-2^53+1") << raw("\x3b\0\x1f\xff\xff""\xff\xff\xff\xfe") << QString(); - QTest::newRow("-2^64+epsilon") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf8\x00") << QString(); - QTest::newRow("emptytextstring") << raw("\x60") << QString(); - QTest::newRow("textstring1") << raw("\x61 ") << QString(); - QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << QString(); - QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << QString(); - QTest::newRow("false") << raw("\xf4") << QString(); - QTest::newRow("true") << raw("\xf5") << QString(); - QTest::newRow("null") << raw("\xf6") << QString(); - QTest::newRow("emptyarray") << raw("\x80") << QString(); - QTest::newRow("emptymap") << raw("\xa0") << QString(); - QTest::newRow("array*1") << raw("\x81\xf6") << QString(); - QTest::newRow("map*1") << raw("\xa1\x61z\xf4") << QString(); - - // ---- everything from here on has at least the type ---- - QTest::newRow("emptybytestring") << raw("\x40") << "\"t\":64"; - QTest::newRow("bytestring1") << raw("\x41 ") << "\"t\":64"; - QTest::newRow("undefined") << raw("\xf7") << "\"t\":247"; - QTest::newRow("0.f16") << raw("\xf9\0\0") << "\"t\":249"; - QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "\"t\":249"; - QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "\"t\":250"; - QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "\"t\":250"; - QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "\"t\":250"; - QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "\"t\":250"; - QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << "\"t\":251"; - QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "\"t\":251"; - QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "\"t\":251"; - QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "\"t\":251"; - QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "\"t\":251"; - QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "\"t\":251"; - - // integers that are too precise for double - QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1") - << "\"t\":0,\"v\":\"+20000000000001\""; - QTest::newRow("INT64_MAX-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xfe") - << "\"t\":0,\"v\":\"+7ffffffffffffffe\""; - QTest::newRow("INT64_MAX+1") << raw("\x1b\x80\0\0\0""\0\0\0\1") - << "\"t\":0,\"v\":\"+8000000000000001\""; - QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0") - << "\"t\":0,\"v\":\"-20000000000000\""; - - // simple values - QTest::newRow("simple0") << raw("\xe0") << "\"t\":224,\"v\":0"; - QTest::newRow("simple19") << raw("\xf3") << "\"t\":224,\"v\":19"; - QTest::newRow("simple32") << raw("\xf8\x20") << "\"t\":224,\"v\":32"; - QTest::newRow("simple255") << raw("\xf8\xff") << "\"t\":224,\"v\":255"; - - // infinities and NaN are not supported in JSON, they convert to null - QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "\"t\":249,\"v\":\"nan\""; - QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "\"t\":250,\"v\":\"nan\""; - QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "\"t\":251,\"v\":\"nan\""; - QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "\"t\":249,\"v\":\"-inf\""; - QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "\"t\":250,\"v\":\"-inf\""; - QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "\"t\":251,\"v\":\"-inf\""; - QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "\"t\":249,\"v\":\"inf\""; - QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "\"t\":250,\"v\":\"inf\""; - QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "\"t\":251,\"v\":\"inf\""; - - // tags on native types - QTest::newRow("tag+0") << raw("\xc0\x00") << "\"tag\":\"0\""; - QTest::newRow("tag+-2") << raw("\xc0\x21") << "\"tag\":\"0\""; - QTest::newRow("tag+0.5") << raw("\xc0\xfb\x3f\xe0\0\0\0\0\0\0") << "\"tag\":\"0\""; - QTest::newRow("tag+emptytextstring") << raw("\xc0\x60") << "\"tag\":\"0\""; - QTest::newRow("tag+textstring1") << raw("\xc0\x61 ") << "\"tag\":\"0\""; - QTest::newRow("tag+false") << raw("\xc0\xf4") << "\"tag\":\"0\""; - QTest::newRow("tag+true") << raw("\xc0\xf5") << "\"tag\":\"0\""; - QTest::newRow("tag+null") << raw("\xc0\xf6") << "\"tag\":\"0\""; - QTest::newRow("tag+emptyarray") << raw("\xc0\x80") << "\"tag\":\"0\""; - QTest::newRow("tag+emptymap") << raw("\xc0\xa0") << "\"tag\":\"0\""; - QTest::newRow("tag+array*1") << raw("\xc0\x81\xf6") << "\"tag\":\"0\""; - QTest::newRow("tag+map*1") << raw("\xc0\xa1\x61z\xf4") << "\"tag\":\"0\""; - - // tags on non-native types - QTest::newRow("tag+emptybytestring") << raw("\xc0\x40") << "\"tag\":\"0\",\"t\":64"; - QTest::newRow("tag+bytestring1") << raw("\xc0\x41 ") << "\"tag\":\"0\",\"t\":64"; - QTest::newRow("tag+undefined") << raw("\xc0\xf7") << "\"tag\":\"0\",\"t\":247"; - QTest::newRow("tag+0.f") << raw("\xc0\xfa\0\0\0\0") << "\"tag\":\"0\",\"t\":250"; - QTest::newRow("tag+-1.f") << raw("\xc0\xfa\xbf\x80\0\0") << "\"tag\":\"0\",\"t\":250"; - QTest::newRow("tag+16777215.f") << raw("\xc0\xfa\x4b\x7f\xff\xff") << "\"tag\":\"0\",\"t\":250"; - QTest::newRow("tag+-16777215.f") << raw("\xc0\xfa\xcb\x7f\xff\xff") << "\"tag\":\"0\",\"t\":250"; - QTest::newRow("tag+0.") << raw("\xc0\xfb\0\0\0\0\0\0\0\0") << "\"tag\":\"0\",\"t\":251"; - QTest::newRow("tag+-1.") << raw("\xc0\xfb\xbf\xf0\0\0\0\0\0\0") << "\"tag\":\"0\",\"t\":251"; - QTest::newRow("tag+16777215.") << raw("\xc0\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "\"tag\":\"0\",\"t\":251"; - QTest::newRow("tag+-16777215.") << raw("\xc0\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "\"tag\":\"0\",\"t\":251"; - - // big tags (don't fit in JS numbers) - QTest::newRow("bigtag1") << raw("\xdb\0\x20\0\0""\0\0\0\1\x60") << "\"tag\":\"9007199254740993\""; - QTest::newRow("bigtag2") << raw("\xdb\xff\xff\xff\xff""\xff\xff\xff\xfe\x60") - << "\"tag\":\"18446744073709551614\""; - - // specially-handled tags - QTest::newRow("negativebignum") << raw("\xc3\x41 ") << "\"tag\":\"3\",\"t\":64"; - QTest::newRow("base64") << raw("\xd6\x41 ") << "\"tag\":\"22\",\"t\":64"; - QTest::newRow("base16") << raw("\xd7\x41 ") << "\"tag\":\"23\",\"t\":64"; -} - -void compareMetaData(QByteArray data, const QString &expected, int otherFlags = 0) -{ - QString decoded; - - // needs to be in one map, with the entry called "v" - data = "\xa1\x61v" + data; - - { - CborParser parser; - CborValue first; - CborError err = cbor_parser_init(reinterpret_cast(data.constData()), data.length(), 0, &parser, &first); - QVERIFY2(!err, QByteArrayLiteral(": Got error \"") + cbor_error_string(err) + "\""); - - err = parseOne(&first, &decoded, CborConvertAddMetadata | otherFlags); - QVERIFY2(!err, QByteArrayLiteral(": Got error \"") + cbor_error_string(err) + - "\"; decoded stream:\n" + decoded.toLatin1()); - - // check that we consumed everything - QCOMPARE((void*)first.ptr, (void*)data.constEnd()); - } - - QVERIFY(decoded.startsWith("{\"v\":")); - QVERIFY(decoded.endsWith('}')); -// qDebug() << "was" << decoded; - - // extract just the metadata - static const char needle[] = "\"v$cbor\":{"; - int pos = decoded.indexOf(needle); - QCOMPARE(pos == -1, expected.isEmpty()); - if (pos != -1) { - decoded.chop(2); - decoded = std::move(decoded).mid(pos + strlen(needle)); - QCOMPARE(decoded, expected); - } -} - -void tst_ToJson::metaData() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - compareMetaData(data, expected); -} - -void tst_ToJson::metaDataAndTagsToObjects() -{ - QFETCH(QByteArray, data); - - // when a tag is converted to an object, the object gets metadata indicating it was a tag - compareMetaData(data, "\"t\":192", CborConvertTagsToObjects); -} - -void tst_ToJson::metaDataForKeys_data() -{ - nonStringKeyMaps_data(); - - // string keys generate no metadata - QTest::newRow("string") << raw("\x60") << QString(); -} - -void tst_ToJson::metaDataForKeys() -{ - QFETCH(QByteArray, data); - QFETCH(QString, expected); - if (expected.isEmpty()) - expected = "{\"\":false}"; - else - expected = "{\"" + expected + "\":false,\"" + expected + "$keycbordump\":true}"; - compareOne('\xa1' + data + '\xf4', expected, - CborConvertAddMetadata | CborConvertStringifyMapKeys); -} - -QTEST_MAIN(tst_ToJson) diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tinycbor.pc.in b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tinycbor.pc.in deleted file mode 100644 index 382779a..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tinycbor.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: TinyCBOR -Description: A tiny CBOR encoder and decoder library -Version: @version@ -Libs: -L${libdir} -ltinycbor -Libs.private: -lm -Cflags: -I${includedir}/tinycbor diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.c deleted file mode 100644 index 97adef3..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.c +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _POSIX_C_SOURCE 200809L -#include "cbor.h" -#include "cborjson.h" -#include -#include -#include -#include -#include - -void *xrealloc(void *old, size_t size, const char *fname) -{ - old = realloc(old, size); - if (old == NULL) { - fprintf(stderr, "%s: %s\n", fname, strerror(errno)); - exit(EXIT_FAILURE); - } - return old; -} - -void printerror(CborError err, const char *fname) -{ - fprintf(stderr, "%s: %s\n", fname, cbor_error_string(err)); - exit(EXIT_FAILURE); -} - -void dumpFile(FILE *in, const char *fname, bool printJosn, int flags) -{ - static const size_t chunklen = 16 * 1024; - static size_t bufsize = 0; - static uint8_t *buffer = NULL; - - size_t buflen = 0; - do { - if (bufsize == buflen) - buffer = xrealloc(buffer, bufsize += chunklen, fname); - - size_t n = fread(buffer + buflen, 1, bufsize - buflen, in); - buflen += n; - if (n == 0) { - if (!ferror(in)) - continue; - fprintf(stderr, "%s: %s\n", fname, strerror(errno)); - exit(EXIT_FAILURE); - } - } while (!feof(in)); - - CborParser parser; - CborValue value; - CborError err = cbor_parser_init(buffer, buflen, 0, &parser, &value); - if (!err) { - if (printJosn) - err = cbor_value_to_json_advance(stdout, &value, flags); - else - err = cbor_value_to_pretty_advance_flags(stdout, &value, flags); - if (!err) - puts(""); - } - if (!err && value.ptr != buffer + buflen) - err = CborErrorGarbageAtEnd; - if (err) - printerror(err, fname); -} - -int main(int argc, char **argv) -{ - bool printJson = false; - int json_flags = CborConvertDefaultFlags; - int cbor_flags = CborPrettyDefaultFlags; - int c; - while ((c = getopt(argc, argv, "MOSUcjhfn")) != -1) { - switch (c) { - case 'c': - printJson = false; - break; - case 'j': - printJson = true; - break; - - case 'f': - cbor_flags |= CborPrettyShowStringFragments; - break; - case 'n': - cbor_flags |= CborPrettyIndicateIndeterminateLength | CborPrettyNumericEncodingIndicators; - break; - - case 'M': - json_flags |= CborConvertAddMetadata; - break; - case 'O': - json_flags |= CborConvertTagsToObjects; - break; - case 'S': - json_flags |= CborConvertStringifyMapKeys; - break; - case 'U': - json_flags |= CborConvertByteStringsToBase64Url; - break; - - case '?': - fprintf(stderr, "Unknown option -%c.\n", optopt); - /* fall through */ - case 'h': - puts("Usage: cbordump [OPTION]... [FILE]...\n" - "Interprets FILEs as CBOR binary data and dumps the content to stdout.\n" - "\n" - "Options:\n" - " -c Print a CBOR dump (see RFC 7049) (default)\n" - " -j Print a JSON equivalent version\n" - " -h Print this help output and exit\n" - "When JSON output is active, the following options are recognized:\n" - " -M Add metadata so converting back to CBOR is possible\n" - " -O Convert CBOR tags to JSON objects\n" - " -S Stringify non-text string map keys\n" - " -U Convert all CBOR byte strings to Base64url regardless of tags\n" - "When CBOR dump is active, the following options are recognized:\n" - " -f Show text and byte string fragments\n" - " -n Show overlong encoding of CBOR numbers and length" - ""); - return c == '?' ? EXIT_FAILURE : EXIT_SUCCESS; - } - } - - char **fname = argv + optind; - if (!*fname) { - dumpFile(stdin, "-", printJson, printJson ? json_flags : cbor_flags); - } else { - for ( ; *fname; ++fname) { - FILE *in = fopen(*fname, "rb"); - if (!in) { - perror("open"); - return EXIT_FAILURE; - } - - dumpFile(in, *fname, printJson, printJson ? json_flags : cbor_flags); - fclose(in); - } - } - - return EXIT_SUCCESS; -} diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.pro deleted file mode 100644 index 71ae6f7..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/cbordump/cbordump.pro +++ /dev/null @@ -1,10 +0,0 @@ -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -CONFIG -= qt -DESTDIR = ../../bin - -CBORDIR = $$PWD/../../src -INCLUDEPATH += $$CBORDIR -SOURCES += cbordump.c -LIBS += ../../lib/libtinycbor.a diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.c b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.c deleted file mode 100644 index c13a751..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.c +++ /dev/null @@ -1,493 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _POSIX_C_SOURCE 200809L -#define _GNU_SOURCE -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -static const char meta_data_marker[] = "$cbor"; -uint8_t *buffer; -size_t buffersize; -bool usingMetaData = false; - -struct MetaData { - CborTag tag; - union { - const char *v; - uint8_t simpleType; - }; - CborType t; - bool tagged; -}; - -uint8_t *decode_base64_generic(const char *string, size_t *len, const int8_t reverse_alphabet[256]) -{ - *len = ((strlen(string) + 3) & ~3) * 3 / 4; - uint8_t *buffer = malloc(*len); - if (buffer == NULL) - return NULL; - - uint8_t *out = buffer; - const uint8_t *in = (const uint8_t *)string; - bool done = false; - while (!done) { - if (reverse_alphabet[in[0]] < 0 || reverse_alphabet[in[1]] < 0) { - if (in[0] == '\0') - done = true; - break; - } - - uint32_t val = reverse_alphabet[in[0]] << 18; - val |= reverse_alphabet[in[1]] << 12; - if (in[2] == '=' || in[2] == '\0') { - if (in[2] == '=' && (in[3] != '=' || in[4] != '\0')) - break; - val >>= 12; - done = true; - } else if (in[3] == '=' || in[3] == '\0') { - if (in[3] == '=' && in[4] != '\0') - break; - val >>= 6; - val |= reverse_alphabet[in[2]]; - done = true; - } else { - val |= reverse_alphabet[in[2]] << 6; - val |= reverse_alphabet[in[3]]; - } - - *out++ = val >> 16; - *out++ = val >> 8; - *out++ = val; - in += 4; - } - - if (!done) { - free(buffer); - return NULL; - } - *len = out - buffer; - return buffer; -} - -uint8_t *decode_base64(const char *string, size_t *len) -{ - static const int8_t reverse_alphabet[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - return decode_base64_generic(string, len, reverse_alphabet); -} - -uint8_t *decode_base64url(const char *string, size_t *len) -{ - static const int8_t reverse_alphabet[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - return decode_base64_generic(string, len, reverse_alphabet); -} - -uint8_t *decode_base16(const char *string, size_t *len) -{ - size_t i; - *len = strlen(string) / 2; - uint8_t *buffer = malloc(*len); - if (buffer == NULL) - return NULL; - - for (i = 0; i < *len; ++i) { - char c = string[i * 2]; - if (c >= '0' && c <= '9') { - buffer[i] = (c - '0') << 4; - } else if ((c | 0x20) >= 'a' && (c | 0x20) <= 'f') { - buffer[i] = ((c | 0x20) - 'a' + 10) << 4; - } else { - free(buffer); - return NULL; - } - - c = string[i * 2 + 1]; - if (c >= '0' && c <= '9') { - buffer[i] |= (c - '0'); - } else if ((c | 0x20) >= 'a' && (c | 0x20) <= 'f') { - buffer[i] |= ((c | 0x20) - 'a' + 10); - } else { - free(buffer); - return NULL; - } - } - - return buffer; -} - -size_t get_cjson_size_limited(cJSON *container) -{ - // cJSON_GetArraySize is O(n), so don't go too far - unsigned s = 0; - cJSON *item; - for (item = container->child; item; item = item->next) { - if (++s > 255) - return CborIndefiniteLength; - } - return s; -} - -cJSON *get_meta_data(cJSON *object, cJSON *item) -{ - cJSON *meta; - char *metadatakey; - - if (asprintf(&metadatakey, "%s%s", item->string, meta_data_marker) < 0 || metadatakey == NULL) - return NULL; - meta = cJSON_GetObjectItem(object, metadatakey); - free(metadatakey); - return meta; -} - -struct MetaData parse_meta_data(cJSON *md) -{ - struct MetaData result = { 0, {NULL}, CborInvalidType, false }; - if (md == NULL || md->type != cJSON_Object) - return result; - - for (md = md->child; md; md = md->next) { - if (strcmp(md->string, "tag") == 0) { - if (md->type != cJSON_String || sscanf(md->valuestring, "%" PRIu64, &result.tag) < 0) - fprintf(stderr, "json2cbor: could not parse tag: %s\n", md->valuestring); - else - result.tagged = true; - } else if (strcmp(md->string, "t") == 0) { - result.t = md->valueint; - } else if (strcmp(md->string, "v") == 0) { - if (md->type == cJSON_Number) - result.simpleType = md->valueint; - else - result.v = md->valuestring; - } - } - return result; -} - -CborError decode_json(cJSON *json, CborEncoder *encoder); -CborError decode_json_with_metadata(cJSON *item, CborEncoder *encoder, struct MetaData md) -{ - switch (md.t) { - case CborIntegerType: { - // integer that has more than 53 bits of precision - uint64_t v; - bool positive = *md.v++ == '+'; - if (sscanf(md.v, "%" PRIx64, &v) < 0) { - fprintf(stderr, "json2cbor: could not parse number: %s\n", md.v); - break; - } - return positive ? cbor_encode_uint(encoder, v) : cbor_encode_negative_int(encoder, v); - } - - case CborByteStringType: { - uint8_t *data; - size_t len; - if (md.tag == CborExpectedBase64Tag) - data = decode_base64(item->valuestring, &len); - else if (md.tag == CborExpectedBase16Tag) - data = decode_base16(item->valuestring, &len); - else if (md.tag == CborNegativeBignumTag) - data = decode_base64url(item->valuestring + 1, &len); - else - data = decode_base64url(item->valuestring, &len); - - if (data != NULL) { - CborError err = cbor_encode_byte_string(encoder, data, len); - free(data); - return err; - } - fprintf(stderr, "json2cbor: could not decode encoded byte string: %s\n", item->valuestring); - break; - } - - case CborSimpleType: - return cbor_encode_simple_value(encoder, md.simpleType); - - case CborUndefinedType: - return cbor_encode_undefined(encoder); - - case CborHalfFloatType: - case CborFloatType: - case CborDoubleType: { - unsigned short half; - double v; - if (!md.v) { - v = item->valuedouble; - } else if (strcmp(md.v, "nan") == 0) { - v = NAN; - } else if (strcmp(md.v, "-inf") == 0) { - v = -INFINITY; - } else if (strcmp(md.v, "inf") == 0) { - v = INFINITY; - } else { - fprintf(stderr, "json2cbor: invalid floating-point value: %s\n", md.v); - break; - } - - // we can't get an OOM here because the metadata makes up for space - // (the smallest metadata is "$cbor":{"t":250} (17 bytes) - return (md.t == CborDoubleType) ? cbor_encode_double(encoder, v) : - (md.t == CborFloatType) ? cbor_encode_float(encoder, v) : - (half = encode_half(v), cbor_encode_half_float(encoder, &half)); - } - - default: - fprintf(stderr, "json2cbor: invalid CBOR type: %d\n", md.t); - case CborInvalidType: - break; - } - - return decode_json(item, encoder); -} - -CborError decode_json(cJSON *json, CborEncoder *encoder) -{ - CborEncoder container; - CborError err; - cJSON *item; - - switch (json->type) { - case cJSON_False: - case cJSON_True: - return cbor_encode_boolean(encoder, json->type == cJSON_True); - - case cJSON_NULL: - return cbor_encode_null(encoder); - - case cJSON_Number: - if ((double)json->valueint == json->valuedouble) - return cbor_encode_int(encoder, json->valueint); -encode_double: - // the only exception that JSON is larger: floating point numbers - container = *encoder; // save the state - err = cbor_encode_double(encoder, json->valuedouble); - - if (err == CborErrorOutOfMemory) { - buffersize += 1024; - uint8_t *newbuffer = realloc(buffer, buffersize); - if (newbuffer == NULL) - return err; - - *encoder = container; // restore state - encoder->data.ptr = newbuffer + (container.data.ptr - buffer); - encoder->end = newbuffer + buffersize; - buffer = newbuffer; - goto encode_double; - } - return err; - - case cJSON_String: - return cbor_encode_text_stringz(encoder, json->valuestring); - - default: - return CborErrorUnknownType; - - case cJSON_Array: - err = cbor_encoder_create_array(encoder, &container, get_cjson_size_limited(json)); - if (err) - return err; - for (item = json->child; item; item = item->next) { - err = decode_json(item, &container); - if (err) - return err; - } - return cbor_encoder_close_container_checked(encoder, &container); - - case cJSON_Object: - err = cbor_encoder_create_map(encoder, &container, - usingMetaData ? CborIndefiniteLength : get_cjson_size_limited(json)); - if (err) - return err; - - for (item = json->child ; item; item = item->next) { - if (usingMetaData && strlen(item->string) > strlen(meta_data_marker) - && strcmp(item->string + strlen(item->string) - strlen(meta_data_marker), meta_data_marker) == 0) - continue; - - err = cbor_encode_text_stringz(&container, item->string); - if (err) - return err; - - if (usingMetaData) { - cJSON *meta = get_meta_data(json, item); - struct MetaData md = parse_meta_data(meta); - if (md.tagged) { - err = cbor_encode_tag(&container, md.tag); - if (err) - return err; - } - - err = decode_json_with_metadata(item, &container, md); - } else { - err = decode_json(item, &container); - } - if (err) - return err; - } - - return cbor_encoder_close_container_checked(encoder, &container); - } -} - -int main(int argc, char **argv) -{ - int c; - while ((c = getopt(argc, argv, "M")) != -1) { - switch (c) { - case 'M': - usingMetaData = true; - break; - - case '?': - fprintf(stderr, "Unknown option -%c.\n", optopt); - // fall through - case 'h': - puts("Usage: json2cbor [OPTION]... [FILE]...\n" - "Reads JSON content from FILE and converts to CBOR.\n" - "\n" - "Options:\n" - " -M Interpret metadata added by cbordump tool\n" - ""); - return c == '?' ? EXIT_FAILURE : EXIT_SUCCESS; - } - } - - FILE *in; - const char *fname = argv[optind]; - if (fname && strcmp(fname, "-") != 0) { - in = fopen(fname, "r"); - if (!in) { - perror("open"); - return EXIT_FAILURE; - } - } else { - in = stdin; - fname = "-"; - } - - /* 1. read the file */ - off_t fsize; - if (fseeko(in, 0, SEEK_END) == 0 && (fsize = ftello(in)) >= 0) { - buffersize = fsize + 1; - buffer = malloc(buffersize); - if (buffer == NULL) { - perror("malloc"); - return EXIT_FAILURE; - } - - rewind(in); - fsize = fread(buffer, 1, fsize, in); - buffer[fsize] = '\0'; - } else { - const unsigned chunk = 16384; - buffersize = 0; - buffer = NULL; - do { // it the hard way - buffer = realloc(buffer, buffersize + chunk); - if (buffer == NULL) { - perror("malloc"); - return EXIT_FAILURE; - } - - buffersize += fread(buffer + buffersize, 1, chunk, in); - } while (!feof(in) && !ferror(in)); - buffer[buffersize] = '\0'; - } - - if (ferror(in)) { - perror("read"); - return EXIT_FAILURE; - } - if (in != stdin) - fclose(in); - - /* 2. parse as JSON */ - cJSON *doc = cJSON_ParseWithOpts((char *)buffer, NULL, true); - if (doc == NULL) { - fprintf(stderr, "json2cbor: %s: could not parse.\n", fname); - return EXIT_FAILURE; - } - - /* 3. encode as CBOR */ - // We're going to reuse the buffer, as CBOR is usually shorter than the equivalent JSON - CborEncoder encoder; - cbor_encoder_init(&encoder, buffer, buffersize, 0); - CborError err = decode_json(doc, &encoder); - - cJSON_Delete(doc); - - if (err) { - fprintf(stderr, "json2cbor: %s: error encoding to CBOR: %s\n", fname, - cbor_error_string(err)); - return EXIT_FAILURE; - } - - fwrite(buffer, 1, encoder.data.ptr - buffer, stdout); - free(buffer); - return EXIT_SUCCESS; -} diff --git a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.pro b/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.pro deleted file mode 100644 index fd6bcd0..0000000 --- a/kws/ota/ota_for_aws/source/dependency/3rdparty/tinycbor/tools/json2cbor/json2cbor.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -CONFIG -= qt -DESTDIR = ../../bin - -CBORDIR = $$PWD/../../src -INCLUDEPATH += $$CBORDIR -SOURCES += json2cbor.c -LIBS += ../../lib/libtinycbor.a - -CJSONDIR = . -!exists($$CJSONDIR/cJSON.h): CJSONDIR = $$CBORDIR/cjson -exists($$CJSONDIR/cJSON.h) { - INCLUDEPATH += $$CJSONDIR - SOURCES += $$CJSONDIR/cJSON.c -} else { - message("cJSON not found, not building json2cbor.") - TEMPLATE = aux -} diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/CONTRIBUTING.md b/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/CONTRIBUTING.md deleted file mode 100644 index 4609904..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/CONTRIBUTING.md +++ /dev/null @@ -1,62 +0,0 @@ -# Contributing Guidelines - -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional -documentation, we greatly value feedback and contributions from our community. - -Please read through this document before submitting any issues or pull requests to ensure we have all the necessary -information to effectively respond to your bug report or contribution. - - -## Reporting Bugs/Feature Requests - -We welcome you to use the GitHub issue tracker to report bugs or suggest features. - -When filing an issue, please check [existing open](https://github.com/FreeRTOS/coreJSON/issues), or [recently closed](https://github.com/FreeRTOS/coreJSON/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already -reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: - -* A reproducible test case or series of steps -* The version of our code being used -* Any modifications you've made relevant to the bug -* Anything unusual about your environment or deployment - - -## Contributing via Pull Requests -Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: - -1. You are working against the latest source on the *main* branch. -1. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. -1. You open an issue to discuss any significant work - we would hate for your time to be wasted. - -To send us a pull request, please: - -1. Fork the repository. -1. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. -1. Ensure that your contributions conform to the [style guide](https://docs.aws.amazon.com/embedded-csdk/202011.00/lib-ref/docs/doxygen/output/html/guide_developer_styleguide.html). -1. Ensure local tests pass. -1. Commit to your fork using clear commit messages. -1. Send us a pull request, answering any default questions in the pull request interface. -1. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. - -GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and -[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). - - -## Finding contributions to work on -Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/FreeRTOS/coreJSON/labels?q=help+wanted) issues is a great place to start. - - -## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. - - -## Security issue notifications -If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. - - -## Licensing - -See the [LICENSE](../LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. - -We may ask you to sign a [Contributor License Agreement (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/ci.yml b/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/ci.yml deleted file mode 100644 index 5cf36ca..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/ci.yml +++ /dev/null @@ -1,163 +0,0 @@ -name: CI Checks -on: - push: - branches: ["**"] - pull_request: - branches: [main] - workflow_dispatch: -jobs: - unittest: - runs-on: ubuntu-latest - steps: - - name: Clone This Repo - uses: actions/checkout@v2 - - name: Build - run: | - sudo apt-get install -y lcov sed - cmake -S test -B build/ \ - -G "Unix Makefiles" \ - -DCMAKE_BUILD_TYPE=Debug \ - -DBUILD_CLONE_SUBMODULES=ON \ - -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror' - make -C build/ all - - name: Test - run: | - cd build/ - ctest -E system --output-on-failure - cd .. - - name: Run Coverage - run: | - make -C build/ coverage - declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId\*" "\*mocks\*" "\*source\*") - echo ${EXCLUDE[@]} | xargs lcov --rc lcov_branch_coverage=1 -r build/coverage.info -o build/coverage.info - lcov --rc lcov_branch_coverage=1 --list build/coverage.info - - name: Check Coverage - env: - MIN_COVERAGE: 100 - run: | - LINE_COVERAGE=$(lcov --list build/coverage.info | tail -n 1 | cut -d '|' -f 2 | sed -n "s/\([^%]*\)%.*/\1/p") - BRANCH_COVERAGE=$(lcov --rc lcov_branch_coverage=1 --list build/coverage.info | tail -n 1 | cut -d '|' -f 4 | sed -n "s/\([^%]*\)%.*/\1/p") - RESULT=0 - echo "Required line and branch coverages: $MIN_COVERAGE" - echo "Line coverage: $LINE_COVERAGE" - if [[ $(echo "$LINE_COVERAGE < $MIN_COVERAGE" | bc) -ne 0 ]]; then - echo "Line Coverage is too low." - RESULT=1 - fi - echo "Branch coverage: $BRANCH_COVERAGE" - if [[ $(echo "$BRANCH_COVERAGE < $MIN_COVERAGE" | bc) -ne 0 ]]; then - echo "Branch Coverage is too low." - RESULT=1 - fi - exit $RESULT - complexity: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Setup - run: sudo apt-get install complexity - - name: Complexity - run: | - find source/ -iname '*.c' |\ - xargs complexity --scores --threshold=0 --horrid-threshold=8 - doxygen: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - name: Install Doxygen - run: | - wget -qO- "http://doxygen.nl/files/doxygen-1.8.20.linux.bin.tar.gz" | sudo tar --strip-components=1 -xz -C /usr/local - sudo apt-get install -y libclang-9-dev - - name: Run Doxygen And Verify Stdout Is Empty - run: | - if [ ! -d docs/doxygen/ ]; then exit 0; fi - doxygen docs/doxygen/config.doxyfile 2>&1 | tee doxyoutput.txt - if [[ "$(wc -c < doxyoutput.txt | bc)" = "0" ]]; then exit 0; else exit 1; fi - spell-check: - runs-on: ubuntu-latest - steps: - - name: Checkout Parent Repo - uses: actions/checkout@v2 - with: - ref: main - repository: aws/aws-iot-device-sdk-embedded-C - - run: rm -rf libraries/standard/coreJSON - - name: Clone This Repo - uses: actions/checkout@v2 - with: - path: libraries/standard/coreJSON - - name: Install spell - run: | - sudo apt-get install spell - sudo apt-get install util-linux - - name: Check spelling - run: | - PATH=$PATH:$PWD/tools/spell - for lexfile in `find libraries/standard/coreJSON -name lexicon.txt` - do dir=${lexfile%/lexicon.txt} - echo $dir - find-unknown-comment-words --directory $dir - if [ $? -ne "0" ] - then - exit 1 - fi - done - formatting: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install Uncrustify - run: sudo apt-get install uncrustify - - name: Run Uncrustify - run: find . -iname "*.[hc]" -exec uncrustify --check -c tools/uncrustify.cfg -l C {} + - - name: Check For Trailing Whitespace - run: | - set +e - grep --exclude="README.md" -rnI -e "[[:blank:]]$" . - if [ "$?" = "0" ]; then - echo "Files have trailing whitespace." - exit 1 - else - exit 0 - fi - - name: Check for CRLF - run: | - set +e - find . -path ./.git -prune -o -exec file {} + | grep "CRLF" - if [ "$?" = "0" ]; then - echo "Files have CRLF line endings." - exit 1 - else - exit 0 - fi - git-secrets: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Checkout awslabs/git-secrets - uses: actions/checkout@v2 - with: - repository: awslabs/git-secrets - ref: master - path: git-secrets - - name: Install git-secrets - run: cd git-secrets && sudo make install && cd .. - - name: Run git-secrets - run: | - git-secrets --register-aws - git-secrets --scan - custom-standard-c-headers: - runs-on: ubuntu-latest - steps: - - name: Clone This Repo - uses: actions/checkout@v2 - - name: Build - run: | - mkdir -p override-include - cp source/include/stdbool.readme override-include/stdbool.h - cp source/include/stdint.readme override-include/stdint.h - cmake -S test -B build/ \ - -G "Unix Makefiles" \ - -DBUILD_CLONE_SUBMODULES=ON \ - -DCMAKE_C_FLAGS='-Wall -Wextra -I../override-include' - make -C build/ coverity_analysis diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/release.yml b/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/release.yml deleted file mode 100644 index 509922e..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/.github/workflows/release.yml +++ /dev/null @@ -1,114 +0,0 @@ -name: Release automation - -on: - workflow_dispatch: - inputs: - commit_id: - description: 'Commit ID to tag and create a release for' - required: true - version_number: - description: 'Release Version Number (Eg, v1.0.0)' - required: true - -jobs: - tag-commit: - name: Tag commit - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.event.inputs.commit_id }} - - name: Configure git identity - run: | - git config --global user.name "Release Workflow" - - name: Tag Commit and Push to remote - run: | - git tag ${{ github.event.inputs.version_number }} -a -m "coreJSON Library ${{ github.event.inputs.version_number }}" - git push origin --tags - - name: Verify tag on remote - run: | - git tag -d ${{ github.event.inputs.version_number }} - git remote update - git checkout tags/${{ github.event.inputs.version_number }} - git diff ${{ github.event.inputs.commit_id }} tags/${{ github.event.inputs.version_number }} - create-zip: - needs: tag-commit - name: Create ZIP and verify package for release asset. - runs-on: ubuntu-latest - steps: - - name: Install ZIP tools - run: sudo apt-get install zip unzip - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.event.inputs.commit_id }} - path: coreJSON - submodules: recursive - - name: Checkout disabled submodules - run: | - cd coreJSON - git submodule update --init --checkout --recursive - - name: Create ZIP - run: | - zip -r coreJSON-${{ github.event.inputs.version_number }}.zip coreJSON -x "*.git*" - ls ./ - - name: Validate created ZIP - run: | - mkdir zip-check - mv coreJSON-${{ github.event.inputs.version_number }}.zip zip-check - cd zip-check - unzip coreJSON-${{ github.event.inputs.version_number }}.zip -d coreJSON-${{ github.event.inputs.version_number }} - ls coreJSON-${{ github.event.inputs.version_number }} - diff -r -x "*.git*" coreJSON-${{ github.event.inputs.version_number }}/coreJSON/ ../coreJSON/ - cd ../ - - name: Build - run: | - cd zip-check/coreJSON-${{ github.event.inputs.version_number }}/coreJSON - sudo apt-get install -y lcov - cmake -S test -B build/ \ - -G "Unix Makefiles" \ - -DCMAKE_BUILD_TYPE=Debug \ - -DBUILD_CLONE_SUBMODULES=ON \ - -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror' - make -C build/ all - - name: Test - run: | - cd zip-check/coreJSON-${{ github.event.inputs.version_number }}/coreJSON/build/ - ctest -E system --output-on-failure - cd .. - - name: Create artifact of ZIP - uses: actions/upload-artifact@v2 - with: - name: coreJSON-${{ github.event.inputs.version_number }}.zip - path: zip-check/coreJSON-${{ github.event.inputs.version_number }}.zip - create-release: - needs: create-zip - name: Create Release and Upload Release Asset - runs-on: ubuntu-latest - steps: - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.event.inputs.version_number }} - release_name: ${{ github.event.inputs.version_number }} - body: Release ${{ github.event.inputs.version_number }} of the coreJSON Library. - draft: false - prerelease: false - - name: Download ZIP artifact - uses: actions/download-artifact@v2 - with: - name: coreJSON-${{ github.event.inputs.version_number }}.zip - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./coreJSON-${{ github.event.inputs.version_number }}.zip - asset_name: coreJSON-${{ github.event.inputs.version_number }}.zip - asset_content_type: application/zip diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/.gitignore b/kws/ota/ota_for_aws/source/dependency/coreJSON/.gitignore deleted file mode 100644 index f7bfcef..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Ignore documentation output. -**/docs/**/output/* - -# Ignore CMake build directory. -build/ - -# Ignore build artifacts -*.o - -# Ignore code coverage artifacts -*.gcda -*.gcno -*.gcov diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/.gitmodules b/kws/ota/ota_for_aws/source/dependency/coreJSON/.gitmodules deleted file mode 100644 index 1f96890..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/.gitmodules +++ /dev/null @@ -1,12 +0,0 @@ -[submodule "test/unit-test/Unity"] - path = test/unit-test/Unity - url = https://github.com/ThrowTheSwitch/Unity - update = none -[submodule "test/cbmc/aws-templates-for-cbmc-proofs"] - path = test/cbmc/aws-templates-for-cbmc-proofs - url = https://github.com/awslabs/aws-templates-for-cbmc-proofs.git - update = none -[submodule "test/cbmc/litani"] - path = test/cbmc/litani - url = https://github.com/awslabs/aws-build-accumulator - update = none diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/CHANGELOG.md b/kws/ota/ota_for_aws/source/dependency/coreJSON/CHANGELOG.md deleted file mode 100644 index d43c9cd..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# Change Log for coreJSON Library - -## v3.0.0 (December 2020) - - [#74](https://github.com/FreeRTOS/coreJSON/pull/74) Add `JSON_Iterate` function to iterate over items in a JSON collection. - - [#74](https://github.com/FreeRTOS/coreJSON/pull/74) Add `JSONInvalid` enum with the value 0 to `JSONTypes_t`. This change is not backwards compatible. - -## v2.0.0 (November 2020) - -### Updates - - [#53](https://github.com/FreeRTOS/coreJSON/pull/53) Update the `JSON_Search` function to support searching JSON arrays. This change is not backwards compatible. - -### Other - - [#35](https://github.com/FreeRTOS/coreJSON/pull/35), [#36](https://github.com/FreeRTOS/coreJSON/pull/36), [#39](https://github.com/FreeRTOS/coreJSON/pull/39), [#51](https://github.com/FreeRTOS/coreJSON/pull/51), [#52](https://github.com/FreeRTOS/coreJSON/pull/52), [#54](https://github.com/FreeRTOS/coreJSON/pull/54) Minor documentation updates. - - [#40](https://github.com/FreeRTOS/coreJSON/pull/40) Build the unit tests with Unity instead of CMock. - - [#44](https://github.com/FreeRTOS/coreJSON/pull/44) Add 100% branch coverage to the unit tests. - - [#46](https://github.com/FreeRTOS/coreJSON/pull/46), [#49](https://github.com/FreeRTOS/coreJSON/pull/49) Fix warnings in the source code. - -## v1.0.0 (September 2020) - -This is the first release of the coreJSON library, a parser that strictly enforces the [ECMA-404 JSON standard](https://www.json.org/json-en.html) and is suitable for low memory footprint embedded devices. diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/LICENSE b/kws/ota/ota_for_aws/source/dependency/coreJSON/LICENSE deleted file mode 100755 index 9cf1062..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/MISRA.md b/kws/ota/ota_for_aws/source/dependency/coreJSON/MISRA.md deleted file mode 100644 index ab2863d..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/MISRA.md +++ /dev/null @@ -1,26 +0,0 @@ -# MISRA Compliance - -The coreJSON library files conform to the [MISRA C:2012](https://www.misra.org.uk/MISRAHome/MISRAC2012/tabid/196/Default.aspx) -guidelines, with some noted exceptions. Compliance is checked with Coverity static analysis. -Deviations from the MISRA standard are listed below: - -### Ignored by [Coverity Configuration](tools/coverity/misra.config) -| Deviation | Category | Justification | -| :-: | :-: | :-: | -| Directive 4.9 | Advisory | Allow inclusion of function like macros. | -| Rule 3.1 | Required | Allow nested comments. C++ style `//` comments are used in example code within Doxygen documentation blocks. | -| Rule 8.13 | Advisory | Allow one function to have a char * argument without const qualifier. | -| Rule 15.4 | Advisory | Allow more then one `break` statement to terminate a loop. | -| Rule 19.2 | Advisory | Allow a `union` of a signed and unsigned type of identical sizes. | -| Rule 20.12 | Required | Allow use of `assert()`, which uses a parameter in both expanded and raw forms. | - -### Flagged by Coverity -| Deviation | Category | Justification | -| :-: | :-: | :-: | -| Rule 2.5 | Advisory | A macro is not used by the library; however, it exists to be used by an application. | -| Rule 8.7 | Advisory | API functions are not used by the library; however, they must be externally visible in order to be used by an application. | - -### Suppressed with Coverity Comments -| Deviation | Category | Justification | -| :-: | :-: | :-: | -| Rule 11.3 | Required | False positive - the rule permits type qualifiers to be added. | diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/README.md b/kws/ota/ota_for_aws/source/dependency/coreJSON/README.md deleted file mode 100644 index f335866..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/README.md +++ /dev/null @@ -1,112 +0,0 @@ -## coreJSON Library - -This repository contains the coreJSON library, a parser that strictly enforces the ECMA-404 JSON standard and is suitable for low memory footprint embedded devices. The coreJSON library is distributed under the [MIT Open Source License](LICENSE). - -This library has gone through code quality checks including verification that no function has a [GNU Complexity](https://www.gnu.org/software/complexity/manual/complexity.html) score over 8, and checks against deviations from mandatory rules in the [MISRA coding standard](https://www.misra.org.uk/MISRAHome/MISRAC2012/tabid/196/Default.aspx). Deviations from the MISRA C:2012 guidelines are documented under [MISRA Deviations](MISRA.md). This library has also undergone both static code analysis from [Coverity static analysis](https://scan.coverity.com/), and validation of memory safety and proof of functional correctness through the [CBMC automated reasoning tool](https://www.cprover.org/cbmc/). - -See memory requirements for this library [here](https://docs.aws.amazon.com/embedded-csdk/202012.00/lib-ref/libraries/standard/coreJSON/docs/doxygen/output/html/index.html#json_memory_requirements). - -## Reference example - -```c -#include -#include "core_json.h" - -int main() -{ - // Variables used in this example. - JSONStatus_t result; - char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}"; - size_t bufferLength = sizeof( buffer ) - 1; - char queryKey[] = "bar.foo"; - size_t queryKeyLength = sizeof( queryKey ) - 1; - char * value; - size_t valueLength; - - // Calling JSON_Validate() is not necessary if the document is guaranteed to be valid. - result = JSON_Validate( buffer, bufferLength ); - - if( result == JSONSuccess ) - { - result = JSON_Search( buffer, bufferLength, queryKey, queryKeyLength, - &value, &valueLength ); - } - - if( result == JSONSuccess ) - { - // The pointer "value" will point to a location in the "buffer". - char save = value[ valueLength ]; - // After saving the character, set it to a null byte for printing. - value[ valueLength ] = '\0'; - // "Found: bar.foo -> xyz" will be printed. - printf( "Found: %s -> %s\n", queryKey, value ); - // Restore the original character. - value[ valueLength ] = save; - } - - return 0; -} -``` -A search may descend through nested objects when the `queryKey` contains matching key strings joined by a separator, `.`. In the example above, `bar` has the value `{"foo":"xyz"}`. Therefore, a search for query key `bar.foo` would output `xyz`. - -## Building coreJSON - -A compiler that supports **C90 or later** such as *gcc* is required to build the library. - -Additionally, the library uses 2 header files introduced in ISO C99, `stdbool.h` and `stdint.h`. For compilers that do not provide this header file, the [source/include](source/include) directory contains [stdbool.readme](source/include/stdbool.readme) and [stdbool.readme](source/include/stdint.readme), which can be renamed to `stdbool.h` and `stdint.h` respectively. - -For instance, if the example above is copied to a file named `example.c`, *gcc* can be used like so: -```bash -gcc -I source/include example.c source/core_json.c -o example -./example -``` - -*gcc* can also produce an output file to be linked: -```bash -gcc -I source/include -c source/core_json.c -``` - -## Generating documentation - -The Doxygen references were created using Doxygen version 1.8.20. To generate the -Doxygen pages, please run the following command from the root of this repository: - -```shell -doxygen docs/doxygen/config.doxyfile -``` - -## Building unit tests - -### Checkout Unity Submodule -By default, the submodules in this repository are configured with `update=none` in [.gitmodules](.gitmodules), to avoid increasing clone time and disk space usage of other repositories (like [amazon-freertos](https://github.com/aws/amazon-freertos) that submodules this repository). - -To build unit tests, the submodule dependency of Unity is required. Use the following command to clone the submodule: -``` -git submodule update --checkout --init --recursive --test/unit-test/Unity -``` - -### Platform Prerequisites - -- For running unit tests - - C90 compiler like gcc - - CMake 3.13.0 or later - - Ruby 2.0.0 or later is additionally required for the Unity test framework (that we use). -- For running the coverage target, gcov is additionally required. - -### Steps to build Unit Tests - -1. Go to the root directory of this repository. (Make sure that the **Unity** submodule is cloned as described [above](#checkout-unity-submodule).) - -1. Create build directory: `mkdir build && cd build` - -1. Run *cmake* while inside build directory: `cmake -S ../test` - -1. Run this command to build the library and unit tests: `make all` - -1. The generated test executables will be present in `build/bin/tests` folder. - -1. Run `ctest` to execute all tests and view the test run summary. - -## Contributing - -See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for information on contributing. diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/SECURITY.md b/kws/ota/ota_for_aws/source/dependency/coreJSON/SECURITY.md deleted file mode 100644 index a6363d9..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/SECURITY.md +++ /dev/null @@ -1,5 +0,0 @@ -## Reporting a Vulnerability - -If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security -via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com. -Please do **not** create a public github issue. diff --git a/kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/config.doxyfile b/kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/config.doxyfile deleted file mode 100644 index e9910ff..0000000 --- a/kws/ota/ota_for_aws/source/dependency/coreJSON/docs/doxygen/config.doxyfile +++ /dev/null @@ -1,2005 +0,0 @@ -# Doxyfile 1.8.20 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the configuration -# file that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# https://www.gnu.org/software/libiconv/ for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "coreJSON" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = "v3.0.0" - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "Parser library for the ECMA-404 JSON standard" - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = docs/doxygen/output/ - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = NO - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line -# such as -# /*************** -# as being the beginning of a Javadoc-style comment "banner". If set to NO, the -# Javadoc-style will behave just like regular comments and it will not be -# interpreted by doxygen. -# The default value is: NO. - -JAVADOC_BANNER = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# By default Python docstrings are displayed as preformatted text and doxygen's -# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the -# doxygen's special commands can be used and the contents of the docstring -# documentation blocks is shown as doxygen documentation. -# The default value is: YES. - -PYTHON_DOCSTRING = YES - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice -# sources only. Doxygen will then generate output that is more tailored for that -# language. For instance, namespaces will be presented as modules, types will be -# separated into more groups, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_SLICE = NO - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up -# to that level are automatically included in the table of contents, even if -# they do not have an id attribute. -# Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 5. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -TOC_INCLUDE_HEADINGS = 5 - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = YES - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use -# during processing. When set to 0 doxygen will based this on the number of -# cores available in the system. You can set it explicitly to a value larger -# than 0 to get more control over the balance between CPU load and processing -# speed. At this moment only the input processing can be done using multiple -# threads. Since this is still an experimental feature the default is set to 1, -# which efficively disables parallel processing. Please report any issues you -# encounter. Generating dot graphs in parallel is controlled by the -# DOT_NUM_THREADS setting. -# Minimum value: 0, maximum value: 32, default value: 1. - -# NUM_PROC_THREADS = 1 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual -# methods of a class will be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIV_VIRTUAL = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# declarations. If set to NO, these declarations will be included in the -# documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# (including Cygwin) and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = docs/doxygen/layout.xml - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = ./docs/doxygen \ - ./source/include \ - ./source \ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen -# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, -# *.vhdl, *.ucf, *.qsf and *.ice. - -FILE_PATTERNS = *.c \ - *.h \ - *.dox - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = NO - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = source/include - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# entity all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see https://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. -# The default value is: NO. - -# CLANG_ASSISTED_PARSING = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = ./docs/doxygen/style.css - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# https://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML -# documentation will contain a main index with vertical navigation menus that -# are dynamically created via JavaScript. If disabled, the navigation index will -# consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have JavaScript, -# like the Qt help browser. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_MENUS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy -# genXcode/_index.html for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the main .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = YES - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg -# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see -# https://inkscape.org) to generate formulas as SVG images instead of PNGs for -# the HTML output. These images will generally look nicer at scaled resolutions. -# Possible values are: png (the default) and svg (looks nicer but requires the -# pdf2svg or inkscape tool). -# The default value is: png. -# This tag requires that the tag GENERATE_HTML is set to YES. - -# HTML_FORMULA_FORMAT = png - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side JavaScript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /