diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount.bb b/meta-digi-dey/recipes-digi/bootcount/bootcount.bb new file mode 100644 index 000000000..e1b720d8e --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount.bb @@ -0,0 +1,44 @@ +# Copyright (C) 2023 Digi International + +SUMMARY = "Application to manage the bootcount value" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad" + +DEPENDS = "libubootenv" + +PV = "1.0" + +SRC_URI = " \ + file://bootcount-bin \ + file://bootcount-init/bootcount-init \ + file://bootcount-init/bootcount-init.service \ +" + +S = "${WORKDIR}/bootcount-bin" + +inherit pkgconfig systemd update-rc.d + +do_install() { + oe_runmake DESTDIR=${D} install + + # INITSCRIPT + install -d ${D}${sysconfdir}/init.d/ + install -m 0755 ${WORKDIR}/bootcount-init/bootcount-init ${D}${sysconfdir}/bootcount-init + ln -sf /etc/bootcount-init ${D}${sysconfdir}/init.d/bootcount-init + + # SYSTEMD + install -d ${D}${systemd_unitdir}/system/ + install -m 0644 ${WORKDIR}/bootcount-init/bootcount-init.service ${D}${systemd_unitdir}/system/ +} + +FILES:${PN} += " \ + ${sysconfdir}/bootcount-init \ + ${sysconfdir}/init.d/bootcount-init \ + ${systemd_unitdir}/system/bootcount-init.service \ +" + +INITSCRIPT_PACKAGES += "${PN}" +INITSCRIPT_NAME:${PN} = "bootcount-init" +INITSCRIPT_PARAMS:${PN = "start 19 2 3 4 5 . stop 21 0 1 6 ." + +SYSTEMD_SERVICE:${PN} = "bootcount-init.service" diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/.gitignore b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/.gitignore new file mode 100644 index 000000000..b87dd0a6a --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/.gitignore @@ -0,0 +1,5 @@ +bootcount +*.o +.cproject +.project +.settings/ diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/Makefile b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/Makefile new file mode 100644 index 000000000..1341e0594 --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/Makefile @@ -0,0 +1,42 @@ +# +# Copyright (c) 2023, Digi International Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +PROGRAM := bootcount + +GIT_REVISION := $(shell git rev-parse --verify --short=7 HEAD 2>/dev/null) + +CFLAGS += -Wall -DGIT_REVISION=\"$(if $(GIT_REVISION),-g$(GIT_REVISION))\" +CFLAGS += -Iinclude +CFLAGS += $(shell pkg-config --cflags libubootenv) +LDLIBS += $(shell pkg-config --libs libubootenv) + +SRCS = $(wildcard *.c) +OBJS = $(SRCS:.c=.o) + +.PHONY: all +all: $(PROGRAM) + +$(PROGRAM): $(OBJS) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +.PHONY: install +install: $(PROGRAM) + install -d $(DESTDIR)/usr/bin + install -m 0755 $(PROGRAM) $(DESTDIR)/usr/bin/ + +.PHONY: clean +clean: + -rm -f *.o $(PROGRAM) diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount.c b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount.c new file mode 100644 index 000000000..c90aa0a18 --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "bootcount_env.h" +#include "bootcount_nvmem.h" +#include "platform_utils.h" + +#define VERSION "1.0" GIT_REVISION + +#define USAGE \ + "Bootcount utility.\n" \ + "Copyright(c) Digi International Inc.\n" \ + "\n" \ + "Version: %s\n" \ + "\n" \ + "Usage: bootcount [options] \n\n" \ + " -p --print Print the current bootcount value (Default action)\n" \ + " -s --set= Set current bootcount to a specific value.\n" \ + " -r --reset Reset bootcount value to zero.\n" \ + " -h --help Print help and exit\n" \ + "\n" + +/* + * Struct used to store the pointers to the methods to read/write + * the bootcount value for each platform. + */ +struct platform_functions { + int (*read_bootcount) (void); + int (*write_bootcount) (unsigned int); +}; + +/* + * Static list of the platforms with their corresponding methods to + * access the bootcount. + */ +struct platform_functions platforms_functions[] = { + [PLATFORM_CC6QP] = {read_bootcount_env, write_bootcount_env}, + [PLATFORM_CC6SBC] = {read_bootcount_env, write_bootcount_env}, + [PLATFORM_CC6UL] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_CC8MM] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_CC8MN] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_CC8X] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_CC93] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_CCMP13] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_CCMP15] = {read_bootcount_nvmem, write_bootcount_nvmem}, + [PLATFORM_UNKNOWN] = {NULL, NULL} +}; + +/* Global variables. */ +platform_t platform; + +/* Command line variables */ +static bool read, write, reset = false; +static uint write_value; + +/** + * @brief Print usage information and exit the program with the specified exit value. + * + * @param exitval The exit status code for the program. + */ +static void usage_and_exit(int exitval) { + fprintf(stdout, USAGE, VERSION); + + exit(exitval); +} + +/** + * @brief Parses command-line options. + * + * This function parses the command-line options passed to the bootcount utility. + * + * If no options are provided (`argc == 1`), the default action is assumed to be read, + * and the 'read' flag is set to true. + * + * If invalid options or incorrect bootcount values are provided, the function prints + * error messages and exits with failure status. + * + * @param argc The number of command-line arguments. + * @param argv An array of strings containing the command-line arguments. + */ +static void parse_options(int argc, char *argv[]) { + static int opt_index, opt; + static const char *short_options = "ps:rh"; + static const struct option long_options[] = { + {"print", no_argument, NULL, 'p'}, + {"set", required_argument, NULL, 's'}, + {"reset", no_argument, NULL, 'r'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + char *endptr; + + if (argc == 1) { + /* Consider default action is print. */ + read = true; + return; + } + + while (1) { + opt = getopt_long(argc, argv, short_options, long_options, &opt_index); + if (opt == -1) + break; + + switch (opt) { + case 'p': + read = true; + break; + case 's': + write = true; + write_value = (int)strtoul(optarg, &endptr, 10); + if (*endptr) { + printf("Error: incorrect bootcount value\n"); + exit(EXIT_FAILURE); + } + break; + case 'r': + reset = true; + break; + case 'h': + usage_and_exit(EXIT_SUCCESS); + break; + default: + usage_and_exit(EXIT_FAILURE); + break; + } + } +} + +/** + * @brief Main program function and entry point. + * + * @param argc The number of command-line arguments. + * @param argv An array of strings containing the command-line arguments. + * + * @return 0 if the process finishes successfully, any other value otherwise.. + */ +int main(int argc, char *argv[]) { + int ret = 0; + struct platform_functions *pfuncs; + + /* Read and parse command line */ + parse_options(argc, argv); + + /* Determine platform. */ + platform = get_platform(); + pfuncs = &platforms_functions[platform]; + + /* Execute the requested action. */ + if (read) { + ret = pfuncs->read_bootcount(); + if (ret >= 0) { + printf("%d\n", ret); + ret = 0; + } + } else if (write) { + ret = pfuncs->write_bootcount(write_value); + } else if (reset) { + ret = pfuncs->write_bootcount(0); + } + + return ret; +} diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount_env.c b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount_env.c new file mode 100644 index 000000000..a18ecdf0e --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount_env.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "bootcount_env.h" +#include "libuboot.h" + +/* Environment variables. */ +#define ENV_VAR_UPGRADE_AVAILABLE "upgrade_available" +#define ENV_VAR_BOOTCOUNT "bootcount" + +int read_bootcount_env() { + int ret; + char* endptr; + const char *var; + + /* Obtain 'bootcount' value from environment. */ + ret = uboot_getenv(ENV_VAR_BOOTCOUNT, &var); + if (!ret) { + /* Convert read value to integer. */ + ret = (int)strtoul(var, &endptr, 10); + if (*endptr) { + printf("Error: incorrect bootcount value in environment\n"); + ret = -1; + } + } else { + fprintf(stderr, "Error: could not read '%s' variable from U-Boot environment'\n", ENV_VAR_BOOTCOUNT); + ret = -1; + } + + free((char*)var); + return ret; +} + +int write_bootcount_env(uint count) { + int ret; + char value_str[5]; + + /* Convert value to string. */ + snprintf(value_str, sizeof(value_str), "%u", count); + /* Write value to environment. */ + ret = uboot_setenv(ENV_VAR_BOOTCOUNT, value_str); + if (ret) { + fprintf(stderr, "Error: could not write '%s' variable to U-Boot environment\n", ENV_VAR_BOOTCOUNT); + ret = -1; + } else if (count == 0) { + /* Clear 'upgrade_available' variable. */ + ret = uboot_setenv(ENV_VAR_UPGRADE_AVAILABLE, NULL); + if (ret) { + fprintf(stderr, "Error: could not unset '%s' variable in U-Boot environment\n", ENV_VAR_UPGRADE_AVAILABLE); + ret = -1; + } + } else { + /* Set 'upgrade_available' variable to '1'. */ + snprintf(value_str, sizeof(value_str), "%u", 1); + ret = uboot_setenv(ENV_VAR_UPGRADE_AVAILABLE, value_str); + if (ret) { + fprintf(stderr, "Error: could not set '%s' variable in U-Boot environment\n", ENV_VAR_UPGRADE_AVAILABLE); + ret = -1; + } + } + + return ret; +} diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount_nvmem.c b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount_nvmem.c new file mode 100644 index 000000000..fa462c426 --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/bootcount_nvmem.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include "file_utils.h" +#include "bootcount_nvmem.h" +#include "platform_utils.h" + +/* Platform struct for the bootcount nvmem access */ +struct platform_nvmem { + const char *nvmem_path; + long bootcount_offset; + int bootcount_size; +}; + +/* List of platform structs for the bootcount nvmem access */ +struct platform_nvmem platforms_nvmem[] = { + [PLATFORM_CC6QP] = {NULL, 0, 1}, + [PLATFORM_CC6SBC] = {NULL, 0, 1}, + [PLATFORM_CC6UL] = {"/sys/bus/i2c/devices/0-007e/nvram", 0, 1}, + [PLATFORM_CC8MM] = {"/sys/bus/i2c/devices/0-0063/nvram", 0, 1}, + [PLATFORM_CC8MN] = {"/sys/bus/i2c/devices/0-0063/nvram", 0, 1}, + [PLATFORM_CC8X] = {"/sys/bus/i2c/devices/0-0063/nvram", 0, 1}, + [PLATFORM_CC93] = {"/sys/bus/i2c/devices/2-0052/rv3028_nvram0/nvmem", 0, 1}, + [PLATFORM_CCMP13] = {"/sys/bus/i2c/devices/2-0052/rv3028_nvram0/nvmem", 0, 1}, + [PLATFORM_CCMP15] = {"/sys/bus/i2c/devices/6-0052/rv3028_nvram0/nvmem", 0, 1}, + [PLATFORM_UNKNOWN] = {NULL, 0, 0}, +}; + +/* Variables. */ +extern platform_t platform; + +int read_bootcount_nvmem() { + char value; + int ret; + struct platform_nvmem *platform_data = &platforms_nvmem[platform]; + + ret = read_file(platform_data->nvmem_path, &value, platform_data->bootcount_offset, platform_data->bootcount_size); + if (!ret) { + return value; + } else { + return -1; + } +} + +int write_bootcount_nvmem(uint count) { + char value = (char)(count & 0xFF); + struct platform_nvmem *platform_data = &platforms_nvmem[platform]; + + return write_file(platform_data->nvmem_path, &value, platform_data->bootcount_offset, platform_data->bootcount_size); +} diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/file_utils.c b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/file_utils.c new file mode 100644 index 000000000..a5b435edd --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/file_utils.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "file_utils.h" + +int read_file(const char* path, char* buffer, long offset, int num_bytes) { + FILE* file; + int ret = -1; + + /* Sanity check. */ + if (path == NULL) { + fprintf(stderr, "Error opening file: path is NULL"); + return ret; + } + + file = fopen(path, "rb"); + if (!file) { + fprintf(stderr, "Error opening file"); + return ret; + } + + fseek(file, offset, SEEK_SET); + ret = fread(buffer, sizeof(char), num_bytes, file); + if (ret != num_bytes) { + printf("Error reading from file '%s'\n", path); + ret = -1; + } else { + ret = 0; + } + + fclose(file); + return ret; +} + +int write_file(const char* path, const char* data, long offset, int num_bytes) { + FILE* file; + int ret = -1; + + /* Sanity check. */ + if (path == NULL) { + fprintf(stderr, "Error opening file: path is NULL"); + return ret; + } + + file = fopen(path, "r+b"); + if (!file) { + fprintf(stderr, "Error opening file"); + return ret; + } + + fseek(file, offset, SEEK_SET); + ret = fwrite(data, sizeof(char), num_bytes, file); + if (ret != num_bytes) { + printf("Error writing to file '%s'\n", path); + ret = -1; + } else { + ret = 0; + } + + fclose(file); + return ret; +} diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/bootcount_env.h b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/bootcount_env.h new file mode 100644 index 000000000..072817cfd --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/bootcount_env.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef BOOTCOUNT_ENV_H +#define BOOTCOUNT_ENV_H + +#include +#include + +/** + * @brief Read the 'bootcount' variable from the U-Boot environment. + * + * This function retrieves the 'bootcount' value from the U-Boot environment and + * converts it to an integer. + * + * @return The 'bootcount' value as an integer on success, -1 on error. + */ +int read_bootcount_env(); + +/** + * @brief Set the 'bootcount' variable in the U-Boot environment. + * + * This function sets the 'bootcount' value to the given one in the U-Boot environment. + * +* @param count The new bootcount value to set. + * + * @return 0 on success, -1 on error. + */ +int write_bootcount_env(uint count); + +#endif /* BOOTCOUNT_ENV_H */ diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/bootcount_nvmem.h b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/bootcount_nvmem.h new file mode 100644 index 000000000..20d4dd301 --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/bootcount_nvmem.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef BOOTCOUNT_NVMEM_H +#define BOOTCOUNT_NVMEM_H + +#include + +/** + * @brief Read the 'bootcount' value from the NVMEM registers. + * + * The method performs an internal check to use the correct NVMEM path depending + * on the running platform. + * + * @return The 'bootcount' value as an integer on success, -1 on error. + */ +int read_bootcount_nvmem(); + +/** + * @brief Write the 'bootcount' value to the NVMEM registers. + * + * The method performs an internal check to use the correct NVMEM path depending + * on the running platform. + * + * @param count The new bootcount value to set. + * + * @return 0 on success, -1 on error. + */ +int write_bootcount_nvmem(uint count); + +#endif /* BOOTCOUNT_NVMEM_H */ diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/file_utils.h b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/file_utils.h new file mode 100644 index 000000000..776f050fe --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/file_utils.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef FILE_UTILS_H +#define FILE_UTILS_H + +/** + * @brief Reads data from a binary file into the provided buffer. + * + * This function opens the specified binary file in read mode and reads up to + * 'num_bytes' of data starting at 'offset' into the provided 'buffer'. + * + * @param path The path to the binary file to read. + * @param buffer The buffer to store the read data. + * @param offset The offset from where to start reading in the file. + * @param num_bytes The number of bytes to read. + * + * @return 0 on success, -1 on error. + */ +int read_file(const char* path, char* buffer, long offset, int num_bytes); + +/** + * @brief Writes data to a binary file at the specified offset. + * + * This function opens the specified binary file in read/write mode and writes up to + * 'num_bytes' of data from the provided 'data' buffer starting at 'offset' in the file. + * + * @param path The path to the binary file to write to. + * @param data The buffer containing the data to write to the file. + * @param offset The offset in the file where to start writing. + * @param num_bytes The number of bytes to write. + * + * @return 0 on success, -1 on error. + */ +int write_file(const char* path, const char* data, long offset, int num_bytes); + +#endif /* FILE_UTILS_H */ diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/platform_utils.h b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/platform_utils.h new file mode 100644 index 000000000..7086c1a8c --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/include/platform_utils.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef PLATFORM_UTILS_H +#define PLATFORM_UTILS_H + +#include + +/* List of all available platforms. */ +typedef enum { + PLATFORM_CC6QP, + PLATFORM_CC6SBC, + PLATFORM_CC6UL, + PLATFORM_CC8MM, + PLATFORM_CC8MN, + PLATFORM_CC8X, + PLATFORM_CC93, + PLATFORM_CCMP13, + PLATFORM_CCMP15, + PLATFORM_UNKNOWN +} platform_t; + +/* List of all platform names. */ +extern char* platform_names[]; + +/** + * @brief Retrieve the running platform. + * + * The running platform is determined by reading the corresponding entry from + * the device tree. + * + * @return The running platform, 'PLATFORM_UNKNOWN' if the platform cannot be determined. + */ +platform_t get_platform(); + +#endif /* PLATFORM_UTILS_H */ diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/platform_utils.c b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/platform_utils.c new file mode 100644 index 000000000..937ef7b57 --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-bin/platform_utils.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "file_utils.h" +#include "platform_utils.h" + +#define DT_COMPATIBLE_NODE "/proc/device-tree/compatible" + +char* platform_names[] = { + [PLATFORM_CC6QP] = "ccimx6qp", + [PLATFORM_CC6SBC] = "ccimx6sbc", + [PLATFORM_CC6UL] = "ccimx6ul", + [PLATFORM_CC8MM] = "ccimx8mm", + [PLATFORM_CC8MN] = "ccimx8mn", + [PLATFORM_CC8X] = "ccimx8x", + [PLATFORM_CC93] = "ccimx93", + [PLATFORM_CCMP13] = "ccmp13", + [PLATFORM_CCMP15] = "ccmp15", + [PLATFORM_UNKNOWN] = "unknown" +}; + +/** + * @brief Checks if the running platform matches the given platform name. + * + * The running platform is determined by reading the corresponding entry from + * the device tree. + * + * @param platform_name The name of the platform to check. + * + * @return true if the given platform name matches the running one, false otherwise. + */ +platform_t get_platform() { + FILE *fd; + char buffer[100]; + int bytes_read = 0; + platform_t platform = PLATFORM_UNKNOWN; + + fd = fopen(DT_COMPATIBLE_NODE, "r"); + if (fd == NULL) { + fprintf(stderr, "No DT node " DT_COMPATIBLE_NODE "\n"); + return platform; + } + + /* The 'compatible' node specifies multiple strings null-deliniated. The fread() will read + * the full file, however, strstr() will consider data up to the first null byte. The strings + * comparison must continue until bytes_read number is reached. + */ + while (feof(fd) == 0 && ferror(fd) == 0 && platform == PLATFORM_UNKNOWN) { + if ((bytes_read = fread(buffer, 1, sizeof(buffer)-1, fd)) > 0 ) { + buffer[bytes_read] = 0; // null-terminate the full string + char *ptr = buffer; + while (ptr < buffer + bytes_read) { + platform = 0; + while (platform < PLATFORM_UNKNOWN) { + if (strstr(ptr, platform_names[platform]) != NULL) { + goto end; + } + platform += 1; + } + ptr += strlen(ptr) + 1; + } + } + } + +end: + fclose(fd); + return platform; +} diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-init/bootcount-init b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-init/bootcount-init new file mode 100644 index 000000000..7d0bb6714 --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-init/bootcount-init @@ -0,0 +1,26 @@ +#!/bin/sh +#=============================================================================== +# +# Copyright (C) 2023 by Digi International Inc. +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published by +# the Free Software Foundation. +# +# +# !Description: Clear bootcount value +# +#=============================================================================== + +case "$1" in + start) + echo -n "Resetting bootcount value... " + bootcount -r + echo "done." + ;; + *) + echo "Usage: $0 {start}" + exit 1 + ;; +esac diff --git a/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-init/bootcount-init.service b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-init/bootcount-init.service new file mode 100755 index 000000000..22b6e042e --- /dev/null +++ b/meta-digi-dey/recipes-digi/bootcount/bootcount/bootcount-init/bootcount-init.service @@ -0,0 +1,12 @@ +[Unit] +Description=Reset bootcount value +After=default.target + +[Service] +Type=simple +RemainAfterExit=no +ExecStart=/etc/bootcount-init start +TimeoutStartSec=0 + +[Install] +WantedBy=default.target