188 lines
5.3 KiB
C
188 lines
5.3 KiB
C
/*
|
|
* Copyright (c) 2023-2024 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 <errno.h>
|
|
#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_CC91] = {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_CCMP25] = {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];
|
|
if (!pfuncs->read_bootcount || !pfuncs->write_bootcount) {
|
|
printf("Platform not supported\n");
|
|
ret = -ENOTSUP;
|
|
goto end;
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
|
|
end:
|
|
return ret;
|
|
}
|