meta-digi-dey: bootcount: add new binary application to manage the bootcount

Add a user space application to manage the bootcount from the running system. This application
allows to read, reset and set the bootcount:

Usage: bootcount [options]
  -r              --read           Read the current bootcount value (Default action)
  -s <value>      --set=<value>    Set current bootcount to a specific value.
  -x              --reset          Reset bootcount value to zero.

The binary checks the running platform underneath to perform the correct system access.

While on it, add a service to automatically execute the binary on boot to reset the bootcount value.

https://onedigi.atlassian.net/browse/DEL-8506

Signed-off-by: David Escalona <david.escalona@digi.com>
This commit is contained in:
David Escalona 2023-08-01 18:18:59 +02:00
parent 88f74279b1
commit 7174a42e87
14 changed files with 800 additions and 0 deletions

View File

@ -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"

View File

@ -0,0 +1,5 @@
bootcount
*.o
.cproject
.project
.settings/

View File

@ -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)

View File

@ -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 <getopt.h>
#include <stdio.h>
#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 <value> --set=<value> 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;
}

View File

@ -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 <stdio.h>
#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;
}

View File

@ -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 <stdbool.h>
#include <stdio.h>
#include <string.h>
#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);
}

View File

@ -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 <stdio.h>
#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;
}

View File

@ -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 <stdbool.h>
#include <stdlib.h>
/**
* @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 */

View File

@ -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 <stdlib.h>
/**
* @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 */

View File

@ -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 */

View File

@ -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 <stdbool.h>
/* 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 */

View File

@ -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 <stdio.h>
#include <string.h>
#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;
}

View File

@ -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

View File

@ -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