├── .check-headers-ignore ├── .release-please-manifest.json ├── CHANGELOG.md ├── .docs_header.md ├── west.yml ├── release-please-config.json ├── NOTICE ├── .gitignore ├── zephyr └── module.yml ├── src ├── platform │ ├── certs │ │ ├── posix │ │ │ └── certs.c │ │ ├── generic │ │ │ └── weak │ │ │ │ └── certs.c │ │ └── zephyr │ │ │ └── certs.c │ ├── inventory │ │ ├── generic │ │ │ └── weak │ │ │ │ └── inventory.c │ │ └── zephyr │ │ │ └── inventory.c │ ├── memory │ │ ├── generic │ │ │ └── alloc.c │ │ └── zephyr │ │ │ └── alloc.c │ ├── log │ │ ├── generic │ │ │ └── weak │ │ │ │ └── log.c │ │ ├── posix │ │ │ └── log.c │ │ └── zephyr │ │ │ └── log.c │ ├── sha │ │ └── generic │ │ │ ├── weak │ │ │ └── sha.c │ │ │ └── mbedtls │ │ │ └── sha.c │ ├── tls │ │ └── generic │ │ │ └── weak │ │ │ └── tls.c │ ├── net │ │ ├── generic │ │ │ └── weak │ │ │ │ └── http.c │ │ └── zephyr │ │ │ └── net.h │ ├── os │ │ └── generic │ │ │ └── weak │ │ │ └── os.c │ └── storage │ │ └── generic │ │ └── weak │ │ └── storage.c ├── include │ ├── alloc.h │ ├── certs.h │ ├── zephyr-image-update-module.h │ ├── update-module.h │ ├── http-client-event.h │ ├── artifact-download-data.h │ ├── log.h │ ├── artifact-download.h │ ├── client.h │ ├── tls.h │ ├── inventory.h │ ├── sha.h │ ├── error-counters.h │ ├── http.h │ ├── os.h │ ├── api.h │ ├── storage.h │ ├── utils.h │ └── artifact.h └── core │ ├── alloc.c │ ├── error-counters.c │ ├── update-module.c │ └── artifact-download.c ├── tests ├── unit │ ├── main_test.cpp │ ├── core │ │ └── client_test.cpp │ └── CMakeLists.txt └── smoke │ └── CMakeLists.txt ├── cmake ├── undefsan.cmake ├── threadsan.cmake ├── asan.cmake ├── CMake_posix_defaults.txt ├── CMake_defaults.txt ├── CMake_weak_defaults.txt ├── helper.cmake └── git_helper.cmake ├── .github └── workflows │ ├── do_code_format.sh │ ├── check_allocations.sh │ ├── check_code_format.sh │ ├── check_equivalence_tests.sh │ ├── check_include_guards.sh │ └── check_headers.sh ├── include └── mender │ ├── zephyr-image-update-module.h │ ├── alloc.h │ ├── inventory.h │ ├── utils.h │ ├── log.h │ ├── client.h │ └── update-module.h ├── docs ├── flashwear.md └── footprint.md ├── target ├── zephyr │ ├── CMakeLists.txt │ └── mender-artifact.cmake └── posix │ └── CMakeLists.txt ├── .clang-format ├── .gitlab └── release.yaml └── .gitlab-ci.yml /.check-headers-ignore: -------------------------------------------------------------------------------- 1 | .gitlab-ci.yml 2 | west.yml 3 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.9.0" 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | --- 2 | ## 0.9.0 - 2025-04-11 3 | 4 | * Preview of Mender MCU 5 | 6 | --- 7 | -------------------------------------------------------------------------------- /.docs_header.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mender MCU 3 | taxonomy: 4 | category: docs 5 | shortcode-core: 6 | active: false 7 | github: false 8 | --- 9 | -------------------------------------------------------------------------------- /west.yml: -------------------------------------------------------------------------------- 1 | manifest: 2 | 3 | remotes: 4 | - name: mender 5 | url-base: https://github.com/mendersoftware 6 | 7 | projects: 8 | - name: cjson-zephyr 9 | submodules: true 10 | remote: mender 11 | path: modules/lib/cjson 12 | revision: 35dd41f010f66bedbd34d4ec2e5595ce74faf96f 13 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": { 4 | "changelog-path": "CHANGELOG.md", 5 | "bump-minor-pre-major": false, 6 | "bump-patch-for-minor-pre-major": false, 7 | "draft": false, 8 | "prerelease": false 9 | } 10 | }, 11 | "release-type": "simple", 12 | "include-component-in-tag": false, 13 | "include-v-in-tag": true, 14 | "signoff": "mender-test-bot ", 15 | "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" 16 | } -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright joelguittet and mender-mcu-client contributors 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | _deps 3 | mender-mcu-client.elf 4 | tests/smoke/mocks/cjson/cjson 5 | tests/smoke/mocks/mbedtls/mbedtls 6 | tests/smoke/mender-mcu-client.elf 7 | 8 | CMakeCache.txt 9 | CMakeFiles/ 10 | Makefile 11 | *.cmake 12 | *.a 13 | 14 | *_test 15 | Testing 16 | lib 17 | tests/unit/reports 18 | *.lcov 19 | 20 | # This file specifies folder icon positions, and other visual information in the 21 | # macOS Finder app (i.e., the file explorer). The file is created automatically 22 | # and is one of those annoying files that shows up as an untracked file in Git. 23 | # It is possible to disable it, although I'm guessing most macOS users don't 24 | # want to do that. Hence, we'll do them a service and list it here. 25 | .DS_Store 26 | -------------------------------------------------------------------------------- /zephyr/module.yml: -------------------------------------------------------------------------------- 1 | # @file module.yml 2 | # @brief mender-mcu-client module YAML file 3 | # 4 | # Copyright joelguittet and mender-mcu-client contributors 5 | # Copyright Northern.tech AS 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | build: 20 | cmake: target/zephyr 21 | kconfig: target/zephyr/Kconfig 22 | -------------------------------------------------------------------------------- /src/platform/certs/posix/certs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file certs.c 3 | * @brief Mender MCU Certificate for posix 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "certs.h" 21 | 22 | mender_err_t 23 | mender_add_dormant_certs(void) { 24 | /* Nothing to do */ 25 | return MENDER_OK; 26 | } 27 | -------------------------------------------------------------------------------- /src/platform/inventory/generic/weak/inventory.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file inventory.c 3 | * @brief weak Mender inventory code 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "utils.h" 21 | 22 | MENDER_FUNC_WEAK mender_err_t 23 | mender_inventory_add_default_callbacks(void) { 24 | return MENDER_OK; 25 | } 26 | -------------------------------------------------------------------------------- /tests/unit/main_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main_test.cpp 3 | * @brief Unit Tests main definition 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | 22 | int 23 | main(int argc, char *argv[]) { 24 | ::testing::InitGoogleTest(&argc, argv); 25 | return RUN_ALL_TESTS(); 26 | } 27 | -------------------------------------------------------------------------------- /cmake/undefsan.cmake: -------------------------------------------------------------------------------- 1 | # @file undefsan.cmake 2 | # @brief Undefined Sanitizer options 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | include(${CMAKE_CURRENT_LIST_DIR}/helper.cmake) 19 | 20 | if (CMAKE_BUILD_TYPE STREQUAL "UndefSan") 21 | sanitizer_add_compiler_and_linker_flags(UNDEFSAN 22 | "-fsanitize=undefined" 23 | "-fsanitize=undefined") 24 | endif() 25 | -------------------------------------------------------------------------------- /cmake/threadsan.cmake: -------------------------------------------------------------------------------- 1 | # @file threadsan.cmake 2 | # @brief Thread Sanitizer options 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | include(${CMAKE_CURRENT_LIST_DIR}/helper.cmake) 19 | 20 | if (CMAKE_BUILD_TYPE STREQUAL "ThreadSan") 21 | sanitizer_add_compiler_and_linker_flags(THREADSAN 22 | "-fsanitize=thread -fPIE -fpie" 23 | "-fsanitize=thread") 24 | endif() 25 | -------------------------------------------------------------------------------- /src/platform/certs/generic/weak/certs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file certs.c 3 | * @brief Mender MCU Certificate for weak platform 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "certs.h" 21 | #include "utils.h" 22 | 23 | MENDER_FUNC_WEAK mender_err_t 24 | mender_add_dormant_certs(void) { 25 | /* Nothing to do */ 26 | return MENDER_NOT_IMPLEMENTED; 27 | } 28 | -------------------------------------------------------------------------------- /cmake/asan.cmake: -------------------------------------------------------------------------------- 1 | # @file asan.cmake 2 | # @brief Address Sanitizer options 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | include(${CMAKE_CURRENT_LIST_DIR}/helper.cmake) 19 | 20 | if (CMAKE_BUILD_TYPE STREQUAL "ASan") 21 | sanitizer_add_compiler_and_linker_flags(ASAN 22 | "-fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope" 23 | "-fsanitize=address") 24 | endif() 25 | -------------------------------------------------------------------------------- /.github/workflows/do_code_format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @file do_code_format.sh 3 | # @brief Update all source files according to wanted code format 4 | # 5 | # Copyright joelguittet and mender-mcu-client contributors 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | # Update source and header files 20 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.c$|.*\.h$|.*\.cpp$|.*\.hpp$)'` 21 | do 22 | clang-format -i ${source_file} || exit 1 23 | done 24 | 25 | exit 0 26 | 27 | -------------------------------------------------------------------------------- /src/platform/memory/generic/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alloc.c 3 | * @brief Generic implementation of the Mender memory management functions 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | void 21 | mender_set_platform_allocation_funcs(void) { 22 | /* Nothing to do here, the default/fallback is to use the standard functions 23 | which is what we want here. We just need this function to be 24 | available. */ 25 | return; 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/check_allocations.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @file check_allocations.sh 3 | # @brief Check that memory allocations are done using our functions 4 | # 5 | # Copyright Northern.tech AS 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | bad_files=$(git grep -Pl '\b(malloc|calloc|realloc|free)\s*\(' | grep -Pv '(tests/|core/src/mender-alloc\.c)') 20 | if [ -n "$bad_files" ]; then 21 | for file in $bad_files; do 22 | echo "==============================" 23 | echo "Bad memory allocations in $file (or a broken check):" 24 | grep -HnP '\b(malloc|calloc|realloc|free)\s*\(' "$file" 25 | echo "==============================" 26 | done 27 | fi 28 | -------------------------------------------------------------------------------- /src/include/alloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alloc.h 3 | * @brief Mender memory management functions (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ALLOC_PRIV_H__ 21 | #define __MENDER_ALLOC_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | /** 30 | * @brief Set platform-specific memory allocation functions (if any) 31 | */ 32 | void mender_set_platform_allocation_funcs(void); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif /* __cplusplus */ 37 | 38 | #endif /* __MENDER_ALLOC_PRIV_H__ */ 39 | -------------------------------------------------------------------------------- /src/include/certs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file certs.h 3 | * @brief Mender MCU Certificate (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_CERTS_PRIV_H__ 21 | #define __MENDER_CERTS_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "utils.h" 28 | 29 | /** 30 | * @brief Add dormant certificates for potential disaster recovery scenarios 31 | * @return MENDER_OK if the function succeeds, error code otherwise 32 | */ 33 | mender_err_t mender_add_dormant_certs(void); 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif /* __cplusplus */ 38 | 39 | #endif /* __MENDER_CERTS_PRIV_H__ */ 40 | -------------------------------------------------------------------------------- /src/include/zephyr-image-update-module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file zephyr-image-update-module.h 3 | * @brief The basic Zephyr update module based on MCUboot (public API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ZEPHYR_IMAGE_UPDATE_MODULE_PRIV_H__ 21 | #define __MENDER_ZEPHYR_IMAGE_UPDATE_MODULE_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | /* No private API here, but having this file allows #include consistency in our sources. */ 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif /* __cplusplus */ 34 | 35 | #endif /* __MENDER_ZEPHYR_IMAGE_UPDATE_MODULE_PRIV_H__ */ 36 | -------------------------------------------------------------------------------- /.github/workflows/check_code_format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @file check_code_format.sh 3 | # @brief Check code format 4 | # 5 | # Copyright joelguittet and mender-mcu-client contributors 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | # Initialize list of files that are not properly formatted 20 | result="" 21 | 22 | # Check source and header files 23 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.c$|.*\.h$|.*\.cpp$|.*\.hpp$)'` 24 | do 25 | lines=$(clang-format --dry-run ${source_file} 2>&1 | wc -l) 26 | if [[ ! $lines -eq 0 ]]; then 27 | result="${result}\n${source_file}" 28 | fi 29 | done 30 | 31 | # Check result 32 | if [[ ${result} != "" ]]; then 33 | echo "The following files are not properly formatted:" 34 | echo -e $result 35 | exit 1 36 | fi 37 | 38 | exit 0 39 | 40 | -------------------------------------------------------------------------------- /cmake/CMake_posix_defaults.txt: -------------------------------------------------------------------------------- 1 | # @file CMake_posix_defaults.txt 2 | # @brief CMake posix defaults 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | set(CONFIG_MENDER_PLATFORM_LOG_TYPE "posix" CACHE STRING "Log type") 19 | set(CONFIG_MENDER_PLATFORM_NET_TYPE "generic/curl" CACHE STRING "Network type") 20 | set(CONFIG_MENDER_PLATFORM_SCHEDULER_TYPE "posix" CACHE STRING "Scheduler type") 21 | set(CONFIG_MENDER_PLATFORM_STORAGE_TYPE "posix" CACHE STRING "Storage type") 22 | set(CONFIG_MENDER_PLATFORM_TLS_TYPE "generic/mbedtls" CACHE STRING "TLS type") 23 | set(CONFIG_MENDER_PLATFORM_SHA_TYPE "generic/mbedtls" CACHE STRING "SHA type") 24 | set(CONFIG_MENDER_PLATFORM_CERT_TYPE "posix" CACHE STRING "Certificate type") 25 | 26 | include(${CMAKE_CURRENT_LIST_DIR}/CMake_defaults.txt) 27 | 28 | # Local Variables: 29 | # mode: cmake 30 | # End: 31 | -------------------------------------------------------------------------------- /cmake/CMake_defaults.txt: -------------------------------------------------------------------------------- 1 | # @file CMake_defaults.txt 2 | # @brief CMake defaults 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | set(CONFIG_MENDER_CLIENT_INVENTORY_DISABLE OFF CACHE BOOL "Inventory") 19 | set(CONFIG_MENDER_DEPLOYMENT_LOGS OFF CACHE BOOL "Deployment logs") 20 | set(CONFIG_MENDER_FULL_PARSE_ARTIFACT ON CACHE BOOL "Full parse artifact") 21 | set(CONFIG_MENDER_PROVIDES_DEPENDS ON CACHE BOOL "Provides depends") 22 | set(CONFIG_MENDER_COMMIT_REQUIRE_AUTH ON CACHE BOOL "Authentication required for update commit") 23 | set(CONFIG_MENDER_ALL_WARNINGS_AS_ERRORS ON CACHE BOOL "All warnings as errors") 24 | set(CONFIG_MENDER_ERRORS_THRESHOLD_NET 10 CACHE STRING "Network errors threshold") 25 | set(CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT 5 CACHE STRING "Reboot errors threshold") 26 | 27 | # Local Variables: 28 | # mode: cmake 29 | # End: 30 | -------------------------------------------------------------------------------- /cmake/CMake_weak_defaults.txt: -------------------------------------------------------------------------------- 1 | # @file CMake_weak_defaults.txt 2 | # @brief CMake weak defaults 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | set(CONFIG_MENDER_PLATFORM_LOG_TYPE "generic/weak" CACHE STRING "Log type") 19 | set(CONFIG_MENDER_PLATFORM_NET_TYPE "generic/weak" CACHE STRING "Network type") 20 | set(CONFIG_MENDER_PLATFORM_SCHEDULER_TYPE "generic/weak" CACHE STRING "Scheduler type") 21 | set(CONFIG_MENDER_PLATFORM_STORAGE_TYPE "generic/weak" CACHE STRING "Storage type") 22 | set(CONFIG_MENDER_PLATFORM_TLS_TYPE "generic/weak" CACHE STRING "TLS type") 23 | set(CONFIG_MENDER_PLATFORM_SHA_TYPE "generic/weak" CACHE STRING "SHA type") 24 | set(CONFIG_MENDER_PLATFORM_CERT_TYPE "generic/weak" CACHE STRING "Certificate type") 25 | 26 | include(${CMAKE_CURRENT_LIST_DIR}/CMake_defaults.txt) 27 | 28 | # Local Variables: 29 | # mode: cmake 30 | # End: 31 | -------------------------------------------------------------------------------- /src/platform/log/generic/weak/log.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log.c 3 | * @brief Mender logging interface for weak platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "log.h" 21 | #include "utils.h" 22 | 23 | MENDER_FUNC_WEAK mender_err_t 24 | mender_log_init(void) { 25 | 26 | /* Nothing to do */ 27 | return MENDER_OK; 28 | } 29 | 30 | MENDER_FUNC_WEAK mender_err_t 31 | mender_log_print(uint8_t level, const char *filename, const char *function, int line, char *format, ...) { 32 | 33 | (void)level; 34 | (void)filename; 35 | (void)function; 36 | (void)line; 37 | (void)format; 38 | 39 | /* Nothing to do */ 40 | return MENDER_OK; 41 | } 42 | 43 | MENDER_FUNC_WEAK mender_err_t 44 | mender_log_exit(void) { 45 | 46 | /* Nothing to do */ 47 | return MENDER_OK; 48 | } 49 | -------------------------------------------------------------------------------- /src/platform/sha/generic/weak/sha.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sha.c 3 | * @brief Mender SHA interface for weak platform 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "sha.h" 21 | 22 | MENDER_FUNC_WEAK mender_err_t 23 | mender_sha256_begin(MENDER_ARG_UNUSED mender_sha256_context_t *ctx) { 24 | /* Nothing to do */ 25 | return MENDER_NOT_IMPLEMENTED; 26 | } 27 | 28 | MENDER_FUNC_WEAK mender_err_t 29 | mender_sha256_update(MENDER_ARG_UNUSED mender_sha256_context_t ctx, MENDER_ARG_UNUSED const unsigned char *input, MENDER_ARG_UNUSED size_t length) { 30 | /* Nothing to do */ 31 | return MENDER_NOT_IMPLEMENTED; 32 | } 33 | 34 | MENDER_FUNC_WEAK mender_err_t 35 | mender_sha256_finish(MENDER_ARG_UNUSED mender_sha256_context_t ctx, MENDER_ARG_UNUSED unsigned char *output) { 36 | /* Nothing to do */ 37 | return MENDER_NOT_IMPLEMENTED; 38 | } 39 | -------------------------------------------------------------------------------- /include/mender/zephyr-image-update-module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file zephyr-image-update-module.h 3 | * @brief The basic Zephyr update module based on MCUboot 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ZEPHYR_IMAGE_UPDATE_MODULE_H__ 21 | #define __MENDER_ZEPHYR_IMAGE_UPDATE_MODULE_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | #ifdef CONFIG_MENDER_ZEPHYR_IMAGE_UPDATE_MODULE 30 | 31 | /** 32 | * @brief Register the 'zephyr-image' update module 33 | * @return MENDER_OK if successfully registered, error code otherwise 34 | */ 35 | mender_err_t mender_zephyr_image_register_update_module(void); 36 | 37 | #endif /* CONFIG_MENDER_ZEPHYR_IMAGE_UPDATE_MODULE */ 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif /* __cplusplus */ 42 | 43 | #endif /* __MENDER_ZEPHYR_IMAGE_UPDATE_MODULE_H__ */ 44 | -------------------------------------------------------------------------------- /src/include/update-module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file update-module.h 3 | * @brief Mender Update Module interface (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_UPDATE_MODULE_PRIV_H__ 21 | #define __MENDER_UPDATE_MODULE_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | /** 30 | * @brief Unregister all registered update modules 31 | */ 32 | void mender_update_module_unregister_all(void); 33 | 34 | /** 35 | * @brief Get update module for the given artifact type 36 | * @param artifact_type Artifact type to get the update module for 37 | * @return An update module or %NULL if no matching one found 38 | */ 39 | mender_update_module_t *mender_update_module_get(const char *artifact_type); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif /* __cplusplus */ 44 | 45 | #endif /* __MENDER_UPDATE_MODULE_PRIV_H__ */ 46 | -------------------------------------------------------------------------------- /src/include/http-client-event.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file http-client-event.h 3 | * @brief Mender HTTP client event type (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_HTTP_CLIENT_EVENT_PRIV_H__ 22 | #define __MENDER_HTTP_CLIENT_EVENT_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | /** 29 | * @brief HTTP client events 30 | */ 31 | typedef enum { 32 | MENDER_HTTP_EVENT_CONNECTED, /**< Connected to the server */ 33 | MENDER_HTTP_EVENT_DATA_RECEIVED, /**< Data received from the server */ 34 | MENDER_HTTP_EVENT_DISCONNECTED, /**< Disconnected from the server */ 35 | MENDER_HTTP_EVENT_ERROR /**< An error occurred */ 36 | } mender_http_client_event_t; 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif /* __cplusplus */ 41 | 42 | #endif /* __MENDER_HTTP_CLIENT_EVENT_PRIV_H__ */ 43 | -------------------------------------------------------------------------------- /src/platform/memory/zephyr/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alloc.c 3 | * @brief Zephyr-specific implementation of the Mender memory management functions 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | 22 | #include "alloc.h" 23 | 24 | #ifdef CONFIG_MENDER_SEPARATE_HEAP 25 | K_HEAP_DEFINE(mender_heap, CONFIG_MENDER_HEAP_SIZE * 1024); 26 | #endif 27 | 28 | static void * 29 | mender_zephyr_malloc(size_t size) { 30 | #ifdef CONFIG_MENDER_SEPARATE_HEAP 31 | return k_heap_alloc(&mender_heap, size, K_NO_WAIT); 32 | #else 33 | return k_malloc(size); 34 | #endif 35 | } 36 | 37 | static void * 38 | mender_zephyr_realloc(void *ptr, size_t size) { 39 | #ifdef CONFIG_MENDER_SEPARATE_HEAP 40 | return k_heap_realloc(&mender_heap, ptr, size, K_NO_WAIT); 41 | #else 42 | return k_realloc(ptr, size); 43 | #endif 44 | } 45 | 46 | static void 47 | mender_zephyr_free(void *ptr) { 48 | #ifdef CONFIG_MENDER_SEPARATE_HEAP 49 | k_heap_free(&mender_heap, ptr); 50 | #else 51 | k_free(ptr); 52 | #endif 53 | } 54 | 55 | void 56 | mender_set_platform_allocation_funcs(void) { 57 | mender_set_allocation_funcs(mender_zephyr_malloc, mender_zephyr_realloc, mender_zephyr_free); 58 | } 59 | -------------------------------------------------------------------------------- /src/include/artifact-download-data.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file artifact-download-data.h 3 | * @brief Mender artifact download data definition (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ARTIFACT_DOWNLOAD_DATA_PRIV_H__ 21 | #define __MENDER_ARTIFACT_DOWNLOAD_DATA_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "deployment-data.h" 28 | #include "http-client-event.h" 29 | #include "update-module.h" 30 | 31 | typedef struct mender_artifact_download_data_t { 32 | mender_deployment_data_t *deployment; 33 | mender_update_module_t *update_module; 34 | mender_err_t (*artifact_download_callback)(mender_http_client_event_t event, 35 | void *data, 36 | size_t data_length, 37 | struct mender_artifact_download_data_t *dl_data); 38 | mender_err_t ret; 39 | } mender_artifact_download_data_t; 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif /* __cplusplus */ 44 | 45 | #endif /* __MENDER_ARTIFACT_DOWNLOAD_DATA_PRIV_H__ */ 46 | -------------------------------------------------------------------------------- /include/mender/alloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alloc.h 3 | * @brief Mender memory management functions (public API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ALLOC_H__ 21 | #define __MENDER_ALLOC_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include /* size_t */ 28 | 29 | /** 30 | * Standard parameters and semantics apply to the types and functions below. 31 | */ 32 | typedef void *(*MenderAllocator)(size_t size); 33 | typedef void *(*MenderReallocator)(void *ptr, size_t size); 34 | typedef void (*MenderDeallocator)(void *ptr); 35 | 36 | void *mender_malloc(size_t size); 37 | void *mender_calloc(size_t n, size_t size); 38 | void *mender_realloc(void *ptr, size_t size); 39 | void mender_free(void *ptr); 40 | 41 | /** 42 | * @brief Set memory allocation functions for Mender to use 43 | * @warning This function has to be called before Mender allocates any memory 44 | * @note All three parameters have to be non-%NULL 45 | */ 46 | void mender_set_allocation_funcs(MenderAllocator malloc_func, MenderReallocator realloc_func, MenderDeallocator free_func); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif /* __cplusplus */ 51 | 52 | #endif /* __MENDER_ALLOC_H__ */ 53 | -------------------------------------------------------------------------------- /.github/workflows/check_equivalence_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @file check_equivalence_tests.sh 3 | # @brief Check equivalence tests 4 | # 5 | # Copyright joelguittet and mender-mcu-client contributors 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | # Initialize list of files that are not properly formatted 20 | result="" 21 | 22 | # Check source and header files 23 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.c$|.*\.h$|.*\.cpp$|.*\.hpp$)'` 24 | do 25 | # This grep matches following formats (which are not allowed): 26 | # - "variable == CONSTANT" / "variable != CONSTANT" 27 | # - "function(...) == CONSTANT" / "function(...) != CONSTANT" 28 | # - "table[...] == CONSTANT" / "table[...] != CONSTANT" 29 | # Where CONSTANT can be a definition or a number 30 | # Any number of spaces before and after "==" / "!=" is catched 31 | lines=$(grep "[])a-z][ ]*[!=]=[ ]*[A-Z0-9]" ${source_file} | wc -l) 32 | if [[ ! $lines -eq 0 ]]; then 33 | grep -H -n "[])a-z][ ]*[!=]=[ ]*[A-Z0-9]" ${source_file} 34 | result="${result}\n${source_file}" 35 | fi 36 | done 37 | 38 | # Check result 39 | if [[ ${result} != "" ]]; then 40 | echo "The following files are not properly formatted:" 41 | echo -e $result 42 | exit 1 43 | fi 44 | 45 | exit 0 46 | 47 | -------------------------------------------------------------------------------- /cmake/helper.cmake: -------------------------------------------------------------------------------- 1 | # @file helper.cmake 2 | # @brief Helper for sanitizers 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | function (sanitizer_add_compiler_and_linker_flags CONFIG SANITIZER_BUILD_FLAGS SANITIZER_SHARED_LINKER_FLAGS) 19 | 20 | message (STATUS "Adding the compiler flags flags: ${SANITIZER_BUILD_FLAGS}") 21 | message (STATUS "Adding the linker flags: ${SANITIZER_SHARED_LINKER_FLAGS}") 22 | 23 | set(CMAKE_C_FLAGS_${CONFIG} 24 | "${CMAKE_C_FLAGS_DEBUG} ${SANITIZER_BUILD_FLAGS}" CACHE STRING 25 | "Flags used by the C compiler for ${CONFIG} build type or configuration." FORCE) 26 | 27 | set(CMAKE_CXX_FLAGS_${CONFIG} 28 | "${CMAKE_CXX_FLAGS_DEBUG} ${SANITIZER_BUILD_FLAGS}" CACHE STRING 29 | "Flags used by the C++ compiler for ${CONFIG} build type or configuration." FORCE) 30 | 31 | set(CMAKE_EXE_LINKER_FLAGS_${CONFIG} 32 | "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${SANITIZER_BUILD_FLAGS}" CACHE STRING 33 | "Linker flags to be used to create executables for ${CONFIG} build type." FORCE) 34 | 35 | set(CMAKE_SHARED_LINKER_FLAGS_${CONFIG} 36 | "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${SANITIZER_SHARED_LINKER_FLAGS}" CACHE STRING 37 | "Linker lags to be used to create shared libraries for ${CONFIG} build type." FORCE) 38 | 39 | endfunction () 40 | -------------------------------------------------------------------------------- /src/include/log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log.h 3 | * @brief Mender logging interface (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_LOG_PRIV_H__ 21 | #define __MENDER_LOG_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | /** 30 | * @brief Initialize mender log 31 | * @return MENDER_OK if the function succeeds, error code otherwise 32 | */ 33 | mender_err_t mender_log_init(void); 34 | 35 | /** 36 | * @brief Release mender log 37 | * @return MENDER_OK if the function succeeds, error code otherwise 38 | */ 39 | mender_err_t mender_log_exit(void); 40 | 41 | #ifdef CONFIG_MENDER_DEPLOYMENT_LOGS 42 | /** 43 | * @brief Activate deployment logs saving 44 | * @return MENDER_OK if the function succeeds, error code otherwise 45 | */ 46 | mender_err_t mender_deployment_logs_activate(void); 47 | 48 | /** 49 | * @brief Deactivate deployment logs saving 50 | * @return MENDER_OK if the function succeeds, error code otherwise 51 | */ 52 | mender_err_t mender_deployment_logs_deactivate(void); 53 | #endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif /* __cplusplus */ 58 | 59 | #endif /* __MENDER_LOG_PRIV_H__ */ 60 | -------------------------------------------------------------------------------- /src/include/artifact-download.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file artifact-download.h 3 | * @brief Mender artifact download interface (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ARTIFACT_DOWNLOAD_PRIV_H__ 21 | #define __MENDER_ARTIFACT_DOWNLOAD_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "artifact.h" 28 | #include "deployment-data.h" 29 | #include "update-module.h" 30 | #include "utils.h" 31 | 32 | /** 33 | * @brief Download artifact from the given URI 34 | * @param uri URI to download the artifact from 35 | * @param deployment_data Deployment data to extend with artifact metadata 36 | * @param update_module A place to store the update module selected for the artifact 37 | * @param artifact_ctx A place to store the the artifact context representing the artifact 38 | */ 39 | mender_err_t mender_download_artifact(const char *uri, 40 | mender_deployment_data_t *deployment_data, 41 | mender_update_module_t **update_module, 42 | mender_artifact_ctx_t **artifact_ctx); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif /* __cplusplus */ 47 | 48 | #endif /* __MENDER_ARTIFACT_DOWNLOAD_PRIV_H__ */ 49 | -------------------------------------------------------------------------------- /src/include/client.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file client.h 3 | * @brief Mender MCU client implementation (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_CLIENT_PRIV_H__ 22 | #define __MENDER_CLIENT_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include 29 | 30 | /** 31 | * @brief Mender client states 32 | */ 33 | typedef enum { 34 | MENDER_CLIENT_STATE_INITIALIZATION, /**< Perform initialization */ 35 | MENDER_CLIENT_STATE_OPERATIONAL, /**< Under standard operation */ 36 | MENDER_CLIENT_STATE_PENDING_REBOOT, /**< Waiting for a reboot */ 37 | } mender_client_state_t; 38 | #define N_MENDER_CLIENT_STATES ((size_t)MENDER_CLIENT_STATE_PENDING_REBOOT) 39 | 40 | /** 41 | * @brief Mender client state 42 | */ 43 | extern mender_client_state_t mender_client_state; 44 | 45 | /** 46 | * @brief Ensures the client has a network connection 47 | * @return MENDER_DONE if already connected, 48 | * MENDER_OK if successfully connected, 49 | * MENDER_FAIL otherwise 50 | */ 51 | mender_err_t mender_client_ensure_connected(void); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif /* __cplusplus */ 56 | 57 | #endif /* __MENDER_CLIENT_PRIV_H__ */ 58 | -------------------------------------------------------------------------------- /cmake/git_helper.cmake: -------------------------------------------------------------------------------- 1 | # @file git_helper.cmake 2 | # @brief Git helper functions 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | # Copied from Zephyr OS project: 19 | # https://github.com/zephyrproject-rtos/zephyr/blob/v4.0.0/cmake/modules/git.cmake 20 | 21 | include_guard(GLOBAL) 22 | 23 | find_package(Git QUIET) 24 | 25 | # Usage: 26 | # git_describe( ) 27 | # 28 | # Helper function to get a short GIT description associated with a directory. 29 | # OUTPUT is set to the output of `git describe --abbrev=12 --always` as run 30 | # from DIR. 31 | # 32 | function(git_describe DIR OUTPUT) 33 | if(GIT_FOUND) 34 | execute_process( 35 | COMMAND ${GIT_EXECUTABLE} describe --abbrev=12 --always 36 | WORKING_DIRECTORY ${DIR} 37 | OUTPUT_VARIABLE DESCRIPTION 38 | OUTPUT_STRIP_TRAILING_WHITESPACE 39 | ERROR_STRIP_TRAILING_WHITESPACE 40 | ERROR_VARIABLE stderr 41 | RESULT_VARIABLE return_code 42 | ) 43 | if(return_code) 44 | message(STATUS "git describe failed: ${stderr}") 45 | elseif(NOT "${stderr}" STREQUAL "") 46 | message(STATUS "git describe warned: ${stderr}") 47 | else() 48 | # Save output 49 | set(${OUTPUT} ${DESCRIPTION} PARENT_SCOPE) 50 | endif() 51 | endif() 52 | endfunction() 53 | -------------------------------------------------------------------------------- /src/platform/tls/generic/weak/tls.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tls.c 3 | * @brief Mender TLS interface for weak platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #include "tls.h" 22 | 23 | MENDER_FUNC_WEAK mender_err_t 24 | mender_tls_init(void) { 25 | 26 | /* Nothing to do */ 27 | return MENDER_OK; 28 | } 29 | 30 | MENDER_FUNC_WEAK mender_err_t 31 | mender_tls_init_authentication_keys(mender_err_t (*get_user_provided_keys)(char **user_provided_key, size_t *user_provided_key_length), bool recommissioning) { 32 | 33 | (void)get_user_provided_keys; 34 | (void)recommissioning; 35 | 36 | /* Nothing to do */ 37 | return MENDER_NOT_IMPLEMENTED; 38 | } 39 | 40 | MENDER_FUNC_WEAK mender_err_t 41 | mender_tls_get_public_key_pem(char **public_key) { 42 | 43 | (void)public_key; 44 | 45 | /* Nothing to do */ 46 | return MENDER_NOT_IMPLEMENTED; 47 | } 48 | 49 | MENDER_FUNC_WEAK mender_err_t 50 | mender_tls_sign_payload(char *payload, char **signature, size_t *signature_length) { 51 | 52 | (void)payload; 53 | (void)signature; 54 | (void)signature_length; 55 | 56 | /* Nothing to do */ 57 | return MENDER_NOT_IMPLEMENTED; 58 | } 59 | 60 | MENDER_FUNC_WEAK mender_err_t 61 | mender_tls_exit(void) { 62 | 63 | /* Nothing to do */ 64 | return MENDER_OK; 65 | } 66 | -------------------------------------------------------------------------------- /.github/workflows/check_include_guards.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @file check_include_guards.sh 3 | # @brief Check include guards 4 | # 5 | # Copyright joelguittet and mender-mcu-client contributors 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | # Initialize list of files that are not properly formatted 20 | result="" 21 | 22 | # Check header files 23 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.h$|.*\.hpp$)'` 24 | do 25 | f_basename="$(basename $source_file)" 26 | uppercase="${f_basename^^}" 27 | guard="MENDER_${uppercase//[^A-Z]/_}" 28 | if expr "$source_file" : "src/include/.*" >/dev/null; then 29 | # private headers have _PRIV_ in the guards 30 | guard="${guard%%_H}_PRIV_H" 31 | fi 32 | pcregrep -Me "#ifndef __${guard}__\n#define __${guard}__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif /\* __cplusplus \*/" ${source_file} > /dev/null 2>&1 33 | if [[ ! $? -eq 0 ]]; then 34 | result="${result}\n${source_file}" 35 | else 36 | pcregrep -Me "#ifdef __cplusplus\n}\n#endif /\* __cplusplus \*/\n\n#endif /\* __${guard}__ \*/" ${source_file} > /dev/null 2>&1 37 | if [[ ! $? -eq 0 ]]; then 38 | result="${result}\n${source_file}" 39 | fi 40 | fi 41 | done 42 | 43 | # Check result 44 | if [[ ${result} != "" ]]; then 45 | echo "The following files have wrong or missing include guards:" 46 | echo -e $result 47 | exit 1 48 | fi 49 | 50 | exit 0 51 | 52 | -------------------------------------------------------------------------------- /src/core/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alloc.c 3 | * @brief Platform-independent parts of the Mender memory management implementation 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include /* malloc(),... */ 21 | #include /* memset() */ 22 | 23 | #include "alloc.h" 24 | 25 | static MenderAllocator malloc_fn = NULL; 26 | static MenderReallocator realloc_fn = NULL; 27 | static MenderDeallocator free_fn = NULL; 28 | 29 | void 30 | mender_set_allocation_funcs(MenderAllocator malloc_func, MenderReallocator realloc_func, MenderDeallocator free_func) { 31 | malloc_fn = malloc_func; 32 | realloc_fn = realloc_func; 33 | free_fn = free_func; 34 | } 35 | 36 | void * 37 | mender_malloc(size_t size) { 38 | if (NULL == malloc_fn) { 39 | return malloc(size); 40 | } 41 | return malloc_fn(size); 42 | } 43 | 44 | void * 45 | mender_calloc(size_t n, size_t size) { 46 | void *ret = mender_malloc(n * size); 47 | if (NULL != ret) { 48 | memset(ret, 0, n * size); 49 | } 50 | return ret; 51 | } 52 | 53 | void * 54 | mender_realloc(void *ptr, size_t size) { 55 | if (NULL == realloc_fn) { 56 | return realloc(ptr, size); 57 | } 58 | return realloc_fn(ptr, size); 59 | } 60 | 61 | void 62 | mender_free(void *ptr) { 63 | if (NULL == free_fn) { 64 | free(ptr); 65 | return; 66 | } 67 | free_fn(ptr); 68 | } 69 | -------------------------------------------------------------------------------- /src/platform/certs/zephyr/certs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file certs.c 3 | * @brief Mender MCU Certificate for zephyr 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include /* size_t */ 21 | #include 22 | 23 | #include "certs.h" 24 | #include "log.h" 25 | #include 26 | 27 | static const unsigned char dormant_certificate_a[] = { 28 | #include "dormant_a.cer.inc" 29 | }; 30 | 31 | static const unsigned char dormant_certificate_b[] = { 32 | #include "dormant_b.cer.inc" 33 | }; 34 | 35 | /* @note See https://docs.zephyrproject.org/4.0.0/doxygen/html/group__tls__credentials.html#ga640ff6dd3eb4d5017feaab6fab2bb2f7 */ 36 | mender_err_t 37 | mender_add_dormant_certs(void) { 38 | int ret; 39 | 40 | // Add main certificate 41 | ret = tls_credential_add( 42 | CONFIG_MENDER_NET_CA_CERTIFICATE_TAG_DORMANT_A, TLS_CREDENTIAL_CA_CERTIFICATE, dormant_certificate_a, sizeof(dormant_certificate_a)); 43 | 44 | if (0 != ret) { 45 | mender_log_error("Failed to add dormant certificate A. (result = %d, error: %s)", ret, strerror(errno)); 46 | return MENDER_FAIL; 47 | } 48 | 49 | // Add backup certificate 50 | ret = tls_credential_add( 51 | CONFIG_MENDER_NET_CA_CERTIFICATE_TAG_DORMANT_B, TLS_CREDENTIAL_CA_CERTIFICATE, dormant_certificate_b, sizeof(dormant_certificate_b)); 52 | 53 | if (0 != ret) { 54 | mender_log_error("Failed to add dormant certificate B. (result = %d, error: %s)", ret, strerror(errno)); 55 | return MENDER_FAIL; 56 | } 57 | 58 | return MENDER_OK; 59 | } 60 | -------------------------------------------------------------------------------- /src/platform/net/generic/weak/http.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file http.c 3 | * @brief Mender HTTP interface for weak platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "http.h" 21 | #include "utils.h" 22 | 23 | /* just some reasonable value, it's never used */ 24 | MENDER_FUNC_WEAK const size_t mender_http_recv_buf_length = 512; 25 | 26 | MENDER_FUNC_WEAK mender_err_t 27 | mender_http_init(mender_http_config_t *config) { 28 | 29 | (void)config; 30 | 31 | /* Nothing to do */ 32 | return MENDER_OK; 33 | } 34 | 35 | MENDER_FUNC_WEAK mender_err_t 36 | mender_http_perform(char *jwt, 37 | char *path, 38 | mender_http_method_t method, 39 | char *payload, 40 | char *signature, 41 | mender_err_t (*callback)(mender_http_client_event_t, void *, size_t, void *), 42 | void *params, 43 | int *status) { 44 | 45 | (void)jwt; 46 | (void)path; 47 | (void)method; 48 | (void)payload; 49 | (void)signature; 50 | (void)callback; 51 | (void)params; 52 | (void)status; 53 | 54 | /* Nothing to do */ 55 | return MENDER_NOT_IMPLEMENTED; 56 | } 57 | 58 | MENDER_FUNC_WEAK mender_err_t 59 | mender_http_artifact_download(MENDER_ARG_UNUSED const char *uri, MENDER_ARG_UNUSED mender_artifact_download_data_t *dl_data, MENDER_ARG_UNUSED int *status) { 60 | return MENDER_NOT_IMPLEMENTED; 61 | } 62 | 63 | MENDER_FUNC_WEAK mender_err_t 64 | mender_http_exit(void) { 65 | 66 | /* Nothing to do */ 67 | return MENDER_OK; 68 | } 69 | -------------------------------------------------------------------------------- /src/platform/log/posix/log.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log.c 3 | * @brief Mender logging interface for Posix platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | #include "log.h" 22 | 23 | mender_err_t 24 | mender_log_init(void) { 25 | 26 | /* Nothing to do */ 27 | return MENDER_OK; 28 | } 29 | 30 | mender_err_t 31 | mender_log_print(uint8_t level, const char *filename, const char *function, int line, char *format, ...) { 32 | 33 | (void)function; 34 | struct timespec now; 35 | char log[256] = { 0 }; 36 | 37 | /* Get time */ 38 | clock_gettime(CLOCK_REALTIME, &now); 39 | 40 | /* Format message */ 41 | va_list args; 42 | va_start(args, format); 43 | vsnprintf(log, sizeof(log), format, args); 44 | va_end(args); 45 | 46 | /* Switch depending log level */ 47 | switch (level) { 48 | case MENDER_LOG_LEVEL_ERR: 49 | printf("[%ld] %s (%d): %s\n", now.tv_sec, filename, line, log); 50 | break; 51 | case MENDER_LOG_LEVEL_WRN: 52 | printf("[%ld] %s (%d): %s\n", now.tv_sec, filename, line, log); 53 | break; 54 | case MENDER_LOG_LEVEL_INF: 55 | printf("[%ld] %s (%d): %s\n", now.tv_sec, filename, line, log); 56 | break; 57 | case MENDER_LOG_LEVEL_DBG: 58 | printf("[%ld] %s (%d): %s\n", now.tv_sec, filename, line, log); 59 | break; 60 | default: 61 | break; 62 | } 63 | 64 | return MENDER_OK; 65 | } 66 | 67 | mender_err_t 68 | mender_log_exit(void) { 69 | 70 | /* Nothing to do */ 71 | return MENDER_OK; 72 | } 73 | -------------------------------------------------------------------------------- /src/platform/sha/generic/mbedtls/sha.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sha.c 3 | * @brief Mender SHA interface for MbedTLS platform 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "alloc.h" 21 | #include "sha.h" 22 | #include "log.h" 23 | 24 | #include 25 | 26 | mender_err_t 27 | mender_sha256_begin(mender_sha256_context_t *context) { 28 | assert(NULL != context); 29 | 30 | mbedtls_sha256_context *ctx = mender_malloc(sizeof(mbedtls_sha256_context)); 31 | if (NULL == ctx) { 32 | mender_log_error("Unable to allocate memory"); 33 | return MENDER_FAIL; 34 | } 35 | 36 | mbedtls_sha256_init(ctx); 37 | if (0 != mbedtls_sha256_starts(ctx, 0 /* Use SHA-256, not SHA-224 */)) { 38 | mender_log_error("Failed to start SHA-256 checksum calculation"); 39 | mender_free(ctx); 40 | return MENDER_FAIL; 41 | } 42 | 43 | *context = ctx; 44 | return MENDER_OK; 45 | } 46 | 47 | mender_err_t 48 | mender_sha256_update(mender_sha256_context_t context, const unsigned char *input, size_t length) { 49 | assert(NULL != context); 50 | 51 | mbedtls_sha256_context *ctx = context; 52 | if (0 != mbedtls_sha256_update(ctx, input, length)) { 53 | mender_log_error("Failed to update SHA-256 checksum calculation"); 54 | return MENDER_FAIL; 55 | } 56 | 57 | return MENDER_OK; 58 | } 59 | 60 | mender_err_t 61 | mender_sha256_finish(mender_sha256_context_t context, unsigned char *output) { 62 | mender_err_t ret = MENDER_OK; 63 | mbedtls_sha256_context *ctx = context; 64 | if (NULL != ctx) { 65 | if (NULL != output) { 66 | if (0 != mbedtls_sha256_finish(ctx, output)) { 67 | mender_log_error("Failed to finish SHA-256 checksum calculation"); 68 | ret = MENDER_FAIL; 69 | } 70 | } 71 | mbedtls_sha256_free(ctx); 72 | mender_free(ctx); 73 | } 74 | return ret; 75 | } 76 | -------------------------------------------------------------------------------- /src/core/error-counters.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file error-counters.c 3 | * @brief Mender Error counters implementation 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | 22 | #include "error-counters.h" 23 | #include "log.h" 24 | #include "utils.h" 25 | 26 | #if CONFIG_MENDER_ERRORS_THRESHOLD_NET > 0 27 | 28 | static uint8_t net_errors = 0; 29 | #if CONFIG_MENDER_ERRORS_THRESHOLD_NET > UINT8_MAX 30 | #error "CONFIG_MENDER_ERRORS_THRESHOLD_NET must be <= UINT8_MAX" 31 | #endif 32 | 33 | mender_err_t 34 | mender_err_count_net_inc(void) { 35 | if (net_errors < UINT8_MAX) { 36 | net_errors++; 37 | } 38 | if (net_errors > CONFIG_MENDER_ERRORS_THRESHOLD_NET) { 39 | mender_log_warning("Network errors limit exceeded"); 40 | return MENDER_FAIL; 41 | } 42 | return MENDER_OK; 43 | } 44 | 45 | mender_err_t 46 | mender_err_count_net_check(void) { 47 | if (net_errors > CONFIG_MENDER_ERRORS_THRESHOLD_NET) { 48 | mender_log_warning("Network errors limit exceeded"); 49 | return MENDER_FAIL; 50 | } 51 | return MENDER_OK; 52 | } 53 | 54 | mender_err_t 55 | mender_err_count_net_reset(void) { 56 | net_errors = 0; 57 | return MENDER_OK; 58 | } 59 | #endif /* CONFIG_MENDER_ERRORS_THRESHOLD_NET > 0 */ 60 | 61 | #if CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT > 0 62 | 63 | static uint8_t reboot_errors = 0; 64 | #if CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT > UINT8_MAX 65 | #error "CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT must be <= UINT8_MAX" 66 | #endif 67 | 68 | mender_err_t 69 | mender_err_count_reboot_inc(void) { 70 | if (reboot_errors < UINT8_MAX) { 71 | reboot_errors++; 72 | } 73 | if (reboot_errors > CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT) { 74 | return MENDER_FAIL; 75 | } 76 | return MENDER_OK; 77 | } 78 | 79 | mender_err_t 80 | mender_err_count_reboot_reset(void) { 81 | reboot_errors = 0; 82 | return MENDER_OK; 83 | } 84 | #endif /* CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT > 0 */ 85 | -------------------------------------------------------------------------------- /src/include/tls.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tls.h 3 | * @brief Mender TLS interface (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_TLS_PRIV_H__ 22 | #define __MENDER_TLS_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include "utils.h" 29 | 30 | /** 31 | * @brief Initialize mender TLS 32 | * @return MENDER_OK if the function succeeds, error code otherwise 33 | */ 34 | mender_err_t mender_tls_init(void); 35 | 36 | /** 37 | * @brief Initialize mender TLS authentication keys 38 | * @param callback to get buffer of user provided key 39 | * @param recommissioning Perform recommissioning (if supported by the platform) 40 | * @return MENDER_OK if the function succeeds, error code otherwise 41 | */ 42 | mender_err_t mender_tls_init_authentication_keys(mender_err_t (*get_user_provided_keys)(char **user_provided_key, size_t *user_provided_key_length), 43 | bool recommissioning); 44 | 45 | /** 46 | * @brief Get public key (PEM format suitable to be integrated in mender authentication request) 47 | * @param public_key Public key, NULL if an error occurred 48 | * @return MENDER_OK if the function succeeds, error code otherwise 49 | */ 50 | mender_err_t mender_tls_get_public_key_pem(char **public_key); 51 | 52 | /** 53 | * @brief Sign payload 54 | * @param payload Payload to sign 55 | * @param signature Signature of the payload 56 | * @param signature_length Length of the signature buffer, updated to the length of the signature 57 | * @return MENDER_OK if the function succeeds, error code otherwise 58 | */ 59 | mender_err_t mender_tls_sign_payload(char *payload, char **signature, size_t *signature_length); 60 | 61 | /** 62 | * @brief Release mender TLS 63 | * @return MENDER_OK if the function succeeds, error code otherwise 64 | */ 65 | mender_err_t mender_tls_exit(void); 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif /* __cplusplus */ 70 | 71 | #endif /* __MENDER_TLS_PRIV_H__ */ 72 | -------------------------------------------------------------------------------- /src/platform/net/zephyr/net.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file net.h 3 | * @brief Mender network common file interface for Zephyr platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_NET_H__ 21 | #define __MENDER_NET_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "utils.h" 28 | 29 | /** 30 | * @brief Returns host name, port and URL from path 31 | * @param path Path 32 | * @param config_host Host name from configuration 33 | * @param host Host name 34 | * @param port Port as string 35 | * @param url URL 36 | * @return MENDER_OK if the function succeeds, error code otherwise 37 | */ 38 | mender_err_t mender_net_get_host_port_url(const char *path, const char *config_host, char **host, char **port, char **url); 39 | 40 | /** 41 | * @brief Add a header to the header list 42 | * @param header_list Header list 43 | * @param header_list_size Header list size 44 | * @param header Header to add 45 | * @return MENDER_OK if the function succeeds, MENDER_FAIL otherwise 46 | */ 47 | mender_err_t header_add(const char **header_list, size_t header_list_size, const char *header); 48 | 49 | /** 50 | * @brief Allocate and add a header to the header list 51 | * @param header_list Header list 52 | * @param header_list_size Header list size 53 | * @param format Format string 54 | * @return Pointer to the allocated string if the function succeeds, NULL otherwise 55 | */ 56 | char *header_alloc_and_add(const char **header_list, size_t header_list_size, const char *format, ...); 57 | 58 | /** 59 | * @brief Perform connection with the server 60 | * @param host Host 61 | * @param port Port 62 | * @return socket descriptor if the function succeeds, -1 otherwise 63 | */ 64 | int mender_net_connect(const char *host, const char *port); 65 | 66 | /** 67 | * @brief Close connection with the server 68 | * @param sock Client socket 69 | * @return MENDER_OK if the function succeeds, error code otherwise 70 | */ 71 | mender_err_t mender_net_disconnect(int sock); 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif /* __cplusplus */ 76 | 77 | #endif /* __MENDER_NET_H__ */ 78 | -------------------------------------------------------------------------------- /src/include/inventory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file inventory.h 3 | * @brief Mender MCU Inventory implementation (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_INVENTORY_PRIV_H__ 22 | #define __MENDER_INVENTORY_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include 29 | 30 | /** 31 | * @brief Initialize mender inventory 32 | * @param interval The interval to perform inventory updates at 33 | * @param device_type Device type 34 | * @param backoff_interval Backoff interval on retry errors 35 | * @param max_backoff_interval Max backoff interval on retry errors 36 | * @return MENDER_OK if the function succeeds, error code otherwise 37 | */ 38 | mender_err_t mender_inventory_init(uint32_t interval, const char *dev_type, uint16_t backoff_interval, uint16_t max_backoff_interval); 39 | 40 | /** 41 | * @brief Reset persistent inventory 42 | * @return MENDER_OK in case of success, error code otherwise 43 | * @note The persistent inventory callbacks are called to get fresh data the next time inventory data 44 | * is needed. 45 | */ 46 | mender_err_t mender_inventory_reset_persistent(void); 47 | 48 | /** 49 | * @brief Add default inventory callbacks 50 | * @return MENDER_OK in case of success, error code otherwise 51 | */ 52 | mender_err_t mender_inventory_add_default_callbacks(void); 53 | 54 | /** 55 | * @brief Activate mender inventory 56 | * @return MENDER_OK if the function succeeds, error code otherwise 57 | */ 58 | mender_err_t mender_inventory_activate(void); 59 | 60 | /** 61 | * @brief Deactivate mender inventory 62 | * @note This function stops synchronization with the server 63 | * @return MENDER_OK if the function succeeds, error code otherwise 64 | */ 65 | mender_err_t mender_inventory_deactivate(void); 66 | 67 | /** 68 | * @brief Trigger execution of the inventory work 69 | * @return MENDER_OK if the function succeeds, error code otherwise 70 | */ 71 | mender_err_t mender_inventory_execute(void); 72 | 73 | /** 74 | * @brief Release mender inventory 75 | * @return MENDER_OK if the function succeeds, error code otherwise 76 | */ 77 | mender_err_t mender_inventory_exit(void); 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif /* __cplusplus */ 82 | 83 | #endif /* __MENDER_INVENTORY_PRIV_H__ */ 84 | -------------------------------------------------------------------------------- /src/include/sha.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sha.h 3 | * @brief Mender SHA interface (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_SHA_PRIV_H__ 21 | #define __MENDER_SHA_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "utils.h" /* mender_err_t */ 28 | 29 | /** 30 | * @brief This type is just a pointer to whatever data structure is required by 31 | * a specific platform implementation. This data structure will be 32 | * allocated on the heap by mender_sha256_begin function and must be 33 | * free'd in the mender_sha256_finish function. 34 | */ 35 | typedef void *mender_sha256_context_t; 36 | 37 | /** 38 | * @brief Size of SHA-256 digest buffer in Bytes. 39 | */ 40 | #define MENDER_DIGEST_BUFFER_SIZE 32 41 | 42 | /** 43 | * @brief Initializes a SHA-256 context and starts a checksum calculation. 44 | * @param context The SHA-256 context to be initialized. This must not be NULL. 45 | * @note A call to mender_sha256_begin must be followed by a call to 46 | * mender_sha256_finish in order to release resources. 47 | * @return MENDER_OK on success, otherwise error code. 48 | */ 49 | mender_err_t mender_sha256_begin(mender_sha256_context_t *context); 50 | 51 | /** 52 | * @brief Feeds an input buffer into an ongoing SHA-256 checksum calculation. 53 | * @param context The SHA-256 context. This must have been initialized. 54 | * @param input The buffer holding the data to be fed. 55 | * @param length The length of the input data in Bytes. 56 | * @return MENDER_OK on success, otherwise error code. 57 | */ 58 | mender_err_t mender_sha256_update(mender_sha256_context_t context, const unsigned char *input, size_t length); 59 | 60 | /** 61 | * @brief Finishes the SHA-256 checksum calculation, writes the result to the 62 | * output buffer and clears the SHA-256 context. 63 | * @param context The SHA-256 context to be cleared. If NULL is passed, no 64 | * operation is performed. 65 | * @param output A writeable buffer of MENDER_DIGEST_BUFFER_SIZE Bytes for 66 | * SHA-256 checksum. If NULL is passed, the function will only 67 | * clear the SHA-256 context. 68 | * @return MENDER_OK on success, otherwise error code. 69 | */ 70 | mender_err_t mender_sha256_finish(mender_sha256_context_t context, unsigned char *output); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif /* __cplusplus */ 75 | 76 | #endif /* __MENDER_SHA_PRIV_H__ */ 77 | -------------------------------------------------------------------------------- /include/mender/inventory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file inventory.h 3 | * @brief Mender MCU Inventory implementation (public API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_INVENTORY_H__ 21 | #define __MENDER_INVENTORY_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | #ifndef CONFIG_MENDER_CLIENT_INVENTORY_DISABLE 30 | 31 | /** 32 | * @brief Inventory callback type 33 | * @param inventory Output argument for the inventory items array pointer 34 | * @param inventory_len Length of the array pointed to by #inventory (limited by the type to 255 35 | * items which should be more than enough) 36 | * @return %MENDER_OK in case of success, error otherwise 37 | */ 38 | typedef mender_err_t(MenderInventoryCallback)(mender_keystore_t **inventory, uint8_t *inventory_len); 39 | 40 | /** 41 | * @brief Add mender inventory callback 42 | * @param callback A function to call to obtain inventory information 43 | * @param persistent Whether the inventory information is persistent or dynamic (see notes below) 44 | * @return MENDER_OK if the function succeeds, error code otherwise 45 | * @note Persistent inventory data is only obtained and sent to the server once in the run of the 46 | * client, i.e. during the first successful inventory submission. Dynamic inventory data is 47 | * obtained and sent to the server at every inventory submission (interval). 48 | * @note Persistent inventory data is *considered static*, dynamic data is considered 49 | * heap-allocated, with ownership being transferred (IOW, the Mender client deallocates the 50 | * data when no longer needed). This applies to both the container (array) and the actual 51 | * data (key-value pairs). 52 | */ 53 | mender_err_t mender_inventory_add_callback(MenderInventoryCallback callback, bool persistent); 54 | 55 | /** 56 | * @brief Function used to trigger execution of the inventory work 57 | * @note Calling this function is optional when the periodic execution of the work is configured 58 | * @note It only permits to execute the work as soon as possible to synchronize inventory 59 | * @return MENDER_OK if the function succeeds, error code otherwise 60 | */ 61 | mender_err_t mender_inventory_execute(void); 62 | 63 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_DISABLE */ 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif /* __cplusplus */ 68 | 69 | #endif /* __MENDER_INVENTORY_H__ */ 70 | -------------------------------------------------------------------------------- /tests/smoke/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # @file CMakeLists.txt 2 | # @brief Test application CMakeLists file 3 | # 4 | # Copyright joelguittet and mender-mcu-client contributors 5 | # Copyright Northern.tech AS 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | cmake_minimum_required(VERSION 3.16.3) 20 | 21 | # CMake configurations 22 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE) 23 | if(NOT CMAKE_BUILD_TYPE) 24 | set(CMAKE_BUILD_TYPE Release) 25 | endif() 26 | 27 | # C++11 28 | set(CMAKE_CXX_STANDARD 11) 29 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 30 | set(CMAKE_CXX_EXTENSIONS OFF) 31 | 32 | # Define PROJECT_BASE_NAME 33 | set(PROJECT_BASE_NAME mender-mcu-client) 34 | message("Configuring for ${PROJECT_BASE_NAME} - Build type is ${CMAKE_BUILD_TYPE}") 35 | 36 | # Define project 37 | project(${PROJECT_BASE_NAME} LANGUAGES C ASM) 38 | 39 | # Declare the executable first, so that we can add flags and sources later on 40 | set(EXECUTABLE_NAME ${PROJECT_BASE_NAME}.elf) 41 | message("Executable name: ${EXECUTABLE_NAME}") 42 | add_executable(${EXECUTABLE_NAME}) 43 | 44 | # Define compile options 45 | if (CMAKE_BUILD_TYPE MATCHES "Debug") 46 | target_compile_options(${EXECUTABLE_NAME} PRIVATE -O1 -g) 47 | target_compile_definitions(${EXECUTABLE_NAME} PRIVATE DEBUG) 48 | else() 49 | target_compile_options(${EXECUTABLE_NAME} PRIVATE -Os) 50 | endif() 51 | 52 | # Add sources 53 | file(GLOB_RECURSE SOURCES_TEMP "${CMAKE_CURRENT_LIST_DIR}/*.c") 54 | target_sources(${EXECUTABLE_NAME} PRIVATE ${SOURCES_TEMP}) 55 | 56 | # Include mender-mcu-client library 57 | add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../target/posix" build) 58 | 59 | # Add definitions to configure the client 60 | if(CONFIG_MENDER_PLATFORM_NET_TYPE MATCHES "zephyr") 61 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_NET_SOCKETS_SOCKOPT_TLS) 62 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_NET_CA_CERTIFICATE_TAG=1) 63 | endif() 64 | if(CONFIG_MENDER_PLATFORM_STORAGE_TYPE MATCHES "zephyr/nvs") 65 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_STORAGE_NVS_SECTOR_COUNT=4) 66 | endif() 67 | 68 | # Link the mender-mcu-client library 69 | if(CONFIG_MENDER_PLATFORM_NET_TYPE MATCHES "generic/curl") 70 | target_link_libraries(mender-mcu-client PRIVATE curl) 71 | endif() 72 | if(CONFIG_MENDER_PLATFORM_SCHEDULER_TYPE MATCHES "posix") 73 | target_link_libraries(mender-mcu-client PRIVATE rt) 74 | endif() 75 | 76 | # Link the executable with the mender-mcu-client library 77 | target_link_libraries(${EXECUTABLE_NAME} mender-mcu-client pthread) 78 | -------------------------------------------------------------------------------- /docs/flashwear.md: -------------------------------------------------------------------------------- 1 | ## Flash wear estimation 2 | 3 | - $N$: Number of deployments during the lifetime of a device. 4 | - $F$: Probability of failure during a deployment. 5 | - $W$: Maximum number of state transitions, defined by `MENDER_MAX_STATE_DATA_STORE_COUNT`. 6 | - $B$: Number of writes for a successful deployment. 7 | - $K$: Total number of writes to the flash. 8 | 9 | We write to the flash in two places: 10 | 1. if no authentication keys are provided by the user, the client will generate authentication keys and write them to the store 11 | 2. during a deployment to keep track of the deployment data, the Artifact being installed and the deployment logs 12 | 13 | Most of the flash wear will occur during a deployment. The deployment data, which -- amongst others -- contains the current state during 14 | a deployment, is written between each state transition. This is what allows Mender to be robust and do atomic deployments. Unless 15 | `MENDER_DEPLOYMENT_LOGS` is disabled, we write the deployment logs to the flash; these are error or warning logs that have occurred during 16 | a deployment and that are sent to the Mender server on failed deployments for further diagnostics and troubleshooting. 17 | 18 | On a successful deployment we update the local provides database with the meta-data from the Artifact that was installed, combining 19 | provides, Artifact name and clears provides. 20 | 21 | A successful deployment using the zephyr-image update module will go through 6 state transitions and write the provides and the Artifact 22 | name to the flash. This results in around $K = 6+2$ writes. 23 | 24 | Based on numbers seen in production, we can expect a 5% failure rate for deployments. If we factor in the estimated failure percentage, we 25 | can roughly estimate the expected amount of writes during the lifetime of a device: 26 | 27 | $K = N \times ( (W \times F ) + (B \times (1 - F)))$ 28 | 29 | If we plot in the following values: 30 | - $N = 100$ 31 | - $F = 0.05$ 32 | - $W = 28$ (the default value of `MENDER_MAX_STATE_DATA_STORE_COUNT`) 33 | - $B = 8$ (the amount of writes for a successful deployment with zephyr-image update module) 34 | 35 | we get an estimated $K = 900$ writes to the flash during the lifetime of a device. 36 | 37 | The equation aims at creating an upper estimate; estimating the exact number of writes during a deployment is next to impossible due to the 38 | unpredictability of the errors and warnings that may occur. However, we can still be fairly sure that the number of writes will be lower than 39 | the estimate, as its based on the maximum number of state transitions during a deployment. The equation does _not_ take the deployment logs 40 | directly into account, but considering the low probability of any failed deployment reaching the maximum state count, we can be rather confident 41 | in the fact that the total number of writes will fall within the estimate. 42 | 43 | The flash wear, including the number of erased sectors, physical sectors used, wear leveling, and more, is influenced by the low-level 44 | implementation of the API, such as NVS in Zephyr. The estimate we provide reflects expected writes, but actual wear is affected by various 45 | device-specific factors beyond our control. 46 | -------------------------------------------------------------------------------- /src/core/update-module.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file update-module.c 3 | * @brief Mender update Module implementation 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include "alloc.h" 21 | #include "log.h" 22 | #include "update-module.h" 23 | #include "utils.h" 24 | 25 | /** 26 | * @brief Mender update modules list 27 | */ 28 | static mender_update_module_t **update_modules_list = NULL; 29 | static size_t update_modules_count = 0; 30 | 31 | mender_err_t 32 | mender_update_module_register(mender_update_module_t *update_module) { 33 | assert(NULL != update_module); 34 | 35 | mender_update_module_t **tmp; 36 | mender_err_t ret = MENDER_OK; 37 | 38 | for (size_t i = 0; i < update_modules_count; i++) { 39 | if (StringEqual(update_module->artifact_type, update_modules_list[i]->artifact_type)) { 40 | mender_log_error("Not registering another update module for artifact type: %s", update_module->artifact_type); 41 | return MENDER_FAIL; 42 | } 43 | } 44 | 45 | /* Add mender artifact type to the list */ 46 | if (NULL == (tmp = (mender_update_module_t **)mender_realloc(update_modules_list, (update_modules_count + 1) * sizeof(mender_update_module_t *)))) { 47 | mender_log_error("Unable to allocate memory for update modules list"); 48 | ret = MENDER_FAIL; 49 | goto END; 50 | } 51 | update_modules_list = tmp; 52 | update_modules_list[update_modules_count++] = update_module; 53 | ret = MENDER_OK; 54 | 55 | END: 56 | 57 | return ret; 58 | } 59 | 60 | void 61 | mender_update_module_unregister_all(void) { 62 | if (NULL != update_modules_list) { 63 | for (size_t update_module_index = 0; update_module_index < update_modules_count; update_module_index++) { 64 | mender_free(update_modules_list[update_module_index]); 65 | } 66 | FREE_AND_NULL(update_modules_list); 67 | } 68 | update_modules_count = 0; 69 | } 70 | 71 | mender_update_module_t * 72 | mender_update_module_get(const char *artifact_type) { 73 | mender_update_module_t *ret = NULL; 74 | 75 | /* Treatment depending of the type */ 76 | if (NULL != update_modules_list) { 77 | for (size_t update_module_index = 0; (NULL == ret) && (update_module_index < update_modules_count); update_module_index++) { 78 | /* Check artifact type */ 79 | if (StringEqual(artifact_type, update_modules_list[update_module_index]->artifact_type)) { 80 | ret = update_modules_list[update_module_index]; 81 | } 82 | } 83 | } 84 | 85 | return ret; 86 | } 87 | -------------------------------------------------------------------------------- /docs/footprint.md: -------------------------------------------------------------------------------- 1 | # Mender MCU memory footprint 2 | 3 | The Mender MCU project is designed with memory footprint in mind. This document 4 | estimates the memory footprint of the client. 5 | 6 | Measuring the memory footprint of a C library in isolation is inherently 7 | difficult. The final size depends not only on system-level factors—such as 8 | processor architecture and compiler optimization settings—but also on how the 9 | library is used within a larger project. Only the parts of the code that are 10 | actually referenced will be retained during linking, while unused sections may 11 | be discarded, further affecting the measured footprint. 12 | 13 | The Mender MCU client also has dependencies that have a major impact on the 14 | total memory footprint. See Dependencies below for more details. 15 | 16 | ## Zephyr OS 17 | 18 | The Zephyr Project provides 19 | [optimization tools](https://docs.zephyrproject.org/latest/develop/optimizations/tools.html#footprint-and-memory-usage) 20 | to let us analyse Footprint and Memory Usage and Data Structures using different 21 | build system targets. 22 | 23 | For one specific board and build configuration, the tools will give us a good 24 | insight on the size of the objects that will be built. That is, the maximum 25 | amount of code that ends up in the ROM section of the memory and the amount of 26 | RAM required (statically allocated objects). 27 | 28 | From the tree breakdown of the objects that the tool produces, we can then take 29 | the numbers for the Mender MCU Zephyr module. 30 | 31 | ### Mender MCU Zephyr Module ROM and RAM estimation for ESP3S3 reference board 32 | 33 | The numbers in this table are extracted from a build with the following properties: 34 | 35 | * Use board [ESP32-S3-DevKitC](https://docs.zephyrproject.org/latest/boards/espressif/esp32s3_devkitc/doc/index.html) 36 | * Built through [Mender MCU reference application](https://github.com/mendersoftware/mender-mcu-integration) 37 | * Use [default feature set](https://github.com/mendersoftware/mender-mcu/blob/main/target/zephyr/Kconfig) of Mender MCU Zephyr module, except: 38 | * Set the log level for Mender MCU to Warning (`CONFIG_MENDER_LOG_LEVEL_WRN=y`) 39 | 40 | | Mender MCU | Zephyr OS | ROM usage | RAM usage | 41 | | ------- | ----------- | --------- | --------- | 42 | | preview | v4.0.0 | 33 KiB | 15 KiB | 43 | 44 | ### RAM usage configuration 45 | 46 | Most of the RAM usage for Mender MCU is configured with the following two parameters: 47 | 48 | * `MENDER_HEAP_SIZE`: Heap size for Mender MCU to use. It defines tha maximum 49 | heap memory available for Mender to use when allocating from its own heap 50 | (recommended behavior). The default value is 8 KiB. 51 | 52 | * `MENDER_SCHEDULER_WORK_QUEUE_STACK_SIZE`: Stack size for Mender MCU work queue 53 | to use. The default value is 6 KiB. 54 | 55 | The defaults are known to work for the reference board and regular operations, 56 | but could or might need to be adjusted for other integrations. 57 | 58 | ### Dependencies 59 | 60 | Mender MCU Zephyr module has one external dependency: 61 | 62 | * [cJSON Zephyr module](https://github.com/mendersoftware/cjson-zephyr) 63 | 64 | And several dependencies within the Zephyr Project. Most notably: 65 | 66 | * Network stack: NETWORKING / NET_TCP / NET_SOCKETS / HTTP_CLIENT 67 | * Mbed TLS 68 | * Non-volatile storage (NVS) 69 | -------------------------------------------------------------------------------- /src/include/error-counters.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file error-counters.h 3 | * @brief Mender Error Counters interface (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_ERROR_COUNTERS_PRIV_H__ 21 | #define __MENDER_ERROR_COUNTERS_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "utils.h" 28 | 29 | #ifndef CONFIG_MENDER_ERRORS_THRESHOLD_NET 30 | #define CONFIG_MENDER_ERRORS_THRESHOLD_NET 0 31 | #endif 32 | 33 | #if CONFIG_MENDER_ERRORS_THRESHOLD_NET > 0 34 | 35 | /** 36 | * @brief Increment the network errors counter 37 | * @return MENDER_OK if not too many errors, MENDER_FAIL if too many errors 38 | */ 39 | mender_err_t mender_err_count_net_inc(void); 40 | 41 | /** 42 | * @brief Check the network errors counter 43 | * @return MENDER_OK if not too many errors, MENDER_FAIL if too many errors 44 | */ 45 | mender_err_t mender_err_count_net_check(void); 46 | 47 | /** 48 | * @brief Reset the network errors counter 49 | * @return MENDER_OK if successful, error otherwise 50 | */ 51 | mender_err_t mender_err_count_net_reset(void); 52 | 53 | #else 54 | 55 | /* Define the functions as inline noops so that the compiler can simply rule them out. */ 56 | inline mender_err_t 57 | mender_err_count_net_inc(void) { 58 | return MENDER_OK; 59 | } 60 | inline mender_err_t 61 | mender_err_count_net_check(void) { 62 | return MENDER_OK; 63 | } 64 | inline mender_err_t 65 | mender_err_count_net_reset(void) { 66 | return MENDER_OK; 67 | } 68 | 69 | #endif /* CONFIG_MENDER_ERRORS_THRESHOLD_NET > 0 */ 70 | 71 | #ifndef CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT 72 | #define CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT 0 73 | #endif 74 | 75 | #if CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT > 0 76 | 77 | /** 78 | * @brief Increment the pending reboot counter 79 | * @return MENDER_OK if not too many errors, MENDER_FAIL if too many errors 80 | */ 81 | mender_err_t mender_err_count_reboot_inc(void); 82 | 83 | /** 84 | * @brief Reset the pending reboot counter 85 | * @return MENDER_OK if successful, error otherwise 86 | */ 87 | mender_err_t mender_err_count_reboot_reset(void); 88 | 89 | #else 90 | 91 | /* Define the functions as inline noops so that the compiler can simply rule them out. */ 92 | inline mender_err_t 93 | mender_err_count_reboot_inc(void) { 94 | return MENDER_OK; 95 | } 96 | inline mender_err_t 97 | mender_err_count_reboot_reset(void) { 98 | return MENDER_OK; 99 | } 100 | 101 | #endif /* CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT > 0 */ 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif /* __cplusplus */ 106 | 107 | #endif /* __MENDER_ERROR_COUNTERS_PRIV_H__ */ 108 | -------------------------------------------------------------------------------- /target/zephyr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # @file CMakeLists.txt 2 | # @brief mender-mcu-client zephyr module CMakeLists file 3 | # 4 | # Copyright joelguittet and mender-mcu-client contributors 5 | # Copyright Northern.tech AS 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | if(CONFIG_MENDER_MCU_CLIENT) 20 | # Include helper to define MENDER_MCU_ variables 21 | include(../../cmake/mender_mcu_sources.txt) 22 | 23 | zephyr_library() 24 | zephyr_library_sources(${MENDER_MCU_SOURCES}) 25 | zephyr_library_include_directories(${MENDER_PRIV_INCLUDE}) 26 | zephyr_include_directories(${MENDER_MCU_INCLUDE}) 27 | 28 | # Define version 29 | include("${MENDER_MCU_ROOT}/cmake/git_helper.cmake") 30 | git_describe(${MENDER_MCU_ROOT} BUILD_VERSION_NAME) 31 | zephyr_library_compile_definitions(-DMENDER_CLIENT_VERSION=\"${BUILD_VERSION_NAME}\") 32 | 33 | zephyr_library_compile_definitions(-D_POSIX_C_SOURCE=200809L) # Required for strdup and strtok_r support 34 | zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) 35 | 36 | if (CONFIG_MENDER_STORAGE_PARTITION_STORAGE_PARTITION) 37 | message(STATUS "Using storage_partition for Mender non-volatile data") 38 | elseif (CONFIG_MENDER_STORAGE_PARTITION_MENDER_PARTITION) 39 | message(STATUS "Using mender_partition for Mender non-volatile data") 40 | else() 41 | message(STATUS "Using a custom partition for Mender non-volatile data") 42 | endif() 43 | 44 | if(CONFIG_MENDER_ARTIFACT_GENERATE) 45 | include(${CMAKE_CURRENT_LIST_DIR}/mender-artifact.cmake) 46 | endif() 47 | 48 | endif() 49 | 50 | # Install the dormant certificates 51 | if (CONFIG_MENDER_SERVER_DORMANT_CERTIFICATES) 52 | set(DORMANT_CERTIFICATE_A_LINK "https://docs.mender.io/releases/certs/isrgrootx1.der") 53 | set(DORMANT_CERTIFICATE_A_SHA256 96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6) 54 | set(DORMANT_CERTIFICATE_A "${CMAKE_CURRENT_BINARY_DIR}/dormant.cer") 55 | file(DOWNLOAD ${DORMANT_CERTIFICATE_A_LINK} ${DORMANT_CERTIFICATE_A} EXPECTED_HASH SHA256=${DORMANT_CERTIFICATE_A_SHA256}) 56 | 57 | generate_inc_file_for_target(app 58 | ${DORMANT_CERTIFICATE_A} 59 | "${ZEPHYR_BINARY_DIR}/include/generated/dormant_a.cer.inc" 60 | ) 61 | 62 | set(DORMANT_CERTIFICATE_B_LINK "https://docs.mender.io/releases/certs/isrg-root-x2.der") 63 | set(DORMANT_CERTIFICATE_B_SHA256 69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470) 64 | set(DORMANT_CERTIFICATE_B "${CMAKE_CURRENT_BINARY_DIR}/dormant_b.cer") 65 | file(DOWNLOAD ${DORMANT_CERTIFICATE_B_LINK} ${DORMANT_CERTIFICATE_B} EXPECTED_HASH SHA256=${DORMANT_CERTIFICATE_B_SHA256}) 66 | 67 | generate_inc_file_for_target(app 68 | ${DORMANT_CERTIFICATE_B} 69 | "${ZEPHYR_BINARY_DIR}/include/generated/dormant_b.cer.inc" 70 | ) 71 | endif() 72 | -------------------------------------------------------------------------------- /src/platform/os/generic/weak/os.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file os.c 3 | * @brief Mender OS interface for weak platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #include "os.h" 22 | #include "utils.h" 23 | 24 | MENDER_FUNC_WEAK mender_err_t 25 | mender_os_scheduler_init(void) { 26 | /* Nothing to do */ 27 | return MENDER_OK; 28 | } 29 | 30 | MENDER_FUNC_WEAK mender_err_t 31 | mender_os_scheduler_work_create(MENDER_ARG_UNUSED mender_os_scheduler_work_params_t *work_params, MENDER_ARG_UNUSED mender_work_t **work) { 32 | /* Nothing to do */ 33 | return MENDER_NOT_IMPLEMENTED; 34 | } 35 | 36 | MENDER_FUNC_WEAK mender_err_t 37 | mender_os_scheduler_work_activate(MENDER_ARG_UNUSED mender_work_t *work) { 38 | /* Nothing to do */ 39 | return MENDER_NOT_IMPLEMENTED; 40 | } 41 | 42 | MENDER_FUNC_WEAK mender_err_t 43 | mender_os_scheduler_work_set_period(MENDER_ARG_UNUSED mender_work_t *work, MENDER_ARG_UNUSED uint32_t period) { 44 | /* Nothing to do */ 45 | return MENDER_NOT_IMPLEMENTED; 46 | } 47 | 48 | MENDER_FUNC_WEAK mender_err_t 49 | mender_os_scheduler_work_execute(MENDER_ARG_UNUSED mender_work_t *work) { 50 | /* Nothing to do */ 51 | return MENDER_NOT_IMPLEMENTED; 52 | } 53 | 54 | MENDER_FUNC_WEAK mender_err_t 55 | mender_os_scheduler_work_deactivate(MENDER_ARG_UNUSED mender_work_t *work) { 56 | /* Nothing to do */ 57 | return MENDER_NOT_IMPLEMENTED; 58 | } 59 | 60 | MENDER_FUNC_WEAK mender_err_t 61 | mender_os_scheduler_work_delete(MENDER_ARG_UNUSED mender_work_t *work) { 62 | /* Nothing to do */ 63 | return MENDER_NOT_IMPLEMENTED; 64 | } 65 | 66 | MENDER_FUNC_WEAK mender_err_t 67 | mender_os_mutex_create(void **handle) { 68 | 69 | (void)handle; 70 | 71 | /* Nothing to do */ 72 | return MENDER_NOT_IMPLEMENTED; 73 | } 74 | 75 | MENDER_FUNC_WEAK mender_err_t 76 | mender_os_mutex_take(void *handle, int32_t delay_ms) { 77 | 78 | (void)handle; 79 | (void)delay_ms; 80 | 81 | /* Nothing to do */ 82 | return MENDER_NOT_IMPLEMENTED; 83 | } 84 | 85 | MENDER_FUNC_WEAK mender_err_t 86 | mender_os_mutex_give(void *handle) { 87 | 88 | (void)handle; 89 | 90 | /* Nothing to do */ 91 | return MENDER_NOT_IMPLEMENTED; 92 | } 93 | 94 | MENDER_FUNC_WEAK mender_err_t 95 | mender_os_mutex_delete(void *handle) { 96 | 97 | (void)handle; 98 | 99 | /* Nothing to do */ 100 | return MENDER_NOT_IMPLEMENTED; 101 | } 102 | 103 | MENDER_FUNC_WEAK mender_err_t 104 | mender_os_scheduler_exit(void) { 105 | 106 | /* Nothing to do */ 107 | return MENDER_OK; 108 | } 109 | 110 | MENDER_FUNC_WEAK void 111 | mender_os_reboot(void) { 112 | return; 113 | } 114 | 115 | MENDER_FUNC_WEAK void 116 | mender_os_sleep(MENDER_ARG_UNUSED uint32_t period_ms) { 117 | return; 118 | } 119 | -------------------------------------------------------------------------------- /.github/workflows/check_headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @file check_headers.sh 3 | # @brief Check headers 4 | # 5 | # Copyright joelguittet and mender-mcu-client contributors 6 | # Copyright Northern.tech AS 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | 20 | # Function used to check headers 21 | # Arg1: Source file path 22 | # Arg2: First line, "" if it is not present 23 | # Arg3: String added in front of each new line except the first and last lines 24 | # Arg4: Last line, "" if it is not present 25 | check_header() { 26 | source_file=$1 27 | first_line=$2 28 | new_line=$3 29 | last_line=$4 30 | filename=$(echo $(basename ${source_file}) | sed -r 's/\+/\\+/g') 31 | pcregrep -Me "${first_line}${first_line:+\n}${new_line} @file ${filename}\n${new_line} @brief [[:print:]]*\n${new_line}\n(${new_line} Copyright joelguittet and mender-mcu-client contributors\n)?(${new_line} Copyright Northern.tech AS\n)?${new_line}\n${new_line} Licensed under the Apache License, Version 2.0 \(the \"License\"\);\n${new_line} you may not use this file except in compliance with the License.\n${new_line} You may obtain a copy of the License at\n${new_line}\n${new_line} http://www.apache.org/licenses/LICENSE-2.0\n${new_line}\n${new_line} Unless required by applicable law or agreed to in writing, software\n${new_line} distributed under the License is distributed on an \"AS IS\" BASIS,\n${new_line} WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n${new_line} See the License for the specific language governing permissions and\n${new_line} limitations under the License.${last_line:+\n}${last_line}\n" ${source_file} > /dev/null 2>&1 32 | return $? 33 | } 34 | 35 | # Initialize list of files that are not properly formatted 36 | result="" 37 | 38 | # Check source, header, ASM and linker files 39 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.c$|.*\.h$|.*\.cpp$|.*\.hpp$|.*\.s$|.*\.ld$)' | grep -vFf .check-headers-ignore` 40 | do 41 | check_header ${source_file} "/\*\*" " \*" " \*/" 42 | if [[ ! $? -eq 0 ]]; then 43 | result="${result}\n${source_file}" 44 | fi 45 | done 46 | 47 | # Check YAML, Python, CMake and configuration files 48 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.yml$|.*\.py$|CMakeLists.*\.txt$|.*\.cmake$|.*\.cfg$|.*\.conf$|.clang-format$)' | grep -vFf .check-headers-ignore` 49 | do 50 | check_header ${source_file} "" "#" "" 51 | if [[ ! $? -eq 0 ]]; then 52 | result="${result}\n${source_file}" 53 | fi 54 | done 55 | 56 | # Check bash files 57 | for source_file in `git ls-tree -r HEAD --name-only | grep -E '(.*\.sh$)' | grep -vFf .check-headers-ignore` 58 | do 59 | check_header ${source_file} "#!/bin/bash" "#" "" 60 | if [[ ! $? -eq 0 ]]; then 61 | result="${result}\n${source_file}" 62 | fi 63 | done 64 | 65 | # Check result 66 | if [[ ${result} != "" ]]; then 67 | echo "The following files have wrong header format:" 68 | echo -e $result 69 | exit 1 70 | fi 71 | 72 | exit 0 73 | 74 | -------------------------------------------------------------------------------- /src/include/http.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file http.h 3 | * @brief Mender HTTP interface (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_HTTP_PRIV_H__ 22 | #define __MENDER_HTTP_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include "artifact-download-data.h" 29 | #include "http-client-event.h" 30 | #include "utils.h" 31 | 32 | /** 33 | * @brief Receive buffer length 34 | */ 35 | extern const size_t mender_http_recv_buf_length; 36 | 37 | /** 38 | * @brief Mender HTTP configuration 39 | */ 40 | typedef struct { 41 | const char *host; /**< URL of the mender server */ 42 | } mender_http_config_t; 43 | 44 | /** 45 | * @brief HTTP methods 46 | */ 47 | typedef enum { 48 | MENDER_HTTP_GET, /**< GET */ 49 | MENDER_HTTP_POST, /**< POST */ 50 | MENDER_HTTP_PUT, /**< PUT */ 51 | MENDER_HTTP_PATCH /**< PATCH */ 52 | } mender_http_method_t; 53 | 54 | /** 55 | * @brief Initialize mender http 56 | * @param config Mender HTTP configuration 57 | * @return MENDER_OK if the function succeeds, error code otherwise 58 | */ 59 | mender_err_t mender_http_init(mender_http_config_t *config); 60 | 61 | /** 62 | * @brief Perform HTTP request 63 | * @param jwt Token, NULL if not authenticated yet 64 | * @param path Path of the request 65 | * @param method Method 66 | * @param payload Payload, NULL if empty 67 | * @param signature Signature of the payload, NULL if it is not required 68 | * @param callback Callback invoked on HTTP events 69 | * @param params Parameters passed to the callback, NULL if not used 70 | * @param status Status code 71 | * @return MENDER_OK if the function succeeds, error code otherwise 72 | */ 73 | mender_err_t mender_http_perform(char *jwt, 74 | char *path, 75 | mender_http_method_t method, 76 | char *payload, 77 | char *signature, 78 | mender_err_t (*callback)(mender_http_client_event_t, void *, size_t, void *), 79 | void *params, 80 | int *status); 81 | 82 | /** 83 | * @brief Perform HTTP artifact download request 84 | * @param path Path of the request 85 | * @param status Status code 86 | * @return MENDER_OK if the function succeeds, error code otherwise 87 | */ 88 | mender_err_t mender_http_artifact_download(const char *path, mender_artifact_download_data_t *dl_data, int *status); 89 | 90 | /** 91 | * @brief Release mender http 92 | * @return MENDER_OK if the function succeeds, error code otherwise 93 | */ 94 | mender_err_t mender_http_exit(void); 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif /* __cplusplus */ 99 | 100 | #endif /* __MENDER_HTTP_PRIV_H__ */ 101 | -------------------------------------------------------------------------------- /include/mender/utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file utils.h 3 | * @brief Mender utility functions (public API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_UTILS_H__ 22 | #define __MENDER_UTILS_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | /** 40 | * @brief A utility macro to make marking unused arguments less noisy/disruptive 41 | */ 42 | #define MENDER_ARG_UNUSED __attribute__((unused)) 43 | 44 | /** 45 | * For variables only used in debug builds, in particular only in assert() 46 | * calls, use MENDER_NDEBUG_UNUSED. 47 | */ 48 | #ifdef NDEBUG 49 | #define MENDER_NDEBUG_UNUSED __attribute__((unused)) 50 | #else 51 | #define MENDER_NDEBUG_UNUSED 52 | #endif 53 | 54 | /** 55 | * @brief A utility macro to make marking weak functions less noisy/disruptive 56 | */ 57 | #define MENDER_FUNC_WEAK __attribute__((weak)) 58 | 59 | /** 60 | * @brief Mender error codes 61 | */ 62 | typedef enum { 63 | MENDER_DONE = 1, /**< Done */ 64 | MENDER_OK = 0, /**< OK */ 65 | MENDER_FAIL = -1, /**< Failure */ 66 | MENDER_NOT_FOUND = -2, /**< Not found */ 67 | MENDER_NOT_IMPLEMENTED = -3, /**< Not implemented */ 68 | MENDER_LOOP_DETECTED = -4, /**< Loop detected */ 69 | MENDER_LOCK_FAILED = -5, /**< Locking failed */ 70 | MENDER_ABORTED = -6, /**< Aborted */ 71 | MENDER_RETRY_ERROR = -7, /**< Retry error */ 72 | } mender_err_t; 73 | 74 | #define MENDER_IS_ERROR(err_t_ret) ((err_t_ret) < 0) 75 | 76 | /** 77 | * @brief Deployment status 78 | */ 79 | typedef enum { 80 | MENDER_DEPLOYMENT_STATUS_DOWNLOADING, /**< Status is "downloading" */ 81 | MENDER_DEPLOYMENT_STATUS_INSTALLING, /**< Status is "installing" */ 82 | MENDER_DEPLOYMENT_STATUS_REBOOTING, /**< Status is "rebooting" */ 83 | MENDER_DEPLOYMENT_STATUS_SUCCESS, /**< Status is "success" */ 84 | MENDER_DEPLOYMENT_STATUS_FAILURE, /**< Status is "failure" */ 85 | } mender_deployment_status_t; 86 | 87 | /** 88 | * @brief Item struct 89 | */ 90 | typedef struct { 91 | char *name; /**< Name of the item */ 92 | char *value; /**< Value of the item */ 93 | } mender_item_t; 94 | 95 | /** 96 | * @brief Key-store 97 | */ 98 | typedef mender_item_t mender_keystore_t; 99 | 100 | /** 101 | * @brief Identity 102 | */ 103 | typedef mender_item_t mender_identity_t; 104 | 105 | /** 106 | * @brief Function used to print deployment status as string 107 | * @param deployment_status Deployment status 108 | * @return Deployment status as string, NULL if it is not found 109 | */ 110 | const char *mender_utils_deployment_status_to_string(mender_deployment_status_t deployment_status); 111 | 112 | /** 113 | * @brief Duplicate string using Mender memory allocation 114 | */ 115 | char *mender_utils_strdup(const char *str); 116 | char *mender_utils_strndup(const char *str, size_t n); 117 | 118 | /** 119 | * @brief Format a new string using Mender memory allocation 120 | */ 121 | int mender_utils_asprintf(char **result, const char *fmt, ...); 122 | int mender_utils_vasprintf(char **result, const char *fmt, va_list ap); 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif /* __cplusplus */ 127 | 128 | #endif /* __MENDER_UTILS_H__ */ 129 | -------------------------------------------------------------------------------- /src/platform/storage/generic/weak/storage.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file storage.c 3 | * @brief Mender storage interface for weak platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #include "log.h" 22 | #include "storage.h" 23 | 24 | MENDER_FUNC_WEAK mender_err_t 25 | mender_storage_init(void) { 26 | 27 | /* Nothing to do */ 28 | return MENDER_OK; 29 | } 30 | 31 | MENDER_FUNC_WEAK mender_err_t 32 | mender_storage_set_authentication_keys(unsigned char *private_key, size_t private_key_length, unsigned char *public_key, size_t public_key_length) { 33 | 34 | (void)private_key; 35 | (void)private_key_length; 36 | (void)public_key; 37 | (void)public_key_length; 38 | 39 | /* Nothing to do */ 40 | return MENDER_NOT_IMPLEMENTED; 41 | } 42 | 43 | MENDER_FUNC_WEAK mender_err_t 44 | mender_storage_get_authentication_keys(unsigned char **private_key, size_t *private_key_length, unsigned char **public_key, size_t *public_key_length) { 45 | 46 | (void)private_key; 47 | (void)private_key_length; 48 | (void)public_key; 49 | (void)public_key_length; 50 | 51 | /* Nothing to do */ 52 | return MENDER_NOT_IMPLEMENTED; 53 | } 54 | 55 | MENDER_FUNC_WEAK mender_err_t 56 | mender_storage_delete_authentication_keys(void) { 57 | 58 | /* Nothing to do */ 59 | return MENDER_NOT_IMPLEMENTED; 60 | } 61 | 62 | MENDER_FUNC_WEAK mender_err_t 63 | mender_storage_set_deployment_data(char *deployment_data) { 64 | 65 | (void)deployment_data; 66 | 67 | /* Nothing to do */ 68 | return MENDER_NOT_IMPLEMENTED; 69 | } 70 | 71 | MENDER_FUNC_WEAK mender_err_t 72 | mender_storage_get_deployment_data(char **deployment_data) { 73 | 74 | (void)deployment_data; 75 | 76 | /* Nothing to do */ 77 | return MENDER_NOT_IMPLEMENTED; 78 | } 79 | 80 | MENDER_FUNC_WEAK mender_err_t 81 | mender_storage_delete_deployment_data(void) { 82 | 83 | /* Nothing to do */ 84 | return MENDER_NOT_IMPLEMENTED; 85 | } 86 | 87 | MENDER_FUNC_WEAK mender_err_t 88 | mender_storage_set_provides(mender_key_value_list_t *provides) { 89 | 90 | (void)provides; 91 | 92 | /* Nothing to do */ 93 | return MENDER_NOT_IMPLEMENTED; 94 | } 95 | 96 | MENDER_FUNC_WEAK mender_err_t 97 | mender_storage_get_provides(mender_key_value_list_t **provides) { 98 | 99 | (void)provides; 100 | 101 | /* Nothing to do */ 102 | return MENDER_NOT_IMPLEMENTED; 103 | } 104 | 105 | MENDER_FUNC_WEAK mender_err_t 106 | mender_storage_set_artifact_name(const char *artifact_name) { 107 | 108 | (void)artifact_name; 109 | 110 | /* Nothing to do */ 111 | return MENDER_NOT_IMPLEMENTED; 112 | } 113 | 114 | MENDER_FUNC_WEAK mender_err_t 115 | mender_storage_get_artifact_name(const char **artifact_name) { 116 | 117 | (void)artifact_name; 118 | 119 | /* Nothing to do */ 120 | return MENDER_NOT_IMPLEMENTED; 121 | } 122 | 123 | #ifdef CONFIG_MENDER_DEPLOYMENT_LOGS 124 | MENDER_FUNC_WEAK mender_err_t 125 | mender_storage_deployment_log_append(MENDER_ARG_UNUSED const char *msg, MENDER_ARG_UNUSED size_t msg_size) { 126 | /* Nothing to do */ 127 | return MENDER_NOT_IMPLEMENTED; 128 | } 129 | 130 | MENDER_FUNC_WEAK mender_err_t 131 | mender_storage_deployment_log_walk(MENDER_ARG_UNUSED MenderDeploymentLogVisitor visitor_fn, MENDER_ARG_UNUSED void *ctx) { 132 | /* Nothing to do */ 133 | return MENDER_NOT_IMPLEMENTED; 134 | } 135 | 136 | MENDER_FUNC_WEAK mender_err_t 137 | mender_storage_deployment_log_clear(void) { 138 | /* Nothing to do */ 139 | return MENDER_NOT_IMPLEMENTED; 140 | } 141 | #endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */ 142 | 143 | MENDER_FUNC_WEAK mender_err_t 144 | mender_storage_exit(void) { 145 | 146 | /* Nothing to do */ 147 | return MENDER_OK; 148 | } 149 | -------------------------------------------------------------------------------- /tests/unit/core/client_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file client_test.cpp 3 | * @brief Unit Tests for client.c 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | 22 | extern "C" { 23 | #include "mender/client.h" 24 | } 25 | 26 | using namespace std; 27 | using namespace testing; 28 | 29 | class MenderClientTest : public ::testing::Test { 30 | protected: 31 | mender_client_config_t config {}; 32 | mender_client_callbacks_t callbacks {}; 33 | 34 | void SetUp() override { 35 | config.device_type = "test_device"; 36 | callbacks.restart = []() { return MENDER_OK; }; 37 | callbacks.get_identity = [](MENDER_ARG_UNUSED const mender_identity_t **identity) { return MENDER_OK; }; 38 | } 39 | }; 40 | 41 | TEST_F(MenderClientTest, ClientInitWithValidStandardTier) { 42 | config.device_tier = MENDER_DEVICE_TIER_STANDARD; 43 | 44 | mender_err_t result = mender_client_init(&config, &callbacks); 45 | EXPECT_EQ(result, MENDER_OK); 46 | 47 | mender_client_exit(); 48 | } 49 | 50 | TEST_F(MenderClientTest, ClientInitWithValidMicroTier) { 51 | config.device_tier = MENDER_DEVICE_TIER_MICRO; 52 | 53 | mender_err_t result = mender_client_init(&config, &callbacks); 54 | EXPECT_EQ(result, MENDER_OK); 55 | 56 | mender_client_exit(); 57 | } 58 | 59 | TEST_F(MenderClientTest, ClientInitWithInvalidTier) { 60 | config.device_tier = "invalid_tier"; 61 | 62 | mender_err_t result = mender_client_init(&config, &callbacks); 63 | EXPECT_EQ(result, MENDER_FAIL); 64 | } 65 | 66 | TEST_F(MenderClientTest, ClientInitWithEmptyTier) { 67 | config.device_tier = ""; 68 | 69 | mender_err_t result = mender_client_init(&config, &callbacks); 70 | EXPECT_EQ(result, MENDER_OK); 71 | // This returns MENDER_OK because we first check if the client 72 | // config has set it, otherwise we use MENDER_DEVICE_TIER which 73 | // can be configured via Kconfig 74 | 75 | mender_client_exit(); 76 | } 77 | 78 | TEST_F(MenderClientTest, ClientInitWithNullTier) { 79 | config.device_tier = nullptr; 80 | 81 | mender_err_t result = mender_client_init(&config, &callbacks); 82 | EXPECT_EQ(result, MENDER_OK); 83 | // This returns MENDER_OK because we first check if the client 84 | // config has set it, other wise we use MENDER_DEVICE_TIER which 85 | // can be configured via Kconfig 86 | 87 | mender_client_exit(); 88 | } 89 | 90 | TEST_F(MenderClientTest, ClientInitNoTier) { 91 | mender_err_t result = mender_client_init(&config, &callbacks); 92 | EXPECT_EQ(result, MENDER_OK); 93 | // This returns MENDER_OK because we first check if the client 94 | // config has set it, other wise we use MENDER_DEVICE_TIER which 95 | // can be configured via Kconfig 96 | 97 | mender_client_exit(); 98 | } 99 | 100 | TEST(DeviceTierValidationTest, ValidStandardTier) { 101 | EXPECT_EQ(mender_client_validate_device_tier(MENDER_DEVICE_TIER_STANDARD), MENDER_OK); 102 | EXPECT_EQ(mender_client_validate_device_tier(MENDER_DEVICE_TIER_MICRO), MENDER_OK); 103 | EXPECT_EQ(mender_client_validate_device_tier("standard"), MENDER_OK); 104 | EXPECT_EQ(mender_client_validate_device_tier("micro"), MENDER_OK); 105 | 106 | EXPECT_EQ(mender_client_validate_device_tier("invalid_tier"), MENDER_FAIL); 107 | EXPECT_EQ(mender_client_validate_device_tier("Standard"), MENDER_FAIL); 108 | EXPECT_EQ(mender_client_validate_device_tier("STANDARD"), MENDER_FAIL); 109 | EXPECT_EQ(mender_client_validate_device_tier("MICRO"), MENDER_FAIL); 110 | EXPECT_EQ(mender_client_validate_device_tier(" standard"), MENDER_FAIL); 111 | EXPECT_EQ(mender_client_validate_device_tier("standard "), MENDER_FAIL); 112 | EXPECT_EQ(mender_client_validate_device_tier(" micro "), MENDER_FAIL); 113 | EXPECT_EQ(mender_client_validate_device_tier(""), MENDER_FAIL); 114 | EXPECT_EQ(mender_client_validate_device_tier(nullptr), MENDER_FAIL); 115 | } 116 | -------------------------------------------------------------------------------- /tests/unit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # @file CMakeLists.txt 2 | # @brief Unit Tests for Mender MCU platform independent code 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | cmake_minimum_required(VERSION 3.16.3) 19 | project(mender-mcu-tests-unit) 20 | 21 | # Include sanitizers options for CMAKE_BUILD_TYPE 22 | include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/asan.cmake") 23 | include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/threadsan.cmake") 24 | include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/undefsan.cmake") 25 | 26 | # Include mender-mcu-client library, forcing warnings and errors 27 | set(CONFIG_MENDER_ALL_WARNINGS_AS_ERRORS ON CACHE BOOL "All warnings as errors" FORCE) 28 | add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../target/posix" build) 29 | 30 | # And add the same flags for the test targets too 31 | add_compile_options(-Wall -Wextra -Werror -Wpointer-arith) 32 | 33 | enable_testing() 34 | 35 | option(COVERAGE "Turn coverage instrumentation on (Default: OFF)" OFF) 36 | if($CACHE{COVERAGE}) 37 | set(CMAKE_CXX_FLAGS "--coverage $CACHE{CMAKE_CXX_FLAGS}") 38 | endif() 39 | 40 | set(GTEST_VERSION 1.12.1) 41 | 42 | option(MENDER_DOWNLOAD_GTEST "Download google test if it is not found (Default: ON)" ON) 43 | 44 | if (MENDER_DOWNLOAD_GTEST) 45 | 46 | ### BEGIN taken from https://google.github.io/googletest/quickstart-cmake.html 47 | include(FetchContent) 48 | FetchContent_Declare( 49 | googletest 50 | URL https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.zip 51 | DOWNLOAD_EXTRACT_TIMESTAMP TRUE 52 | ) 53 | 54 | # For Windows: Prevent overriding the parent project's compiler/linker settings 55 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 56 | ### END 57 | 58 | set(BUILD_GMOCK ON) 59 | set(INSTALL_GTEST OFF) 60 | FetchContent_MakeAvailable(googletest) 61 | 62 | else() 63 | find_package(GTest REQUIRED) 64 | endif() 65 | 66 | if($CACHE{COVERAGE}) 67 | add_custom_target(coverage_enabled COMMAND true) 68 | else() 69 | add_custom_target(coverage_enabled 70 | COMMAND echo 'Please run `cmake -D COVERAGE=ON .` first!' 71 | COMMAND false 72 | ) 73 | endif() 74 | 75 | set(MENDER_COVERAGE_EXCLUDE_FLAGS 76 | --exclude '/usr/*' 77 | --exclude '*/_deps/*' 78 | --exclude '*_test.*' 79 | ) 80 | # Following the recipe from lcov man page, genearte 81 | # an initial report and then the tests one, so that the 82 | # source files with 0% coverage are also reported. See: 83 | # https://linux.die.net/man/1/lcov 84 | add_custom_target(coverage 85 | COMMAND lcov --add-tracefile initial.info --add-tracefile tests.info --output-file coverage.lcov 86 | DEPENDS coverage-tests coverage-initial 87 | ) 88 | add_custom_target(coverage-initial 89 | COMMAND lcov --capture --quiet --directory . 90 | --initial 91 | --output-file initial.info 92 | ${MENDER_COVERAGE_EXCLUDE_FLAGS} 93 | DEPENDS coverage_enabled tests 94 | ) 95 | add_custom_target(coverage-tests 96 | COMMAND lcov --capture --quiet --directory . 97 | --output-file tests.info 98 | ${MENDER_COVERAGE_EXCLUDE_FLAGS} 99 | DEPENDS coverage_enabled check 100 | ) 101 | 102 | # CMake is not clever enough to build the tests before running them so we use 103 | # the 'check' target below that does both. 104 | add_custom_target(check 105 | COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure 106 | DEPENDS tests 107 | ) 108 | add_custom_target(tests 109 | # This target itself does nothing, but all tests are added as dependencies for it. 110 | COMMAND true 111 | ) 112 | 113 | include(GoogleTest) 114 | set(MENDER_TEST_FLAGS EXTRA_ARGS --gtest_output=xml:${CMAKE_SOURCE_DIR}/reports/) 115 | 116 | add_library(main_test STATIC EXCLUDE_FROM_ALL main_test.cpp) 117 | target_link_libraries(main_test PUBLIC gtest) 118 | target_compile_options(main_test PRIVATE ${PLATFORM_SPECIFIC_COMPILE_OPTIONS}) 119 | add_dependencies(tests main_test) 120 | 121 | # test for core source files 122 | add_executable(core_test EXCLUDE_FROM_ALL core/utils_test.cpp core/artifact_test.cpp core/client_test.cpp) 123 | target_include_directories(core_test PRIVATE ${CMAKE_SOURCE_DIR}/../../src/include) 124 | target_link_libraries(core_test PUBLIC 125 | mender-mcu-client 126 | gtest 127 | main_test 128 | ) 129 | gtest_discover_tests(core_test 130 | ${MENDER_TEST_FLAGS} 131 | NO_PRETTY_VALUES 132 | ) 133 | add_dependencies(tests core_test) 134 | -------------------------------------------------------------------------------- /include/mender/log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log.h 3 | * @brief Mender logging interface (public API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_LOG_H__ 21 | #define __MENDER_LOG_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #ifdef __ZEPHYR__ 28 | #include 29 | #endif /* __ZEPHYR */ 30 | 31 | #include "utils.h" 32 | 33 | /** 34 | * @brief Mender log levels 35 | */ 36 | #define MENDER_LOG_LEVEL_OFF (0) 37 | #define MENDER_LOG_LEVEL_ERR (1) 38 | #define MENDER_LOG_LEVEL_WRN (2) 39 | #define MENDER_LOG_LEVEL_INF (3) 40 | #define MENDER_LOG_LEVEL_DBG (4) 41 | 42 | /** 43 | * @brief Default log level 44 | */ 45 | #ifndef CONFIG_MENDER_LOG_LEVEL 46 | #define CONFIG_MENDER_LOG_LEVEL MENDER_LOG_LEVEL_INF 47 | #endif /* CONFIG_MENDER_LOG_LEVEL */ 48 | 49 | #ifdef __ZEPHYR__ 50 | 51 | LOG_MODULE_DECLARE(mender, CONFIG_MENDER_LOG_LEVEL); 52 | 53 | /** 54 | * @brief Print error log 55 | * @param ... Arguments 56 | * @return Error code 57 | */ 58 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_ERR 59 | #define mender_log_error LOG_ERR 60 | #else 61 | #define mender_log_error(...) 62 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_ERR */ 63 | 64 | /** 65 | * @brief Print warning log 66 | * @param ... Arguments 67 | * @return Error code 68 | */ 69 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_WRN 70 | #define mender_log_warning LOG_WRN 71 | #else 72 | #define mender_log_warning(...) 73 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_WRN */ 74 | 75 | /** 76 | * @brief Print info log 77 | * @param ... Arguments 78 | * @return Error code 79 | */ 80 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_INF 81 | #define mender_log_info LOG_INF 82 | #else 83 | #define mender_log_info(...) 84 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_INF */ 85 | 86 | /** 87 | * @brief Print debug log 88 | * @param error_code Error code 89 | * @param ... Arguments 90 | * @return Error code 91 | */ 92 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_DBG 93 | #define mender_log_debug LOG_DBG 94 | #else 95 | #define mender_log_debug(...) 96 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_DBG */ 97 | 98 | #else /* __ZEPHYR__ */ 99 | 100 | /** 101 | * @brief Print log 102 | * @param level Log level 103 | * @param filename Filename 104 | * @param function Function name 105 | * @param line Line 106 | * @param format Log format 107 | * @param ... Arguments 108 | * @return MENDER_OK if the function succeeds, error code otherwise 109 | */ 110 | mender_err_t mender_log_print(uint8_t level, const char *filename, const char *function, int line, char *format, ...); 111 | 112 | /** 113 | * @brief Print error log 114 | * @param ... Arguments 115 | * @return Error code 116 | */ 117 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_ERR 118 | #define mender_log_error(...) ({ mender_log_print(MENDER_LOG_LEVEL_ERR, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); }) 119 | #else 120 | #define mender_log_error(...) 121 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_ERR */ 122 | 123 | /** 124 | * @brief Print warning log 125 | * @param ... Arguments 126 | * @return Error code 127 | */ 128 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_WRN 129 | #define mender_log_warning(...) ({ mender_log_print(MENDER_LOG_LEVEL_WRN, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); }) 130 | #else 131 | #define mender_log_warning(...) 132 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_WRN */ 133 | 134 | /** 135 | * @brief Print info log 136 | * @param ... Arguments 137 | * @return Error code 138 | */ 139 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_INF 140 | #define mender_log_info(...) ({ mender_log_print(MENDER_LOG_LEVEL_INF, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); }) 141 | #else 142 | #define mender_log_info(...) 143 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_INF */ 144 | 145 | /** 146 | * @brief Print debug log 147 | * @param error_code Error code 148 | * @param ... Arguments 149 | * @return Error code 150 | */ 151 | #if CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_DBG 152 | #define mender_log_debug(...) ({ mender_log_print(MENDER_LOG_LEVEL_DBG, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); }) 153 | #else 154 | #define mender_log_debug(...) 155 | #endif /* CONFIG_MENDER_LOG_LEVEL >= MENDER_LOG_LEVEL_DBG */ 156 | 157 | #endif /* __ZEPHYR__ */ 158 | 159 | #ifdef __cplusplus 160 | } 161 | #endif /* __cplusplus */ 162 | 163 | #endif /* __MENDER_LOG_H__ */ 164 | -------------------------------------------------------------------------------- /src/core/artifact-download.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file artifact-download.c 3 | * @brief Mender artifact download implementation 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #include "api.h" 22 | #include "artifact.h" 23 | #include "artifact-download.h" 24 | #include "artifact-download-data.h" 25 | #include "error-counters.h" 26 | #include "http.h" 27 | #include "log.h" 28 | 29 | static mender_err_t mender_download_artifact_callback(mender_http_client_event_t event, 30 | void *data, 31 | size_t data_length, 32 | mender_artifact_download_data_t *dl_data); 33 | 34 | mender_err_t 35 | mender_download_artifact(const char *uri, 36 | mender_deployment_data_t *deployment_data, 37 | mender_update_module_t **update_module, 38 | mender_artifact_ctx_t **artifact_ctx) { 39 | assert(NULL != uri); 40 | assert(NULL != deployment_data); 41 | assert(NULL != update_module); 42 | 43 | mender_err_t ret; 44 | int status = 0; 45 | 46 | mender_artifact_download_data_t dl_data = { 47 | .deployment = deployment_data, 48 | .artifact_download_callback = &mender_download_artifact_callback, 49 | .ret = MENDER_OK, 50 | }; 51 | 52 | /* Perform HTTP request */ 53 | ret = mender_http_artifact_download(uri, &dl_data, &status); 54 | if (MENDER_OK == mender_artifact_get_ctx(artifact_ctx)) { 55 | /* Download done (one way or another), we can drop the auxiliary buffers 56 | from the artifact context. */ 57 | assert(NULL != *artifact_ctx); 58 | mender_artifact_compact_ctx(*artifact_ctx); 59 | } 60 | 61 | if (MENDER_OK != ret) { 62 | mender_log_error("Unable to perform HTTP request"); 63 | mender_err_count_net_inc(); 64 | return ret; 65 | } 66 | 67 | /* Treatment depending of the status */ 68 | if (200 == status) { 69 | /* Nothing to do */ 70 | *update_module = dl_data.update_module; 71 | return MENDER_OK; 72 | } else { 73 | mender_api_print_response_error(NULL, status); 74 | return MENDER_FAIL; 75 | } 76 | } 77 | 78 | static mender_err_t 79 | mender_download_artifact_callback(mender_http_client_event_t event, void *data, size_t data_length, mender_artifact_download_data_t *dl_data) { 80 | mender_err_t ret = MENDER_OK; 81 | 82 | mender_artifact_ctx_t *mender_artifact_ctx = NULL; 83 | 84 | /* Treatment depending of the event */ 85 | switch (event) { 86 | case MENDER_HTTP_EVENT_CONNECTED: 87 | /* Create new artifact context */ 88 | if (NULL == (mender_artifact_ctx = mender_artifact_create_ctx(2 * MENDER_ARTIFACT_STREAM_BLOCK_SIZE + mender_http_recv_buf_length))) { 89 | mender_log_error("Unable to create artifact context"); 90 | return MENDER_FAIL; 91 | } 92 | break; 93 | case MENDER_HTTP_EVENT_DATA_RECEIVED: 94 | /* Check input data */ 95 | if ((NULL == data) || (0 == data_length)) { 96 | mender_log_error("Invalid data received"); 97 | return MENDER_FAIL; 98 | } 99 | 100 | /* Check artifact context */ 101 | if (MENDER_OK != mender_artifact_get_ctx(&mender_artifact_ctx)) { 102 | mender_log_error("Unable to get artifact context"); 103 | return MENDER_FAIL; 104 | } 105 | assert(NULL != mender_artifact_ctx); 106 | 107 | /* Parse input data */ 108 | if (MENDER_OK != (ret = mender_artifact_process_data(mender_artifact_ctx, data, data_length, dl_data))) { 109 | mender_log_error("Unable to process data"); 110 | return ret; 111 | } 112 | break; 113 | case MENDER_HTTP_EVENT_DISCONNECTED: 114 | break; 115 | case MENDER_HTTP_EVENT_ERROR: 116 | /* Downloading the artifact fails */ 117 | mender_log_error("An error occurred"); 118 | return MENDER_FAIL; 119 | default: 120 | /* Should not occur */ 121 | return MENDER_FAIL; 122 | } 123 | 124 | return ret; 125 | } 126 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # @file .clang-format 2 | # @brief clang-format configuration 3 | # 4 | # Copyright joelguittet and mender-mcu-client contributors 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | # 19 | # This file is based on BARR-C 2018 format from https://github.com/petertorelli/clang-format-barr-c 20 | # Several modifications are done (braces positions and line width mainly) 21 | # 22 | 23 | --- 24 | Language: Cpp 25 | AccessModifierOffset: -4 26 | AlignAfterOpenBracket: Align 27 | AlignConsecutiveMacros: true 28 | AlignConsecutiveAssignments: true 29 | AlignConsecutiveDeclarations: true 30 | AlignEscapedNewlines: Left 31 | AlignOperands: true 32 | AlignTrailingComments: true 33 | AllowAllArgumentsOnNextLine: true 34 | AllowAllConstructorInitializersOnNextLine: true 35 | AllowAllParametersOfDeclarationOnNextLine: true 36 | AllowShortBlocksOnASingleLine: Never 37 | AllowShortCaseLabelsOnASingleLine: false 38 | AllowShortFunctionsOnASingleLine: None 39 | AllowShortLambdasOnASingleLine: All 40 | AllowShortIfStatementsOnASingleLine: Never 41 | AllowShortLoopsOnASingleLine: false 42 | AlwaysBreakAfterDefinitionReturnType: TopLevel 43 | AlwaysBreakAfterReturnType: TopLevelDefinitions 44 | AlwaysBreakBeforeMultilineStrings: true 45 | AlwaysBreakTemplateDeclarations: Yes 46 | BinPackArguments: false 47 | BinPackParameters: false 48 | BraceWrapping: 49 | AfterCaseLabel: false 50 | AfterClass: false 51 | AfterControlStatement: false 52 | AfterEnum: false 53 | AfterFunction: false 54 | AfterNamespace: false 55 | AfterObjCDeclaration: false 56 | AfterStruct: false 57 | AfterUnion: false 58 | AfterExternBlock: false 59 | BeforeCatch: false 60 | BeforeElse: false 61 | IndentBraces: false 62 | SplitEmptyFunction: false 63 | SplitEmptyRecord: false 64 | SplitEmptyNamespace: false 65 | BreakBeforeBinaryOperators: All 66 | BreakBeforeBraces: Custom 67 | BreakBeforeInheritanceComma: false 68 | BreakInheritanceList: BeforeComma 69 | BreakBeforeTernaryOperators: true 70 | BreakConstructorInitializersBeforeComma: false 71 | BreakConstructorInitializers: BeforeComma 72 | BreakAfterJavaFieldAnnotations: true 73 | BreakStringLiterals: true 74 | ColumnLimit: 160 75 | CommentPragmas: '^ IWYU pragma:' 76 | CompactNamespaces: false 77 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 78 | ConstructorInitializerIndentWidth: 4 79 | ContinuationIndentWidth: 4 80 | Cpp11BracedListStyle: false 81 | DeriveLineEnding: true 82 | DerivePointerAlignment: false 83 | DisableFormat: false 84 | ExperimentalAutoDetectBinPacking: false 85 | FixNamespaceComments: false 86 | ForEachMacros: 87 | - foreach 88 | - Q_FOREACH 89 | - BOOST_FOREACH 90 | IncludeBlocks: Preserve 91 | IncludeCategories: 92 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 93 | Priority: 2 94 | SortPriority: 0 95 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 96 | Priority: 3 97 | SortPriority: 0 98 | - Regex: '.*' 99 | Priority: 1 100 | SortPriority: 0 101 | IncludeIsMainRegex: '(Test)?$' 102 | IncludeIsMainSourceRegex: '' 103 | IndentCaseLabels: true 104 | IndentGotoLabels: true 105 | IndentPPDirectives: None 106 | IndentWidth: 4 107 | IndentWrappedFunctionNames: false 108 | JavaScriptQuotes: Leave 109 | JavaScriptWrapImports: true 110 | KeepEmptyLinesAtTheStartOfBlocks: true 111 | MacroBlockBegin: '' 112 | MacroBlockEnd: '' 113 | MaxEmptyLinesToKeep: 1 114 | NamespaceIndentation: None 115 | ObjCBinPackProtocolList: Auto 116 | ObjCBlockIndentWidth: 4 117 | ObjCSpaceAfterProperty: true 118 | ObjCSpaceBeforeProtocolList: false 119 | PenaltyBreakAssignment: 2 120 | PenaltyBreakBeforeFirstCallParameter: 19 121 | PenaltyBreakComment: 300 122 | PenaltyBreakFirstLessLess: 120 123 | PenaltyBreakString: 1000 124 | PenaltyBreakTemplateDeclaration: 10 125 | PenaltyExcessCharacter: 1000000 126 | PenaltyReturnTypeOnItsOwnLine: 200 127 | PointerAlignment: Right 128 | ReflowComments: false 129 | SortIncludes: false 130 | SortUsingDeclarations: false 131 | SpaceAfterCStyleCast: false 132 | SpaceAfterLogicalNot: false 133 | SpaceAfterTemplateKeyword: false 134 | SpaceBeforeAssignmentOperators: true 135 | SpaceBeforeCpp11BracedList: true 136 | SpaceBeforeCtorInitializerColon: true 137 | SpaceBeforeInheritanceColon: true 138 | SpaceBeforeParens: ControlStatements 139 | SpaceBeforeRangeBasedForLoopColon: true 140 | SpaceInEmptyBlock: false 141 | SpaceInEmptyParentheses: false 142 | SpacesBeforeTrailingComments: 1 143 | SpacesInAngles: false 144 | SpacesInConditionalStatement: false 145 | SpacesInContainerLiterals: false 146 | SpacesInCStyleCastParentheses: false 147 | SpacesInParentheses: false 148 | SpacesInSquareBrackets: false 149 | SpaceBeforeSquareBrackets: false 150 | Standard: Latest 151 | StatementMacros: 152 | - Q_UNUSED 153 | - QT_REQUIRE_VERSION 154 | TabWidth: 8 155 | UseCRLF: false 156 | UseTab: Never 157 | ... 158 | 159 | -------------------------------------------------------------------------------- /src/include/os.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file os.h 3 | * @brief Mender OS interface (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_OS_PRIV_H__ 22 | #define __MENDER_OS_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include 29 | 30 | /** 31 | * @brief Backoff intervals 32 | */ 33 | typedef struct { 34 | uint16_t interval; /**< Backoff interval for retries on retry errors (seconds) */ 35 | uint16_t max_interval; /**< Max backoff interval for retries on retry errors (seconds) */ 36 | } mender_os_scheduler_backoff_t; 37 | 38 | /** 39 | * @brief Work parameters 40 | */ 41 | typedef struct { 42 | mender_err_t (*function)(void); /**< Work function */ 43 | uint32_t period; /**< Work period (seconds), 0 to disable periodic execution */ 44 | char *name; /**< Work name */ 45 | mender_os_scheduler_backoff_t backoff; /**< Backoff intervals */ 46 | } mender_os_scheduler_work_params_t; 47 | 48 | /** 49 | * @brief Work item 50 | * @note This is an opaque type the implementation of which is platform-dependent. 51 | */ 52 | typedef struct mender_platform_work_t mender_work_t; 53 | 54 | /** 55 | * @brief Initialization of the scheduler 56 | * @return MENDER_OK if the function succeeds, error code otherwise 57 | */ 58 | mender_err_t mender_os_scheduler_init(void); 59 | 60 | /** 61 | * @brief Function used to register a new work 62 | * @param work_params Work parameters 63 | * @param handle Work handle if the function succeeds, NULL otherwise 64 | * @return MENDER_OK if the function succeeds, error code otherwise 65 | */ 66 | mender_err_t mender_os_scheduler_work_create(mender_os_scheduler_work_params_t *work_params, mender_work_t **work); 67 | 68 | /** 69 | * @brief Function used to activate a work 70 | * @param handle Work handle 71 | * @return MENDER_OK if the function succeeds, error code otherwise 72 | */ 73 | mender_err_t mender_os_scheduler_work_activate(mender_work_t *work); 74 | 75 | /** 76 | * @brief Function used to set work period 77 | * @param handle Work handle 78 | * @param period Work period (seconds) 79 | * @return MENDER_OK if the function succeeds, error code otherwise 80 | */ 81 | mender_err_t mender_os_scheduler_work_set_period(mender_work_t *work, uint32_t period); 82 | 83 | /** 84 | * @brief Function used to trigger execution of the work 85 | * @param handle Work handle 86 | * @return MENDER_OK if the function succeeds, error code otherwise 87 | */ 88 | mender_err_t mender_os_scheduler_work_execute(mender_work_t *work); 89 | 90 | /** 91 | * @brief Function used to deactivate a work 92 | * @param handle Work handle 93 | * @return MENDER_OK if the function succeeds, error code otherwise 94 | */ 95 | mender_err_t mender_os_scheduler_work_deactivate(mender_work_t *work); 96 | 97 | /** 98 | * @brief Function used to delete a work 99 | * @param handle Work handle 100 | * @return MENDER_OK if the function succeeds, error code otherwise 101 | */ 102 | mender_err_t mender_os_scheduler_work_delete(mender_work_t *work); 103 | 104 | /** 105 | * @brief Release mender scheduler 106 | * @return MENDER_OK if the function succeeds, error code otherwise 107 | */ 108 | mender_err_t mender_os_scheduler_exit(void); 109 | 110 | /** 111 | * @brief Function used to create a mutex 112 | * @param handle Mutex handle if the function succeeds, NULL otherwise 113 | * @return MENDER_OK if the function succeeds, error code otherwise 114 | */ 115 | mender_err_t mender_os_mutex_create(void **handle); 116 | 117 | /** 118 | * @brief Function used to take a mutex 119 | * @param handle Mutex handle 120 | * @param delay_ms Delay to obtain the mutex, -1 to block indefinitely (without a timeout) 121 | * @return MENDER_OK if the function succeeds, error code otherwise 122 | */ 123 | mender_err_t mender_os_mutex_take(void *handle, int32_t delay_ms); 124 | 125 | /** 126 | * @brief Function used to give a mutex 127 | * @param handle Mutex handle 128 | * @return MENDER_OK if the function succeeds, error code otherwise 129 | */ 130 | mender_err_t mender_os_mutex_give(void *handle); 131 | 132 | /** 133 | * @brief Function used to delete a mutex 134 | * @param handle Mutex handle 135 | * @return MENDER_OK if the function succeeds, error code otherwise 136 | */ 137 | mender_err_t mender_os_mutex_delete(void *handle); 138 | 139 | /** 140 | * @brief Unconditionally reboot the system (e.g. if the reboot callback fails to do so) 141 | */ 142 | void mender_os_reboot(void); 143 | 144 | /** 145 | * @brief Sleep for a given period 146 | * @retry period A period to sleep for (in milliseconds) 147 | */ 148 | void mender_os_sleep(uint32_t period_ms); 149 | 150 | #ifdef __cplusplus 151 | } 152 | #endif /* __cplusplus */ 153 | 154 | #endif /* __MENDER_OS_PRIV_H__ */ 155 | -------------------------------------------------------------------------------- /src/include/api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file api.h 3 | * @brief Implementation of the Mender API (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_API_PRIV_H__ 22 | #define __MENDER_API_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include "artifact.h" 29 | #include "http.h" 30 | #include "utils.h" 31 | 32 | /** 33 | * @brief Mender API configuration 34 | */ 35 | typedef struct { 36 | const char *device_type; /**< Device type */ 37 | const char *host; /**< URL of the mender server */ 38 | const char *tenant_token; /**< Tenant token used to authenticate on the mender server (optional) */ 39 | const char *device_tier; /**< Device tier: "standard" or "micro" */ 40 | mender_err_t (*identity_cb)(const mender_identity_t **identity); /**< Invoked to retrieve identity */ 41 | } mender_api_config_t; 42 | 43 | /** 44 | * @brief Deployment API Struct 45 | */ 46 | typedef struct { 47 | char *id; /**< ID of the deployment */ 48 | char *artifact_name; /**< Artifact name of the deployment */ 49 | char *uri; /**< URI of the deployment */ 50 | char **device_types_compatible; /**< Array of compatible deployment types */ 51 | size_t device_types_compatible_size; /**< Size of the deployment type array */ 52 | } mender_api_deployment_data_t; 53 | 54 | /** 55 | * @brief Initialization of the API 56 | * @param config Mender API configuration 57 | * @return MENDER_OK if the function succeeds, error code otherwise 58 | */ 59 | mender_err_t mender_api_init(mender_api_config_t *config); 60 | 61 | /** 62 | * @brief Ensures being authenticated to a Mender server API 63 | * @return MENDER_DONE if already authenticated, 64 | * MENDER_OK if successfully authenticated, 65 | * MENDER_FAIL otherwise 66 | */ 67 | mender_err_t mender_api_ensure_authenticated(void); 68 | 69 | /** 70 | * @brief Drops authentication data so the next request will have to re-authenticate 71 | * @return MENDER_OK in case of success, error otherwise 72 | */ 73 | mender_err_t mender_api_drop_authentication_data(void); 74 | 75 | /** 76 | * @brief Check for deployments for the device from the mender-server 77 | * @param deployment Deployment structure to be filled with the deployment information, if one is pending 78 | * @return MENDER_OK if the function succeeds, error code otherwise 79 | */ 80 | mender_err_t mender_api_check_for_deployment(mender_api_deployment_data_t *deployment); 81 | 82 | /** 83 | * @brief Publish deployment status of the device to the mender-server 84 | * @param id ID of the deployment received from mender_api_check_for_deployment function 85 | * @param deployment_status Deployment status 86 | * @return MENDER_OK if the function succeeds, error code otherwise 87 | */ 88 | mender_err_t mender_api_publish_deployment_status(const char *id, mender_deployment_status_t deployment_status); 89 | 90 | /** 91 | * @brief Print response error 92 | * @param response HTTP response, NULL if not available 93 | * @param status HTTP status 94 | */ 95 | void mender_api_print_response_error(char *response, int status); 96 | 97 | /** 98 | * @brief Download artifact from the mender-server 99 | * @param uri URI of the deployment received from mender_api_check_for_deployment function 100 | * @return MENDER_OK if the function succeeds, error code otherwise 101 | */ 102 | mender_err_t mender_api_download_artifact(char *uri); 103 | 104 | /** 105 | * @brief HTTP callback used to handle artifact content 106 | * @param event HTTP client event 107 | * @param data Data received 108 | * @param data_length Data length 109 | * @return MENDER_OK if the function succeeds, error code otherwise 110 | */ 111 | mender_err_t mender_api_http_artifact_callback(mender_http_client_event_t event, void *data, size_t data_length); 112 | 113 | #ifndef CONFIG_MENDER_CLIENT_INVENTORY_DISABLE 114 | 115 | /** 116 | * @brief Publish inventory data of the device to the mender-server 117 | * @param inventory Mender inventory data as a JSON array of key-value pairs (ownership transferred) 118 | * @param patch Whether to patch inventory data (PATCH) or replace the old data with new (PUT) 119 | * @return MENDER_OK if the function succeeds, error code otherwise 120 | * @note #inventory is consumed by the function (taken over and deallocated) 121 | */ 122 | mender_err_t mender_api_publish_inventory_data(cJSON *inventory, bool patch); 123 | 124 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_DISABLE */ 125 | 126 | /** 127 | * @brief Release mender API 128 | * @return MENDER_OK if the function succeeds, error code otherwise 129 | */ 130 | mender_err_t mender_api_exit(void); 131 | 132 | #ifdef __cplusplus 133 | } 134 | #endif /* __cplusplus */ 135 | 136 | #endif /* __MENDER_API_PRIV_H__ */ 137 | -------------------------------------------------------------------------------- /include/mender/client.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file client.h 3 | * @brief Mender MCU client implementation (public API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_CLIENT_H__ 22 | #define __MENDER_CLIENT_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | /** 33 | * @brief Device tier constants 34 | */ 35 | #define MENDER_DEVICE_TIER_STANDARD "standard" 36 | #define MENDER_DEVICE_TIER_MICRO "micro" 37 | 38 | /** 39 | * @brief Validate device tier value 40 | * @param device_tier Device tier string 41 | * @return MENDER_OK if valid, MENDER_FAIL otherwise 42 | */ 43 | mender_err_t mender_client_validate_device_tier(const char *device_tier); 44 | 45 | /** 46 | * @brief Mender client configuration 47 | */ 48 | typedef struct { 49 | const char *device_type; /**< Device type, must be string literal or outlive config */ 50 | const char *host; /**< URL of the mender server, must be string literal or outlive config */ 51 | const char *tenant_token; /**< Tenant token used to authenticate on the mender server (optional), must be string literal or outlive config */ 52 | const char *device_tier; /**< Device tier: "standard" or "micro" (optional), must be string literal or a string that outlives the config */ 53 | uint32_t update_poll_interval; /**< Update poll interval, default is 1800 seconds, must be > 0 */ 54 | #ifndef CONFIG_MENDER_CLIENT_INVENTORY_DISABLE 55 | uint32_t inventory_update_interval; /**< Inventory update interval, default is compile-time defined */ 56 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_DISABLE */ 57 | uint16_t backoff_interval; /**< Backoff interval for retries on retry errors, 0 means use compile-time defined option */ 58 | uint16_t max_backoff_interval; /**< Max backoff interval for retries on retry errors, 0 means use compile-time defined option */ 59 | bool recommissioning; /**< Used to force creation of new authentication keys */ 60 | struct { 61 | MenderAllocator malloc_func; 62 | MenderReallocator realloc_func; 63 | MenderDeallocator free_func; 64 | } allocation_funcs; 65 | } mender_client_config_t; 66 | 67 | /** 68 | * @brief Mender client callbacks 69 | */ 70 | typedef struct { 71 | mender_err_t (*network_connect)(void); /**< Invoked when mender-client requests access to the network */ 72 | mender_err_t (*network_release)(void); /**< Invoked when mender-client releases access to the network */ 73 | mender_err_t (*deployment_status)(mender_deployment_status_t, const char *); /**< Invoked on transition changes to inform of the new deployment status */ 74 | mender_err_t (*restart)(void); /**< Invoked to restart the device */ 75 | mender_err_t (*get_identity)(const mender_identity_t **identity); /**< Invoked to retrieve identity */ 76 | mender_err_t (*get_user_provided_keys)( 77 | char **user_provided_key, size_t *user_provided_key_length); /**< Invoked to retrieve buffer and buffer size of PEM encoded user-provided key */ 78 | } mender_client_callbacks_t; 79 | 80 | extern mender_client_callbacks_t mender_client_callbacks; 81 | 82 | /** 83 | * @brief Return mender client version 84 | * @return Mender client version as string 85 | */ 86 | const char *mender_client_version(void); 87 | 88 | /** 89 | * @brief Initialize mender client 90 | * @param config Mender client configuration 91 | * @param callbacks Mender client callbacks 92 | * @return MENDER_OK if the function succeeds, error code otherwise 93 | */ 94 | mender_err_t mender_client_init(mender_client_config_t *config, mender_client_callbacks_t *callbacks); 95 | 96 | /** 97 | * @brief Activate mender client 98 | * @return MENDER_OK if the function succeeds, error code otherwise 99 | */ 100 | mender_err_t mender_client_activate(void); 101 | 102 | /** 103 | * @brief Deactivate mender client 104 | * @note This function stops synchronization with the server 105 | * @return MENDER_OK if the function succeeds, error code otherwise 106 | */ 107 | mender_err_t mender_client_deactivate(void); 108 | 109 | /** 110 | * @brief Function used to trigger execution of the authentication and update work 111 | * @note Calling this function is optional when the periodic execution of the work is configured 112 | * @note It only permits to execute the work as soon as possible to synchronize updates 113 | * @return MENDER_OK if the function succeeds, error code otherwise 114 | */ 115 | mender_err_t mender_client_execute(void); 116 | 117 | /** 118 | * @brief Release mender client 119 | * @return MENDER_OK if the function succeeds, error code otherwise 120 | */ 121 | mender_err_t mender_client_exit(void); 122 | 123 | #ifdef __cplusplus 124 | } 125 | #endif /* __cplusplus */ 126 | 127 | #endif /* __MENDER_CLIENT_H__ */ 128 | -------------------------------------------------------------------------------- /src/platform/log/zephyr/log.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log.c 3 | * @brief Mender logging interface for Zephyr platform 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | 22 | #ifdef CONFIG_MENDER_DEPLOYMENT_LOGS 23 | #include 24 | #include 25 | #include 26 | 27 | #include "storage.h" 28 | #endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */ 29 | 30 | /* XXX: Cannot #include "log.h" here because LOG_MODULE_DECLARE() and 31 | LOG_MODULE_REGISTER() cannot be present in the same source file 32 | (compilation unit). */ 33 | 34 | #include "utils.h" 35 | 36 | LOG_MODULE_REGISTER(mender, CONFIG_MENDER_LOG_LEVEL); 37 | 38 | #ifdef CONFIG_MENDER_DEPLOYMENT_LOGS 39 | 40 | /* The deployment logs API 41 | (https://docs.mender.io/api/#device-api-deployments-schemas-deploymentlog) 42 | requires an ISO8601 timestamp. */ 43 | #ifndef CONFIG_LOG_OUTPUT_FORMAT_ISO8601_TIMESTAMP 44 | #error Mender Deployment Logs require ISO8601 timestamps (LOG_OUTPUT_FORMAT_ISO8601_TIMESTAMP) 45 | #endif 46 | 47 | /* XXX: keep in sync with the related constant in storage.c (+1 byte for the 48 | terminating '\0')*/ 49 | #define DEPL_LOGS_MAX_MSG_SIZE 256 50 | 51 | static int depl_logs_log(uint8_t *data, size_t length, void *ctx); 52 | 53 | static uint8_t msg_buf[DEPL_LOGS_MAX_MSG_SIZE]; 54 | LOG_OUTPUT_DEFINE(depl_log_output, depl_logs_log, msg_buf, sizeof(msg_buf)); 55 | 56 | static uint8_t msg_tmp[sizeof(msg_buf)]; 57 | static uint8_t msg_tmp_idx = 0; 58 | 59 | static void panic(struct log_backend const *const backend); 60 | static void dropped(const struct log_backend *const backend, uint32_t cnt); 61 | static void process(const struct log_backend *const backend, union log_msg_generic *msg); 62 | 63 | static const struct log_backend_api log_backend_depl_logs_api = { 64 | .process = process, 65 | .panic = panic, 66 | .dropped = dropped, 67 | }; 68 | 69 | LOG_BACKEND_DEFINE(log_backend_mender_depl_logs, log_backend_depl_logs_api, false /* autostart */); 70 | #endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */ 71 | 72 | mender_err_t 73 | mender_log_init(void) { 74 | 75 | /* Nothing to do */ 76 | return MENDER_OK; 77 | } 78 | 79 | mender_err_t 80 | mender_log_exit(void) { 81 | 82 | /* Nothing to do */ 83 | return MENDER_OK; 84 | } 85 | 86 | #ifdef CONFIG_MENDER_DEPLOYMENT_LOGS 87 | mender_err_t 88 | mender_deployment_logs_activate(void) { 89 | log_backend_activate(&log_backend_mender_depl_logs, NULL); 90 | return MENDER_OK; 91 | } 92 | 93 | mender_err_t 94 | mender_deployment_logs_deactivate(void) { 95 | MENDER_NDEBUG_UNUSED mender_err_t ret; 96 | 97 | /* In case there is an incomplete log message, save it. */ 98 | if (0 != msg_tmp_idx) { 99 | msg_tmp[msg_tmp_idx++] = '\0'; 100 | ret = mender_storage_deployment_log_append((const char *)msg_tmp, msg_tmp_idx); 101 | assert(MENDER_OK == ret); 102 | msg_tmp_idx = 0; 103 | } 104 | 105 | log_backend_deactivate(&log_backend_mender_depl_logs); 106 | return MENDER_OK; 107 | } 108 | 109 | static int 110 | depl_logs_log(uint8_t *data, size_t length, MENDER_ARG_UNUSED void *ctx) { 111 | MENDER_NDEBUG_UNUSED mender_err_t ret; 112 | 113 | /* This function can be called even for every character of a log message logged. */ 114 | for (uint8_t i = 0; i < length; i++) { 115 | if ('\r' == (char)data[i]) { 116 | /* throw away carriage-returns */ 117 | continue; 118 | } else if ('\n' == (char)data[i]) { 119 | /* newline terminates a log message */ 120 | msg_tmp[msg_tmp_idx++] = '\0'; 121 | ret = mender_storage_deployment_log_append((const char *)msg_tmp, msg_tmp_idx); 122 | assert(MENDER_OK == ret); 123 | msg_tmp_idx = 0; 124 | } else { 125 | /* just append the character to the message being constructed */ 126 | msg_tmp[msg_tmp_idx++] = data[i]; 127 | } 128 | } 129 | 130 | /* This function ought to return the number of bytes processed so even in 131 | case of a failure we have no other choice. */ 132 | return length; 133 | } 134 | 135 | static void 136 | panic(struct log_backend const *const backend) { 137 | log_backend_deactivate(backend); 138 | } 139 | 140 | static void 141 | dropped(MENDER_ARG_UNUSED const struct log_backend *const backend, uint32_t cnt) { 142 | log_output_dropped_process(&depl_log_output, cnt); 143 | } 144 | 145 | static void 146 | process(MENDER_ARG_UNUSED const struct log_backend *const backend, union log_msg_generic *msg) { 147 | /* We only care about warning and error log messages */ 148 | if (msg->log.hdr.desc.level > LOG_LEVEL_WRN) { 149 | return; 150 | } 151 | 152 | uint32_t flags = log_backend_std_get_flags() & ~LOG_OUTPUT_FLAG_COLORS; 153 | log_format_func_t log_format_func = log_format_func_t_get(LOG_OUTPUT_TEXT); 154 | 155 | log_format_func(&depl_log_output, &msg->log, flags); 156 | } 157 | #endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */ 158 | -------------------------------------------------------------------------------- /src/platform/inventory/zephyr/inventory.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file inventory.c 3 | * @brief Mender inventory code for Zephyr platform 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #include 21 | #include /* a file generated during build */ 22 | 23 | #include "alloc.h" 24 | #include "inventory.h" 25 | #include "log.h" 26 | #include "utils.h" 27 | 28 | #ifndef CONFIG_MENDER_CLIENT_INVENTORY_DISABLE 29 | 30 | #ifdef CONFIG_MENDER_CLIENT_INVENTORY_BUILD_INFO 31 | static mender_err_t 32 | build_info_callback(mender_keystore_t **inventory, uint8_t *inventory_len) { 33 | static mender_keystore_t build_info[] = { 34 | { "mender_client", "Mender MCU client (Zephyr)" }, 35 | { "mender_client_version", MENDER_CLIENT_VERSION }, 36 | { "zephyr_version", KERNEL_VERSION_STRING }, 37 | }; 38 | *inventory = build_info; 39 | *inventory_len = 3; 40 | 41 | return MENDER_OK; 42 | } 43 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_BUILD_INFO */ 44 | 45 | #ifdef CONFIG_MENDER_CLIENT_INVENTORY_NETWORK_INFO 46 | static mender_err_t 47 | network_info_callback(mender_keystore_t **inventory, uint8_t *inventory_len) { 48 | mender_keystore_t *network_info = NULL; 49 | struct net_if *iface = NULL; 50 | const char *ifname = NULL; 51 | 52 | if (NULL == (iface = net_if_get_default())) { 53 | mender_log_debug("No network interface"); 54 | return MENDER_FAIL; 55 | } 56 | ifname = net_if_get_device(iface)->name; 57 | 58 | network_info = mender_calloc(4, sizeof(mender_keystore_t)); 59 | if (NULL == network_info) { 60 | mender_log_error("Unable to allocate memory"); 61 | goto ERR; 62 | } 63 | 64 | /* Default interface name */ 65 | network_info[0].name = mender_utils_strdup("Default network interface"); 66 | network_info[0].value = mender_utils_strdup(ifname); 67 | 68 | /* The first IP of the iface */ 69 | if (mender_utils_asprintf(&(network_info[1].name), "IPv4[%s]", ifname) <= 0) { 70 | mender_log_error("Failed to construct network inventory data"); 71 | goto ERR; 72 | } 73 | if (NULL == (network_info[1].value = mender_malloc(NET_IPV4_ADDR_LEN))) { 74 | mender_log_error("Unable to allocate memory"); 75 | goto ERR; 76 | } 77 | if (NULL == net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[0].ipv4.address.in_addr, network_info[1].value, NET_IPV4_ADDR_LEN)) { 78 | mender_log_error("Failed to construct network inventory data"); 79 | goto ERR; 80 | } 81 | 82 | /* Netmask of the first IP */ 83 | if (mender_utils_asprintf(&(network_info[2].name), "Netmask[%s]", ifname) <= 0) { 84 | mender_log_error("Failed to construct network inventory data"); 85 | goto ERR; 86 | } 87 | if (NULL == (network_info[2].value = mender_malloc(NET_IPV4_ADDR_LEN))) { 88 | mender_log_error("Unable to allocate memory"); 89 | goto ERR; 90 | } 91 | if (NULL == net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[0].netmask, network_info[2].value, NET_IPV4_ADDR_LEN)) { 92 | mender_log_error("Failed to construct network inventory data"); 93 | goto ERR; 94 | } 95 | 96 | /* Gateway */ 97 | if (mender_utils_asprintf(&(network_info[3].name), "Gateway[%s]", ifname) <= 0) { 98 | mender_log_error("Failed to construct network inventory data"); 99 | goto ERR; 100 | } 101 | if (NULL == (network_info[3].value = mender_malloc(NET_IPV4_ADDR_LEN))) { 102 | mender_log_error("Unable to allocate memory"); 103 | goto ERR; 104 | } 105 | if (NULL == net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, network_info[3].value, NET_IPV4_ADDR_LEN)) { 106 | mender_log_error("Failed to construct network inventory data"); 107 | goto ERR; 108 | } 109 | 110 | /* Error cases jump over this */ 111 | *inventory = network_info; 112 | *inventory_len = 4; 113 | return MENDER_OK; 114 | 115 | ERR: 116 | mender_utils_keystore_delete(network_info, 4); 117 | return MENDER_FAIL; 118 | } 119 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_NETWORK_INFO */ 120 | 121 | mender_err_t 122 | mender_inventory_add_default_callbacks(void) { 123 | bool some_error = false; 124 | 125 | #ifdef CONFIG_MENDER_CLIENT_INVENTORY_BUILD_INFO 126 | if (MENDER_OK != mender_inventory_add_callback(build_info_callback, true)) { 127 | mender_log_error("Failed to add build info inventory callback"); 128 | some_error = true; 129 | } 130 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_BUILD_INFO */ 131 | 132 | #ifdef CONFIG_MENDER_CLIENT_INVENTORY_NETWORK_INFO 133 | /* Not a persistent callback -- DHCP lease expires and network config can 134 | change (plus we need to construct the data dynamically, see above). */ 135 | if (MENDER_OK != mender_inventory_add_callback(network_info_callback, false)) { 136 | mender_log_error("Failed to add network info inventory callback"); 137 | some_error = true; 138 | } 139 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_NETWORK_INFO */ 140 | 141 | return some_error ? MENDER_FAIL : MENDER_OK; 142 | } 143 | 144 | #endif /* CONFIG_MENDER_CLIENT_INVENTORY_DISABLE */ 145 | -------------------------------------------------------------------------------- /.gitlab/release.yaml: -------------------------------------------------------------------------------- 1 | variables: 2 | DEFAULT_BRANCH: "main" 3 | GITHUB_REPO_URL: 4 | description: "The Github Repo URL for release-please, in the format of 'owner/repo'" 5 | value: "mendersoftware/mender-mcu" 6 | GITHUB_USER_NAME: 7 | description: "The Github username for release-please" 8 | value: "mender-test-bot" 9 | GITHUB_USER_EMAIL: 10 | description: "The Github user email for release-please" 11 | value: "mender@northern.tech" 12 | GITHUB_CHANGELOG_REPO_URL: 13 | description: "The Github Repo URL where to push the changelog" 14 | value: "mendersoftware/mender-docs-changelog" 15 | CHANGELOG_REMOTE_FILE: 16 | description: "The changelog file in the remote changelog repo" 17 | value: "80.mender-mcu/docs.md" 18 | GIT_CLIFF: 19 | description: "Run git cliff to override the release-please changelog" 20 | value: "true" 21 | options: 22 | - "true" 23 | - "false" 24 | 25 | changelog: 26 | image: "registry.gitlab.com/northern.tech/mender/mender-test-containers:release-please-v1-master" 27 | stage: changelog 28 | variables: 29 | GIT_DEPTH: 0 # Always get the full history 30 | GIT_STRATEGY: clone # Always get the full history 31 | tags: 32 | - hetzner-amd-beefy 33 | rules: 34 | - if: $CI_COMMIT_BRANCH =~ "/^v\d+\.\d+\.x$/" 35 | - if: $CI_COMMIT_BRANCH == $DEFAULT_BRANCH 36 | # Exclude release tags 37 | - if: $CI_COMMIT_TAG 38 | when: never 39 | before_script: 40 | # Setting up git 41 | - git config --global user.email "${GITHUB_USER_EMAIL}" 42 | - git config --global user.name "${GITHUB_USER_NAME}" 43 | # GITHUB_TOKEN for Github cli authentication 44 | - export GITHUB_TOKEN=${GITHUB_CLI_TOKEN} 45 | # getting the centralized git cliff config 46 | script: 47 | - release-please release-pr 48 | --token=${GITHUB_BOT_TOKEN_REPO_FULL} 49 | --repo-url=${GITHUB_REPO_URL} 50 | --target-branch=${CI_COMMIT_REF_NAME} || echo "INFO - release already exists" # workaround because we shifted to prerelease versioning strategy and there's already a PR open 51 | # git cliff: override the changelog 52 | - test $GIT_CLIFF == "false" && echo "INFO - Skipping git-cliff" && exit 0 53 | - git remote add github-${CI_JOB_ID} https://${GITHUB_USER_NAME}:${GITHUB_BOT_TOKEN_REPO_FULL}@github.com/${GITHUB_REPO_URL} || true # Ignore already existing remote 54 | - gh repo set-default https://${GITHUB_USER_NAME}:${GITHUB_BOT_TOKEN_REPO_FULL}@github.com/${GITHUB_REPO_URL} 55 | - RELEASE_PLEASE_PR=$(gh pr list --author "${GITHUB_USER_NAME}" --head "release-please--branches--${CI_COMMIT_REF_NAME}" --json number | jq -r '.[0].number // empty') 56 | - test -z "$RELEASE_PLEASE_PR" && echo "No release-please PR found" && exit 0 57 | - cp CHANGELOG.md CHANGELOG.md.${CI_COMMIT_SHA} 58 | - gh pr checkout --force $RELEASE_PLEASE_PR 59 | - mv CHANGELOG.md.${CI_COMMIT_SHA} CHANGELOG.md 60 | - wget --output-document cliff.toml https://raw.githubusercontent.com/mendersoftware/mendertesting/master/utils/cliff.toml 61 | - RELEASE_VERSION="$(jq -r '.["."]' .release-please-manifest.json)" 62 | - git cliff --unreleased --prepend CHANGELOG.md --github-repo ${GITHUB_REPO_URL} --use-branch-tags --tag ${RELEASE_VERSION} 63 | - git add CHANGELOG.md 64 | - git commit --amend -s --no-edit 65 | - git push github-${CI_JOB_ID} --force 66 | # Update the PR body 67 | - git cliff --unreleased --bump -o tmp_pr_body.md --github-repo ${GITHUB_REPO_URL} --use-branch-tags 68 | - gh pr edit $RELEASE_PLEASE_PR --body-file tmp_pr_body.md 69 | - rm tmp_pr_body.md 70 | after_script: 71 | - git remote remove github-${CI_JOB_ID} 72 | 73 | release:github: 74 | image: "registry.gitlab.com/northern.tech/mender/mender-test-containers:release-please-v1-master" 75 | stage: .post 76 | tags: 77 | - hetzner-amd-beefy 78 | rules: 79 | # Only make available for protected branches (main and maintenance branches) 80 | - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/' 81 | when: never 82 | - if: $CI_COMMIT_BRANCH =~ "/^v\d+\.\d+\.x$/" 83 | when: manual 84 | allow_failure: true 85 | - if: $CI_COMMIT_BRANCH == $DEFAULT_BRANCH 86 | when: manual 87 | allow_failure: true 88 | # Exclude release tags 89 | - if: $CI_COMMIT_TAG 90 | when: never 91 | needs: 92 | - job: changelog 93 | script: 94 | - release-please github-release 95 | --token=${GITHUB_BOT_TOKEN_REPO_FULL} 96 | --repo-url=${GITHUB_REPO_URL} 97 | --target-branch=${CI_COMMIT_REF_NAME} 98 | 99 | release:mender-docs-changelog: 100 | image: "registry.gitlab.com/northern.tech/mender/mender-test-containers:release-please-v1-master" 101 | stage: .post 102 | tags: 103 | - hetzner-amd-beefy 104 | rules: 105 | # Only make available for stable branches 106 | - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/' 107 | allow_failure: true 108 | before_script: 109 | # Setting up git 110 | - git config --global user.email "${GITHUB_USER_EMAIL}" 111 | - git config --global user.name "${GITHUB_USER_NAME}" 112 | # GITHUB_TOKEN for Github cli authentication 113 | - export GITHUB_TOKEN=${GITHUB_CLI_TOKEN} 114 | script: 115 | - git clone https://${GITHUB_USER_NAME}:${GITHUB_BOT_TOKEN_REPO_FULL}@github.com/${GITHUB_CHANGELOG_REPO_URL} 116 | - cd ${GITHUB_CHANGELOG_REPO_URL#*/} 117 | - git checkout -b changelog-${CI_JOB_ID} 118 | - cat ../.docs_header.md > ${CHANGELOG_REMOTE_FILE} 119 | - cat ../CHANGELOG.md | grep -v -E '^---' >> ${CHANGELOG_REMOTE_FILE} 120 | - git add ${CHANGELOG_REMOTE_FILE} 121 | - 'git commit -s -m "chore: add $CI_PROJECT_NAME changelog"' 122 | - git push origin changelog-${CI_JOB_ID} 123 | - gh pr create --title "Update CHANGELOG.md for $CI_PROJECT_NAME" --body "Automated change to the CHANGELOG.md file" --base master --head changelog-${CI_JOB_ID} 124 | -------------------------------------------------------------------------------- /include/mender/update-module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file update-module.h 3 | * @brief Mender Update Module interface (public API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_UPDATE_MODULE_H__ 21 | #define __MENDER_UPDATE_MODULE_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | typedef enum mender_update_state_t { 34 | MENDER_UPDATE_STATE_DOWNLOAD = 0, 35 | MENDER_UPDATE_STATE_INSTALL, 36 | MENDER_UPDATE_STATE_REBOOT, 37 | MENDER_UPDATE_STATE_VERIFY_REBOOT, 38 | MENDER_UPDATE_STATE_COMMIT, 39 | MENDER_UPDATE_STATE_CLEANUP, 40 | MENDER_UPDATE_STATE_ROLLBACK, 41 | MENDER_UPDATE_STATE_ROLLBACK_REBOOT, 42 | MENDER_UPDATE_STATE_ROLLBACK_VERIFY_REBOOT, 43 | MENDER_UPDATE_STATE_FAILURE, 44 | MENDER_UPDATE_STATE_END 45 | } mender_update_state_t; 46 | #define N_MENDER_UPDATE_STATES ((size_t)MENDER_UPDATE_STATE_END) 47 | 48 | /* The structs below are not supposed to be used directly, only as arguments 49 | * passed by in the union below. */ 50 | /** 51 | * @param id ID of the deployment 52 | * @param artifact name Artifact name 53 | * @param type Type from header-info payloads 54 | * @param meta_data Meta-data from header tarball 55 | * @param filename Artifact filename 56 | * @param size Artifact file size 57 | * @param data Artifact data 58 | * @param index Artifact data index 59 | * @param length Artifact data length 60 | */ 61 | struct mender_update_download_state_data_s { 62 | const char *id; 63 | const char *artifact_name; 64 | const char *type; 65 | const cJSON *meta_data; 66 | const char *filename; 67 | size_t size; 68 | const uint8_t *data; 69 | size_t offset; 70 | size_t length; 71 | bool done; 72 | }; 73 | 74 | #ifdef __clang__ 75 | /* The empty structs below will differ in size between C and C++; disable the warning */ 76 | #pragma clang diagnostic push 77 | #pragma clang diagnostic ignored "-Wextern-c-compat" 78 | #endif 79 | struct mender_update_install_state_data_s { 80 | /* TBD; a NULL pointer in the union below until there is something here */ 81 | }; 82 | 83 | struct mender_update_reboot_state_data_s { 84 | /* TBD; a NULL pointer in the union below until there is something here */ 85 | }; 86 | 87 | struct mender_update_verify_reboot_state_data_s { 88 | /* TBD; a NULL pointer in the union below until there is something here */ 89 | }; 90 | 91 | struct mender_update_commit_state_data_s { 92 | /* TBD; a NULL pointer in the union below until there is something here */ 93 | }; 94 | 95 | struct mender_update_cleanup_state_data_s { 96 | /* TBD; a NULL pointer in the union below until there is something here */ 97 | }; 98 | 99 | struct mender_update_rollback_state_data_s { 100 | /* TBD; a NULL pointer in the union below until there is something here */ 101 | }; 102 | 103 | struct mender_update_rollback_reboot_state_data_s { 104 | /* TBD; a NULL pointer in the union below until there is something here */ 105 | }; 106 | 107 | struct mender_update_failure_state_data_s { 108 | /* TBD; a NULL pointer in the union below until there is something here */ 109 | }; 110 | #ifdef __clang__ 111 | #pragma clang diagnostic pop 112 | #endif 113 | 114 | /* The last member allows to type-cast NULL to mender_update_state_data_t, 115 | * otherwise we would have to type-cast NULL to one of the other member types 116 | * first. */ 117 | /* Should we just use (void *data) as parameter of the callbacks? */ 118 | typedef union mender_update_state_data_u { 119 | struct mender_update_download_state_data_s *download_state_data; 120 | struct mender_update_install_state_data_s *install_state_data; 121 | struct mender_update_reboot_state_data_s *reboot_state_data; 122 | struct mender_update_verify_reboot_state_data_s *verify_reboot_state_data; 123 | struct mender_update_commit_state_data_s *commit_state_data; 124 | struct mender_update_cleanup_state_data_s *cleanup_state_data; 125 | struct mender_update_rollback_state_data_s *rollback_state_data; 126 | struct mender_update_rollback_reboot_state_data_s *rollback_reboot_state_data; 127 | struct mender_update_failure_state_data_s *failure_state_data; 128 | void *only_for_nicer_type_casting; 129 | } mender_update_state_data_t; 130 | 131 | typedef mender_err_t (*MenderUpdateStateCallback)(mender_update_state_t state, mender_update_state_data_t callback_data); 132 | 133 | typedef struct mender_update_module_s { 134 | MenderUpdateStateCallback callbacks[N_MENDER_UPDATE_STATES]; 135 | const char *artifact_type; 136 | bool requires_reboot; 137 | bool supports_rollback; 138 | } mender_update_module_t; 139 | 140 | /** 141 | * @brief Register update module 142 | * @param update_module The update module to register 143 | * @return MENDER_OK if the function succeeds, error code otherwise 144 | * @note Takes ownership of #update_module in case of success 145 | * (make sure to use mender_malloc() or mender_calloc() for allocation) 146 | */ 147 | mender_err_t mender_update_module_register(mender_update_module_t *update_module); 148 | 149 | #ifdef __cplusplus 150 | } 151 | #endif /* __cplusplus */ 152 | 153 | #endif /* __MENDER_UPDATE_MODULE_H__ */ 154 | -------------------------------------------------------------------------------- /src/include/storage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file storage.h 3 | * @brief Mender storage interface (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_STORAGE_PRIV_H__ 21 | #define __MENDER_STORAGE_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include "utils.h" 28 | #include "update-module.h" 29 | 30 | /** 31 | * @brief Initialize mender storage 32 | * @return MENDER_OK if the function succeeds, error code otherwise 33 | */ 34 | mender_err_t mender_storage_init(void); 35 | 36 | /** 37 | * @brief Set authentication keys 38 | * @param private_key Private key to store 39 | * @param private_key_length Private key length 40 | * @param public_key Public key to store 41 | * @param public_key_length Public key length 42 | * @return MENDER_OK if the function succeeds, error code otherwise 43 | */ 44 | mender_err_t mender_storage_set_authentication_keys(unsigned char *private_key, size_t private_key_length, unsigned char *public_key, size_t public_key_length); 45 | 46 | /** 47 | * @brief Get authentication keys 48 | * @param private_key Private key from storage, NULL if not found 49 | * @param private_key_length Private key length from storage, 0 if not found 50 | * @param public_key Public key from storage, NULL if not found 51 | * @param public_key_length Public key length from storage, 0 if not found 52 | * @return MENDER_OK if the function succeeds, error code otherwise 53 | */ 54 | mender_err_t mender_storage_get_authentication_keys(unsigned char **private_key, 55 | size_t *private_key_length, 56 | unsigned char **public_key, 57 | size_t *public_key_length); 58 | 59 | /** 60 | * @brief Delete authentication keys 61 | * @return MENDER_OK if the function succeeds, error code otherwise 62 | */ 63 | mender_err_t mender_storage_delete_authentication_keys(void); 64 | 65 | /** 66 | * @brief Set deployment data 67 | * @param deployment_data Deployment data to store 68 | * @return MENDER_OK if the function succeeds, error code otherwise 69 | */ 70 | mender_err_t mender_storage_set_deployment_data(char *deployment_data); 71 | 72 | /** 73 | * @brief Get deployment data 74 | * @param deployment_data Deployment data from storage, NULL if not found 75 | * @return MENDER_OK if the function succeeds, error code otherwise 76 | */ 77 | mender_err_t mender_storage_get_deployment_data(char **deployment_data); 78 | 79 | /** 80 | * @brief Delete deployment data 81 | * @return MENDER_OK if the function succeeds, error code otherwise 82 | */ 83 | mender_err_t mender_storage_delete_deployment_data(void); 84 | 85 | #ifdef CONFIG_MENDER_DEPLOYMENT_LOGS 86 | /** 87 | * @brief Append a deployment log message 88 | * @param msg Message to append 89 | * @param msg_size Size of the message (length + 1) 90 | * @return MENDER_OK if the function succeeds, error code otherwise 91 | */ 92 | mender_err_t mender_storage_deployment_log_append(const char *msg, size_t msg_size); 93 | 94 | /** 95 | * @brief Visitor function for deployment log messages 96 | * @param msg Deployment log message 97 | * @param ctx Arbitrary context data 98 | */ 99 | typedef void(MenderDeploymentLogVisitor)(char *msg, void *ctx); 100 | 101 | /** 102 | * @brief Walk/iterate over stored deployment log messages 103 | * @param visitor_fn Function to call on every stored log message 104 | * @param ctx Arbitrary context data passed to #visitor_fn 105 | * @return MENDER_OK if the function succeeds, error code otherwise 106 | */ 107 | mender_err_t mender_storage_deployment_log_walk(MenderDeploymentLogVisitor visitor_fn, void *ctx); 108 | 109 | /** 110 | * @brief Clear the deployment logs storage 111 | * @return MENDER_OK if the function succeeds, error code otherwise 112 | */ 113 | mender_err_t mender_storage_deployment_log_clear(void); 114 | #endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */ 115 | 116 | #ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT 117 | #ifdef CONFIG_MENDER_PROVIDES_DEPENDS 118 | /** 119 | * @brief Set provides 120 | * @return MENDER_OK if the function succeeds, error code otherwise 121 | */ 122 | mender_err_t mender_storage_set_provides(mender_key_value_list_t *provides); 123 | 124 | /** 125 | * @brief Get provides 126 | * @return MENDER_OK if the function succeeds, error code otherwise 127 | */ 128 | mender_err_t mender_storage_get_provides(mender_key_value_list_t **provides); 129 | 130 | /** 131 | * @brief Delete provides 132 | * @return MENDER_OK if the function succeeds, error code otherwise 133 | */ 134 | mender_err_t mender_storage_delete_provides(void); 135 | 136 | #endif /* CONFIG_MENDER_PROVIDES_DEPENDS */ 137 | #endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */ 138 | 139 | /** 140 | * @brief Set artifact name 141 | * @return MENDER_OK if the function succeeds, error code otherwise 142 | */ 143 | mender_err_t mender_storage_set_artifact_name(const char *artifact_name); 144 | 145 | /** 146 | * @brief Get artifact name 147 | * @return MENDER_OK if the function succeeds, error code otherwise 148 | */ 149 | mender_err_t mender_storage_get_artifact_name(const char **artifact_name); 150 | 151 | /** 152 | * @brief Release mender storage 153 | * @return MENDER_OK if the function succeeds, error code otherwise 154 | */ 155 | mender_err_t mender_storage_exit(void); 156 | 157 | #ifdef __cplusplus 158 | } 159 | #endif /* __cplusplus */ 160 | 161 | #endif /* __MENDER_STORAGE_PRIV_H__ */ 162 | -------------------------------------------------------------------------------- /src/include/utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file utils.h 3 | * @brief Mender utility functions (private API) 4 | * 5 | * Copyright Northern.tech AS 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | #ifndef __MENDER_UTILS_PRIV_H__ 21 | #define __MENDER_UTILS_PRIV_H__ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | #include 28 | 29 | #ifndef MAX 30 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 31 | #endif /* !MAX */ 32 | 33 | /** 34 | * @brief Macro for releasing a resource followed by setting it to NULL. 35 | */ 36 | #define DESTROY_AND_NULL(destructor, resource) \ 37 | destructor(resource); \ 38 | resource = NULL 39 | 40 | /** 41 | * @brief Macro for releasing a resource with mender_free() followed by setting it to NULL. 42 | */ 43 | #define FREE_AND_NULL(resource) DESTROY_AND_NULL(mender_free, resource) 44 | 45 | /** 46 | * @brief Macro for checking if string is NULL or empty 47 | */ 48 | #define IS_NULL_OR_EMPTY(str) ((NULL == str) || (str[0] == '\0')) 49 | 50 | /** 51 | * @brief Macro for comparing two strings 52 | * @return true if the strings are equal, false otherwise 53 | */ 54 | #define StringEqual(str1, str2) (0 == strcmp(str1, str2)) 55 | 56 | /** 57 | * @brief Macro for comparing two strings up to N bytes 58 | * @return true if the strings are equal, false otherwise 59 | */ 60 | #define StringEqualN(str1, str2, n) (0 == strncmp(str1, str2, n)) 61 | 62 | /** 63 | * @brief Linked-list 64 | */ 65 | typedef struct mender_key_value_list_t { 66 | char *key; 67 | char *value; 68 | struct mender_key_value_list_t *next; 69 | } mender_key_value_list_t; 70 | 71 | /** 72 | * @brief Function used to print HTTP status as string 73 | * @param status HTTP status code 74 | * @return HTTP status as string, NULL if it is not found 75 | */ 76 | const char *mender_utils_http_status_to_string(int status); 77 | 78 | /** 79 | * @brief Function used to locate last substring in string 80 | * @param haystack String to look for a substring 81 | * @param needle Substring to look for 82 | * @return Pointer to the beginning of the substring, NULL is the substring is not found 83 | */ 84 | char *mender_utils_strrstr(const char *haystack, const char *needle); 85 | 86 | /** 87 | * @brief Function used to check if string begins with wanted substring 88 | * @param s1 String to be checked 89 | * @param s2 Substring to look for at the beginning of the string 90 | * @return true if the string begins with wanted substring, false otherwise 91 | */ 92 | bool mender_utils_strbeginswith(const char *s1, const char *s2); 93 | 94 | /** 95 | * @brief Function used to check if string ends with wanted substring 96 | * @param s1 String to be checked 97 | * @param s2 Substring to look for at the end of the string 98 | * @return true if the string ends with wanted substring, false otherwise 99 | */ 100 | bool mender_utils_strendswith(const char *s1, const char *s2); 101 | 102 | /** 103 | * @brief Convert a hexdump of bytes into the respective bytes 104 | * @param hexdump String containing the hexdumped bytes 105 | * @param bytes An array to store the bytes in 106 | * @param n_bytes The number of the bytes to convert (i.e. the size of #bytes and half the 107 | * length of #hexdump). 108 | * @return %true if the conversion was successful, false otherwise 109 | */ 110 | bool mender_utils_hexdump_to_bytes(const char *hexdump, unsigned char *bytes, size_t n_bytes); 111 | 112 | /** 113 | * @brief Function used to format identity to JSON object 114 | * @param identity Identity 115 | * @param object JSON object 116 | * @return MENDER_OK if the function succeeds, error code otherwise 117 | */ 118 | mender_err_t mender_utils_identity_to_json(const mender_identity_t *identity, cJSON **object); 119 | 120 | /** 121 | * @brief Delete the given keystore 122 | */ 123 | void mender_utils_keystore_delete(mender_keystore_t *keystore, uint8_t keystore_len); 124 | 125 | /** 126 | * @brief Free linked list list 127 | * @param provides_depends List to clear 128 | */ 129 | mender_err_t mender_utils_key_value_list_free(mender_key_value_list_t *list); 130 | 131 | /** 132 | * @brief Get linked list length 133 | * @param list List to get the length of 134 | */ 135 | size_t mender_utils_key_value_list_length(const mender_key_value_list_t *list); 136 | 137 | /** 138 | * @brief Create a new key-value node 139 | */ 140 | mender_err_t mender_utils_key_value_list_create_node(const char *type, const char *value, mender_key_value_list_t **list); 141 | 142 | /** 143 | * @brief Append linked list - appends list2 to list1 and sets list2 to NULL 144 | */ 145 | mender_err_t mender_utils_key_value_list_append(mender_key_value_list_t **list1, mender_key_value_list_t **list2); 146 | 147 | /** 148 | * @brief Convert linked list to string 149 | */ 150 | mender_err_t mender_utils_key_value_list_to_string(mender_key_value_list_t *list, char **key_value_str); 151 | 152 | /** 153 | * @brief Convert string to linked list 154 | */ 155 | mender_err_t mender_utils_string_to_key_value_list(const char *key_value_str, mender_key_value_list_t **list); 156 | 157 | /** 158 | * @brief Append items from list2 that are not in list1 159 | */ 160 | mender_err_t mender_utils_key_value_list_append_unique(mender_key_value_list_t **list1, mender_key_value_list_t **list2); 161 | 162 | /** 163 | * @brief Delete a node from a linked list 164 | */ 165 | mender_err_t mender_utils_key_value_list_delete_node(mender_key_value_list_t **list, const char *key); 166 | 167 | /** 168 | * @brief Compare `string` with `wild_card_string` 169 | * @return true if matches, else false 170 | */ 171 | mender_err_t mender_utils_compare_wildcard(const char *str, const char *wildcard_str, bool *match); 172 | 173 | #ifdef __cplusplus 174 | } 175 | #endif /* __cplusplus */ 176 | 177 | #endif /* __MENDER_UTILS_PRIV_H__ */ 178 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - component: gitlab.com/Northern.tech/Mender/mendertesting/commit-lint@master 3 | - project: 'Northern.tech/Mender/mendertesting' 4 | file: 5 | # QA-1046 Remove after hardening sign-off checks in the modern commit linter 6 | - '.gitlab-ci-check-commits-signoffs.yml' 7 | - '.gitlab-ci-github-status-updates.yml' 8 | - local: "/.gitlab/release.yaml" 9 | 10 | stages: 11 | - test 12 | - changelog 13 | - release 14 | - trigger 15 | - publish 16 | - .post 17 | 18 | variables: 19 | # mender-artifact version for tests 20 | MENDER_ARTIFACT_VERSION: 21 | description: "mender-artifact version for tests" 22 | value: 4.2.0 23 | MENDER_MCU_INTEGRATION_REVISION: 24 | description: | 25 | Revision of mender-mcu-integration to trigger. 26 | Should correspond to the gitlab branch: `pr_XXX` 27 | value: main 28 | 29 | default: 30 | tags: 31 | - hetzner-podman 32 | 33 | .test:static: 34 | stage: test 35 | image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/ubuntu:24.04 36 | needs: [] 37 | before_script: 38 | - apt-get update && apt-get install -y git clang-format pcregrep 39 | 40 | test:static:license: 41 | extends: .test:static 42 | script: 43 | - ./.github/workflows/check_headers.sh 44 | 45 | test:static:code: 46 | extends: .test:static 47 | script: 48 | - ./.github/workflows/check_include_guards.sh 49 | - ./.github/workflows/check_equivalence_tests.sh 50 | - ./.github/workflows/check_code_format.sh 51 | - ./.github/workflows/check_allocations.sh 52 | 53 | test:smoke-build:posix: 54 | stage: test 55 | image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/debian:12-slim 56 | needs: [] 57 | before_script: 58 | - apt-get update && apt-get install -yqq 59 | cmake git make pkg-config python3 60 | libcurl4-openssl-dev libcjson-dev 61 | script: 62 | - cmake -C cmake/CMake_posix_defaults.txt -B build tests/smoke 63 | - cmake --build build --parallel $(nproc --all) 64 | - ./build/mender-mcu-client.elf --help 65 | 66 | test:smoke-build:weak: 67 | stage: test 68 | image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/debian:12-slim 69 | needs: [] 70 | before_script: 71 | - apt-get update && apt-get install -yqq 72 | cmake git make pkg-config python3 73 | libcjson-dev 74 | script: 75 | - cmake -C cmake/CMake_weak_defaults.txt -B build tests/smoke 76 | - cmake --build build --parallel $(nproc --all) 77 | - ./build/mender-mcu-client.elf --help 78 | 79 | test:unit: 80 | stage: test 81 | image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/debian:12-slim 82 | before_script: 83 | - apt update && apt install -yyq 84 | cmake git make pkg-config python3 85 | libcurl4-openssl-dev libcjson-dev 86 | g++ lcov wget 87 | # Fetch and install mender-artifact 88 | - wget "https://downloads.mender.io/repos/workstation-tools/pool/main/m/mender-artifact/mender-artifact_${MENDER_ARTIFACT_VERSION}-1+debian+bookworm_amd64.deb" 89 | -O mender-artifact.deb && 90 | apt install -yyq ./mender-artifact.deb 91 | script: 92 | - cmake -D COVERAGE=ON tests/unit/ 93 | - make --jobs=$(nproc --all) --keep-going coverage 94 | artifacts: 95 | expire_in: 2w 96 | reports: 97 | junit: /tests/unit/reports/*.xml 98 | paths: 99 | - coverage.lcov 100 | 101 | .test:static:template: 102 | stage: test 103 | image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/ubuntu:24.04 104 | before_script: 105 | - apt update && apt install -yyq 106 | cmake git make pkg-config python3 107 | libcurl4-openssl-dev libcjson-dev 108 | clang wget 109 | # Fetch and install mender-artifact 110 | - wget "https://downloads.mender.io/repos/workstation-tools/pool/main/m/mender-artifact/mender-artifact_${MENDER_ARTIFACT_VERSION}-1+ubuntu+noble_amd64.deb" 111 | -O mender-artifact.deb && 112 | apt install -yyq ./mender-artifact.deb 113 | - export CC=$(which clang) 114 | - export CXX=$(which clang++) 115 | script: 116 | - cmake -D CMAKE_BUILD_TYPE=${BUILD_TYPE} tests/unit 117 | - make --jobs=$(nproc --all) --keep-going check 118 | 119 | test:static:asan: 120 | extends: .test:static:template 121 | variables: 122 | BUILD_TYPE: ASan 123 | 124 | test:static:threadsan: 125 | extends: .test:static:template 126 | tags: 127 | # Hetzner Podman fails with Result: Segmentation fault 128 | # Falling back to GCP runners 129 | - mender-qa-worker-generic-light 130 | variables: 131 | BUILD_TYPE: ThreadSan 132 | 133 | test:static:undefinedsan: 134 | extends: .test:static:template 135 | variables: 136 | BUILD_TYPE: UndefSan 137 | 138 | test:static:release: 139 | extends: .test:static:template 140 | variables: 141 | BUILD_TYPE: Release 142 | 143 | trigger:mender-mcu-integration: 144 | stage: trigger 145 | trigger: 146 | project: Northern.tech/Mender/mender-mcu-integration 147 | branch: ${MENDER_MCU_INTEGRATION_REVISION} 148 | strategy: depend 149 | variables: 150 | MENDER_MCU_REVISION: $CI_COMMIT_SHA 151 | PARENT_MENDER_MCU_PIPELINE_ID: $CI_PIPELINE_ID 152 | PARENT_MENDER_MCU_COMMIT_BRANCH: $CI_COMMIT_BRANCH 153 | 154 | publish:tests: 155 | stage: publish 156 | image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/python:3.11 157 | dependencies: 158 | - test:unit 159 | before_script: 160 | # https://github.com/coverallsapp/coverage-reporter 161 | - wget -qO- https://coveralls.io/coveralls-linux.tar.gz | tar xz -C /usr/local/bin 162 | variables: 163 | COVERALLS_PARALLEL: true 164 | COVERALLS_FLAG_NAME: "unit-tests" 165 | COVERALLS_SERVICE_NAME: "gitlab-ci" 166 | COVERALLS_GIT_BRANCH: $CI_COMMIT_BRANCH 167 | COVERALLS_GIT_COMMIT: $CI_COMMIT_SHA 168 | COVERALLS_REPO_TOKEN: $COVERALLS_TOKEN 169 | script: 170 | - coveralls report --build-number $CI_PIPELINE_ID 171 | 172 | 173 | coveralls:finish-build: 174 | stage: .post 175 | variables: 176 | COVERALLS_WEBHOOK_URL: "https://coveralls.io/webhook" 177 | COVERALLS_RERUN_BUILD_URL: "https://coveralls.io/rerun_build" 178 | COVERALLS_GIT_BRANCH: $CI_COMMIT_BRANCH 179 | COVERALLS_GIT_COMMIT: $CI_COMMIT_SHA 180 | image: curlimages/curl-base 181 | script: 182 | - 'curl -k ${COVERALLS_WEBHOOK_URL}?repo_token=${COVERALLS_TOKEN} -d "payload[build_num]=$CI_PIPELINE_ID&payload[status]=done"' 183 | - 'curl -k "${COVERALLS_RERUN_BUILD_URL}?repo_token=${COVERALLS_TOKEN}&build_num=${CI_PIPELINE_ID}"' 184 | -------------------------------------------------------------------------------- /target/zephyr/mender-artifact.cmake: -------------------------------------------------------------------------------- 1 | # @file mender-artifact.cmake 2 | # @brief CMake code to generate the Mender Artifact 3 | # 4 | # Copyright Northern.tech AS 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | # Check for the tool and the Artifact Name. The rest of the parameters have defaults 19 | find_program(mender_artifact_found mender-artifact) 20 | if(NOT mender_artifact_found) 21 | message(FATAL_ERROR "mender-artifact not found in PATH. Visit https://docs.mender.io/downloads#mender-artifact to download the tool or disable Artifact generation with MENDER_ARTIFACT_GENERATE") 22 | endif() 23 | 24 | # Fail if version mender-artifact version doesn't have the Artifact size functionality 25 | if (CONFIG_MENDER_ARTIFACT_SIZE_LIMITS) 26 | execute_process(COMMAND mender-artifact write module-image --help OUTPUT_VARIABLE HELP_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) 27 | string(FIND "${HELP_OUTPUT}" "--warn-artifact-size" FOUND_ARTIFACT_SIZE) 28 | if (FOUND_ARTIFACT_SIZE LESS 0) 29 | message(FATAL_ERROR "Setting Artifact size limits require mender-artifact >= 4.2.0") 30 | endif() 31 | endif() 32 | 33 | # Print a warning on empty Artifact name 34 | if(CONFIG_MENDER_ARTIFACT_NAME STREQUAL "") 35 | message(WARNING "MENDER_ARTIFACT_NAME cannot be empty; Artifact generation will fail. Set the variable in your build or alternatively disable the feature with CONFIG_MENDER_ARTIFACT_GENERATE=n") 36 | endif() 37 | 38 | # Assemble the mender-artifact arguments 39 | set(mender_artifact_cmd mender-artifact write module-image) 40 | # No compression 41 | set(mender_artifact_cmd ${mender_artifact_cmd} --compression none) 42 | # Artifact name 43 | set(mender_artifact_cmd ${mender_artifact_cmd} --artifact-name '${CONFIG_MENDER_ARTIFACT_NAME}') 44 | # Update Module 45 | set(mender_artifact_cmd ${mender_artifact_cmd} --type ${CONFIG_MENDER_ARTIFACT_TYPE}) 46 | # Device type 47 | string(REPLACE " " ";" device_type_list ${CONFIG_MENDER_DEVICE_TYPES_COMPATIBLE}) 48 | foreach(device_type ${device_type_list}) 49 | set(mender_artifact_cmd ${mender_artifact_cmd} --device-type ${device_type}) 50 | endforeach() 51 | # Artifact provides 52 | if(NOT CONFIG_MENDER_ARTIFACT_PROVIDES STREQUAL "") 53 | string(REPLACE " " ";" provides_list ${CONFIG_MENDER_ARTIFACT_PROVIDES}) 54 | foreach(provides ${provides_list}) 55 | set(mender_artifact_cmd ${mender_artifact_cmd} --provides ${provides}) 56 | endforeach() 57 | endif() 58 | # Artifact depends 59 | if(NOT CONFIG_MENDER_ARTIFACT_DEPENDS STREQUAL "") 60 | string(REPLACE " " ";" depends_list ${CONFIG_MENDER_ARTIFACT_DEPENDS}) 61 | foreach(depends ${depends_list}) 62 | set(mender_artifact_cmd ${mender_artifact_cmd} --depends ${depends}) 63 | endforeach() 64 | endif() 65 | # Prefix for the default provides 66 | set(mender_artifact_cmd ${mender_artifact_cmd} --software-filesystem ${CONFIG_MENDER_ARTIFACT_SOFTWARE_FILESYSTEM}) 67 | set(mender_artifact_cmd ${mender_artifact_cmd} --software-name ${CONFIG_MENDER_ARTIFACT_SOFTWARE_NAME}) 68 | # Set fail/warn limits on Artifact size 69 | if (CONFIG_MENDER_ARTIFACT_WARN_SIZE) 70 | set(mender_artifact_cmd ${mender_artifact_cmd} --warn-artifact-size ${CONFIG_MENDER_ARTIFACT_WARN_SIZE}) 71 | endif() 72 | if (CONFIG_MENDER_ARTIFACT_MAX_SIZE) 73 | set(mender_artifact_cmd ${mender_artifact_cmd} --max-artifact-size ${CONFIG_MENDER_ARTIFACT_MAX_SIZE}) 74 | endif() 75 | # Extra arguments 76 | if(NOT CONFIG_MENDER_ARTIFACT_EXTRA_ARGS STREQUAL "") 77 | separate_arguments(extra_args UNIX_COMMAND ${CONFIG_MENDER_ARTIFACT_EXTRA_ARGS}) 78 | set(mender_artifact_cmd ${mender_artifact_cmd} ${extra_args}) 79 | endif() 80 | # Input file 81 | if(CONFIG_MENDER_ARTIFACT_PAYLOAD_FILE STREQUAL "") 82 | set(mender_artifact_payload ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}.signed.bin) 83 | else() 84 | set(mender_artifact_payload ${CONFIG_MENDER_ARTIFACT_PAYLOAD_FILE}) 85 | endif() 86 | set(mender_artifact_cmd ${mender_artifact_cmd} --file ${mender_artifact_payload}) 87 | # Output file 88 | if(CONFIG_MENDER_ARTIFACT_OUTPUT_FILE STREQUAL "") 89 | set(mender_artifact_output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}.mender) 90 | else() 91 | set(mender_artifact_output ${CONFIG_MENDER_ARTIFACT_OUTPUT_FILE}) 92 | endif() 93 | set(mender_artifact_cmd ${mender_artifact_cmd} --output-path ${mender_artifact_output}) 94 | 95 | 96 | #### Design note ### 97 | # 98 | # Ideally, we would have used the existing hook from Zephyr project to trigger the 99 | # Mender Artifact build as a "Build Event" 100 | # (https://cmake.org/cmake/help/latest/command/add_custom_command.html#build-events) 101 | # through extra_post_build_commands with something like: 102 | # 103 | # set_property( 104 | # GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${mender_artifact_cmd} 105 | # ) 106 | # set_property( 107 | # GLOBAL APPEND PROPERTY extra_post_build_byproducts ${mender_artifact_output} 108 | # ) 109 | # 110 | # However, the Mender Artifact post build command would depend on the signed 111 | # kernel, which is in itself generated through a post build command 112 | # (https://github.com/zephyrproject-rtos/zephyr/blob/v4.0.0/cmake/mcuboot.cmake#L149) 113 | # and there is no way to "sort" the command or declare interdependencies between 114 | # them. 115 | # 116 | # So here is the workaround: as a post build command just remove the Artifact, 117 | # so that we clear any stale Artifact every time that we build a new kernel. And 118 | # then as custom target that runs always, we check and generate the Artifact 119 | # opportunistically. 120 | # 121 | ################## 122 | 123 | set_property( 124 | GLOBAL APPEND PROPERTY 125 | extra_post_build_commands 126 | COMMAND 127 | rm -f ${mender_artifact_output} 128 | ) 129 | 130 | add_custom_target( 131 | mender-artifact ALL 132 | COMMAND 133 | test -f ${mender_artifact_output} || 134 | echo "Generating Mender Artifact ${CONFIG_MENDER_ARTIFACT_NAME} for devices ${CONFIG_MENDER_DEVICE_TYPES_COMPATIBLE} from ${mender_artifact_payload}" && 135 | ${mender_artifact_cmd} 136 | DEPENDS 137 | ${mender_artifact_payload} 138 | BYPRODUCTS 139 | ${mender_artifact_output} 140 | ) 141 | -------------------------------------------------------------------------------- /target/posix/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # @file CMakeLists.txt 2 | # @brief mender-mcu-client static library CMakeLists file 3 | # 4 | # Copyright joelguittet and mender-mcu-client contributors 5 | # Copyright Northern.tech AS 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | cmake_minimum_required(VERSION 3.16.3) 20 | 21 | # Library project 22 | project(mender-mcu-client LANGUAGES C) 23 | 24 | # Include helpers to define default cache and MENDER_MCU_ variables 25 | include(../../cmake/CMake_posix_defaults.txt) 26 | include(../../cmake/mender_mcu_sources.txt) 27 | 28 | # Compiler options 29 | if (CONFIG_MENDER_ALL_WARNINGS_AS_ERRORS) 30 | add_compile_options(-Wall -Wextra -Werror -Wpointer-arith) 31 | endif() 32 | 33 | # Creation of the library 34 | add_library(mender-mcu-client STATIC) 35 | target_sources(mender-mcu-client PRIVATE ${MENDER_MCU_SOURCES}) 36 | target_include_directories(mender-mcu-client PUBLIC ${MENDER_MCU_INCLUDE}) 37 | target_include_directories(mender-mcu-client PUBLIC ${MENDER_MCU_INCLUDE}) 38 | target_include_directories(mender-mcu-client PRIVATE ${MENDER_PRIV_INCLUDE}) 39 | 40 | option(COVERAGE "Turn coverage instrumentation on (Default: OFF)" OFF) 41 | if($CACHE{COVERAGE}) 42 | target_compile_options(mender-mcu-client PRIVATE --coverage) 43 | endif() 44 | 45 | # POSIX definitions, mimicking what KConfig defines for Zephyr OS builds 46 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_ARTIFACT_NAME=\"${CONFIG_MENDER_ARTIFACT_NAME}\") 47 | if (CONFIG_MENDER_SERVER_HOST) 48 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_SERVER_HOST=\"${CONFIG_MENDER_SERVER_HOST}\") 49 | endif() 50 | if (CONFIG_MENDER_SERVER_TENANT_TOKEN) 51 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_SERVER_TENANT_TOKEN=\"${CONFIG_MENDER_SERVER_TENANT_TOKEN}\") 52 | endif() 53 | if (CONFIG_MENDER_DEVICE_TIER) 54 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_DEVICE_TIER=\"${CONFIG_MENDER_DEVICE_TIER}\") 55 | endif() 56 | if (CONFIG_MENDER_DEVICE_TYPE) 57 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_DEVICE_TYPE=\"${CONFIG_MENDER_DEVICE_TYPE}\") 58 | endif() 59 | if (CONFIG_MENDER_CLIENT_UPDATE_POLL_INTERVAL) 60 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_CLIENT_UPDATE_POLL_INTERVAL=${CONFIG_MENDER_CLIENT_UPDATE_POLL_INTERVAL}) 61 | endif() 62 | if (CONFIG_MENDER_RETRY_ERROR_BACKOFF) 63 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_RETRY_ERROR_BACKOFF=${CONFIG_MENDER_RETRY_ERROR_BACKOFF}) 64 | endif() 65 | if (CONFIG_MENDER_RETRY_ERROR_MAX_BACKOFF) 66 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_RETRY_ERROR_MAX_BACKOFF=${CONFIG_MENDER_RETRY_ERROR_MAX_BACKOFF}) 67 | endif() 68 | if (CONFIG_MENDER_CLIENT_INVENTORY_DISABLE) 69 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_CLIENT_INVENTORY_DISABLE) 70 | endif() 71 | if (CONFIG_MENDER_CLIENT_INVENTORY_REFRESH_INTERVAL) 72 | target_compile_definitions(mender-mcu-client PRIVATE CONFIG_MENDER_CLIENT_INVENTORY_REFRESH_INTERVAL=${CONFIG_MENDER_CLIENT_INVENTORY_REFRESH_INTERVAL}) 73 | endif() 74 | if (CONFIG_MENDER_ZEPHYR_IMAGE_UPDATE_MODULE) 75 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_ZEPHYR_IMAGE_UPDATE_MODULE) 76 | endif() 77 | if (CONFIG_MENDER_LOG_LEVEL) 78 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_LOG_LEVEL=${CONFIG_MENDER_LOG_LEVEL}) 79 | endif() 80 | if (CONFIG_MENDER_FULL_PARSE_ARTIFACT) 81 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_FULL_PARSE_ARTIFACT) 82 | endif() 83 | if (CONFIG_MENDER_PROVIDES_DEPENDS) 84 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_PROVIDES_DEPENDS) 85 | endif() 86 | if (CONFIG_MENDER_COMMIT_REQUIRE_AUTH) 87 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_COMMIT_REQUIRE_AUTH) 88 | endif() 89 | if (CONFIG_MENDER_ERRORS_THRESHOLD_NET) 90 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_ERRORS_THRESHOLD_NET=${CONFIG_MENDER_ERRORS_THRESHOLD_NET}) 91 | endif() 92 | if (CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT) 93 | target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT=${CONFIG_MENDER_ERRORS_THRESHOLD_REBOOT}) 94 | endif() 95 | 96 | find_package(PkgConfig REQUIRED) 97 | 98 | # Depencency: cJSON. Rely on the system provided package 99 | pkg_check_modules(cjson REQUIRED libcjson) 100 | target_compile_options(mender-mcu-client PUBLIC ${cjson_CFLAGS}) 101 | target_link_libraries(mender-mcu-client PRIVATE cjson) 102 | 103 | # Depencency: Mbed TLS. Fetch the project from upstream 104 | # This is because the popular Linux distributions (Fedora, Ubuntu) are stuck in 2.x version 105 | # due to an breaking API change in 3.x. As Zephyr project uses 3.x, we want to avoid poluting 106 | # the code with many ifdefs for the two major versions 107 | include(FetchContent) 108 | FetchContent_Declare( 109 | MbedTLS 110 | GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls 111 | GIT_TAG v3.6.2 112 | DOWNLOAD_EXTRACT_TIMESTAMP TRUE 113 | FIND_PACKAGE_ARGS NAMES MbedTLS 114 | ) 115 | 116 | # We don't want to build MbedTLS tests and utilities. The only working way to do 117 | # so seems to be to preset the variables/options MbedTLS uses for this before we 118 | # "include" it. Unfortunately, they are not not prefixed and don't have very 119 | # specific names. See 120 | # https://github.com/Mbed-TLS/mbedtls/issues/2824#issuecomment-2457546685 for 121 | # details. 122 | set(ENABLE_TESTING OFF CACHE BOOL "" FORCE) 123 | set(ENABLE_PROGRAMS OFF CACHE BOOL "" FORCE) 124 | message(STATUS "Fetching MbedTLS...") 125 | FetchContent_MakeAvailable(MbedTLS) 126 | unset(ENABLE_TESTING CACHE) 127 | unset(ENABLE_PROGRAMS CACHE) 128 | 129 | find_package(MbedTLS REQUIRED) 130 | target_link_libraries(mender-mcu-client PRIVATE MbedTLS::mbedtls) 131 | 132 | # mbedtls error strings 133 | option(MENDER_MBEDTLS_ERROR_STR "Enable mbedtls error strings" OFF) 134 | if (CONFIG_MENDER_PLATFORM_TLS_TYPE STREQUAL "mbedtls") 135 | if (MENDER_MBEDTLS_ERROR_STR) 136 | target_compile_definitions(mender-mcu-client PRIVATE MBEDTLS_ERROR_C) 137 | endif() 138 | endif() 139 | 140 | # generic/curl network implementation 141 | if(CONFIG_MENDER_PLATFORM_NET_TYPE MATCHES "generic/curl") 142 | target_link_libraries(mender-mcu-client PRIVATE curl) 143 | endif() 144 | 145 | # Define version 146 | include("${MENDER_MCU_ROOT}/cmake/git_helper.cmake") 147 | git_describe(${MENDER_MCU_ROOT} BUILD_VERSION_NAME) 148 | add_definitions("-DMENDER_CLIENT_VERSION=\"${BUILD_VERSION_NAME}\"") 149 | -------------------------------------------------------------------------------- /src/include/artifact.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file artifact.h 3 | * @brief Mender artifact parser (private API) 4 | * 5 | * Copyright joelguittet and mender-mcu-client contributors 6 | * Copyright Northern.tech AS 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #ifndef __MENDER_ARTIFACT_PRIV_H__ 22 | #define __MENDER_ARTIFACT_PRIV_H__ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif /* __cplusplus */ 27 | 28 | #include "artifact-download-data.h" 29 | #include "utils.h" 30 | #include "sha.h" 31 | 32 | /** 33 | * @brief TAR block size 34 | */ 35 | #define MENDER_ARTIFACT_STREAM_BLOCK_SIZE (512) 36 | 37 | /** 38 | * @brief Artifact state machine used to process input data stream 39 | */ 40 | typedef enum { 41 | MENDER_ARTIFACT_STREAM_STATE_PARSING_HEADER = 0, /**< Currently parsing header */ 42 | MENDER_ARTIFACT_STREAM_STATE_PARSING_DATA /**< Currently parsing data */ 43 | } mender_artifact_stream_state_t; 44 | 45 | /** 46 | * @brief Artifact payloads 47 | */ 48 | typedef struct { 49 | char *type; /**< Type of the payload */ 50 | #ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT 51 | /* Provides and depends are key-value pairs e.g.: `artifact_name: "test" */ 52 | mender_key_value_list_t *provides; /**< Provides of the payload */ 53 | mender_key_value_list_t *depends; /**< Depends of the payload */ 54 | /* Clears provides is an array of provides to clear e.g.: ["artifact_name", "artifact_group"] */ 55 | char **clears_provides; /**< Clears provides of the payload (string list) */ 56 | size_t clears_provides_size; /**< Number of clears provides of the payload */ 57 | #endif 58 | cJSON *meta_data; /**< Meta-data from the header tarball, NULL if no meta-data */ 59 | } mender_artifact_payload_t; 60 | 61 | #ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT 62 | typedef struct mender_artifact_checksum_t mender_artifact_checksum_t; 63 | struct mender_artifact_checksum_t { 64 | char *filename; 65 | unsigned char manifest[MENDER_DIGEST_BUFFER_SIZE]; 66 | mender_sha256_context_t context; 67 | mender_artifact_checksum_t *next; 68 | }; 69 | #endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */ 70 | 71 | /** 72 | * @brief Artifact context 73 | */ 74 | typedef struct { 75 | mender_artifact_stream_state_t stream_state; /**< Stream state of the artifact processing */ 76 | struct { 77 | void *data; /**< Data received, concatenated chunk by chunk */ 78 | size_t length; /**< Length of the data received */ 79 | size_t size; /**< Current size of the buffer */ 80 | size_t orig_size; /**< Original size of the buffer */ 81 | } input; /**< Input data of the artifact */ 82 | struct { 83 | size_t size; /**< Number of payloads in the artifact */ 84 | mender_artifact_payload_t *values; /**< Values of payloads in the artifact */ 85 | } payloads; /**< Payloads of the artifact */ 86 | #ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT 87 | struct { 88 | mender_artifact_checksum_t *checksums; /**< Contains checksums of the artifact */ 89 | mender_key_value_list_t *provides; /**< Provides of the artifact */ 90 | mender_key_value_list_t *depends; /**< Depends of the artifact */ 91 | } artifact_info; /**< Global information about the artifact */ 92 | #endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */ 93 | struct { 94 | char *name; /**< Name of the file currently parsed */ 95 | size_t size; /**< Size of the file currently parsed (bytes) */ 96 | size_t index; /**< Index of the data in the file currently parsed (bytes), incremented block by block */ 97 | } file; /**< Information about the file currently parsed */ 98 | } mender_artifact_ctx_t; 99 | 100 | #ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT 101 | /** 102 | * @brief Function used to retrieve device type from artifact context 103 | * @param ctx Artifact context 104 | * @param device_type Device type 105 | * @return MENDER_OK if the function succeeds, error code otherwise 106 | */ 107 | mender_err_t mender_artifact_get_device_type(mender_artifact_ctx_t *ctx, const char **device_type); 108 | #endif 109 | 110 | /** 111 | * @brief Function used to create a new artifact context 112 | * @param buf_size Size of the internal buffer 113 | * @return Artifact context if the function succeeds, NULL otherwise 114 | */ 115 | mender_artifact_ctx_t *mender_artifact_create_ctx(size_t buf_size); 116 | 117 | /** 118 | * @brief Function used to get the artifact context 119 | * @return MENDER_OK if the function succeeds, error code otherwise 120 | */ 121 | mender_err_t mender_artifact_get_ctx(mender_artifact_ctx_t **ctx); 122 | 123 | /** 124 | * @brief Function used to process data from artifact stream 125 | * @param ctx Artifact context 126 | * @param input_data Input data from the stream 127 | * @param input_length Length of the input data from the stream 128 | * @param dl_data Download data for the artifact 129 | * @return MENDER_OK if the function succeeds, error code otherwise 130 | */ 131 | mender_err_t mender_artifact_process_data(mender_artifact_ctx_t *ctx, void *input_data, size_t input_length, mender_artifact_download_data_t *dl_data); 132 | 133 | /** 134 | * @brief Do integrity check to one item by comparing the manifest checksum to the computed one and remove it from the list. 135 | * @param ctx Artifact context 136 | * @param filename Unique key for the integrity item to check 137 | * @return MENDER_OK if integrity is enforced, error code otherwise 138 | * @note Call this for early validation after the processing the data of an item in the artifact stream 139 | */ 140 | mender_err_t mender_artifact_check_integrity_and_remove_item(mender_artifact_ctx_t *ctx, const char *filename); 141 | 142 | /** 143 | * @brief Do integrity checks to the remaining items by comparing the manifest checksums to the computed ones. 144 | * @param ctx Artifact context 145 | * @return MENDER_OK if integrity is enforced, error code otherwise 146 | * @note Call this after the processing of the data from the artifact stream is complete 147 | */ 148 | mender_err_t mender_artifact_check_integrity_remaining(mender_artifact_ctx_t *ctx); 149 | 150 | /** 151 | * @brief Compact the artifact context by dropping its auxiliary buffers 152 | */ 153 | void mender_artifact_compact_ctx(mender_artifact_ctx_t *ctx); 154 | 155 | /** 156 | * @brief Function used to release artifact context 157 | * @param ctx Artifact context 158 | */ 159 | void mender_artifact_release_ctx(mender_artifact_ctx_t *ctx); 160 | 161 | #ifdef __cplusplus 162 | } 163 | #endif /* __cplusplus */ 164 | 165 | #endif /* __MENDER_ARTIFACT_PRIV_H__ */ 166 | --------------------------------------------------------------------------------