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:
parent
88f74279b1
commit
7174a42e87
|
|
@ -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"
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
bootcount
|
||||||
|
*.o
|
||||||
|
.cproject
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue