From cc5b99a72598bc4adc79e69c2d1aa73e1a0b893a Mon Sep 17 00:00:00 2001 From: Norman Rasmussen Date: Sat, 22 Jan 2022 00:40:48 -0800 Subject: [PATCH] system/uniqueid: Add a tool to get the board uniqueid --- system/uniqueid/Kconfig | 14 ++ system/uniqueid/Make.defs | 23 +++ system/uniqueid/Makefile | 34 ++++ system/uniqueid/uniqueid_main.c | 282 ++++++++++++++++++++++++++++++++ 4 files changed, 353 insertions(+) create mode 100644 system/uniqueid/Kconfig create mode 100644 system/uniqueid/Make.defs create mode 100644 system/uniqueid/Makefile create mode 100644 system/uniqueid/uniqueid_main.c diff --git a/system/uniqueid/Kconfig b/system/uniqueid/Kconfig new file mode 100644 index 000000000..af885571d --- /dev/null +++ b/system/uniqueid/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config SYSTEM_UNIQUEID + tristate "'uniqueid' command" + default n + depends on BOARDCTL_UNIQUEID + ---help--- + Enable the uniqueid tool + +if SYSTEM_UNIQUEID +endif diff --git a/system/uniqueid/Make.defs b/system/uniqueid/Make.defs new file mode 100644 index 000000000..1968d725a --- /dev/null +++ b/system/uniqueid/Make.defs @@ -0,0 +1,23 @@ +############################################################################ +# apps/system/uniqueid/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_SYSTEM_UNIQUEID),) +CONFIGURED_APPS += $(APPDIR)/system/uniqueid +endif diff --git a/system/uniqueid/Makefile b/system/uniqueid/Makefile new file mode 100644 index 000000000..80b714444 --- /dev/null +++ b/system/uniqueid/Makefile @@ -0,0 +1,34 @@ +############################################################################ +# apps/system/uniqueid/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +# UNIQUEID tool built-in application info + +PROGNAME = uniqueid +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE) +MODULE = $(CONFIG_SYSTEM_UNIQUEID) + +# UNIQUEID tool + +MAINSRC = uniqueid_main.c + +include $(APPDIR)/Application.mk diff --git a/system/uniqueid/uniqueid_main.c b/system/uniqueid/uniqueid_main.c new file mode 100644 index 000000000..bf94ec79b --- /dev/null +++ b/system/uniqueid/uniqueid_main.c @@ -0,0 +1,282 @@ +/**************************************************************************** + * apps/system/uniqueid/uniqueid_main.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct cfg_s +{ + const FAR char *delim; + const FAR char *format; + uint8_t positions[CONFIG_BOARDCTL_UNIQUEID_SIZE]; + size_t count; + const FAR char *prefix; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int parse_positions(FAR char *arg, FAR uint8_t *positions, + FAR size_t *count) +{ + char *list_save; + char *list_item; + char *range_save; + char *range_item; + char *endptr; + int pos; + int pos2; + +#define APPEND_POSITION(pos) \ + do \ + { \ + if ((*count) >= CONFIG_BOARDCTL_UNIQUEID_SIZE) \ + { \ + fprintf(stderr, "ERROR: Too many bytes selected\n"); \ + return -1; \ + } \ + \ + positions[*count] = pos; \ + (*count)++; \ + } \ + while (0); + + list_item = strtok_r(arg, ",", &list_save); + while (list_item) + { + range_item = strtok_r(list_item, "-", &range_save); + pos = strtol(range_item, &endptr, 0); + if (endptr == range_item || *endptr != '\0') + { + fprintf(stderr, "ERROR: Invalid byte position: '%s'\n", + range_item); + return -1; + } + + pos--; + if (pos < 0 || pos >= CONFIG_BOARDCTL_UNIQUEID_SIZE) + { + fprintf(stderr, "ERROR: Invalid byte position: '%s'\n", + range_item); + return -1; + } + + range_item = strtok_r(0, "-", &range_save); + if (range_item) + { + pos2 = strtol(range_item, &endptr, 0); + if (endptr == range_item || *endptr != '\0') + { + fprintf(stderr, "ERROR: Invalid byte position: '%s'\n", + range_item); + return -1; + } + + pos2--; + if (pos2 < 0 || pos2 >= CONFIG_BOARDCTL_UNIQUEID_SIZE) + { + fprintf(stderr, "ERROR: Invalid byte position: '%s'\n", + range_item); + return -1; + } + + range_item = strtok_r(0, "-", &range_save); + if (range_item) + { + fprintf(stderr, "ERROR: Invalid byte range: '%d-%d-%s'\n", + pos + 1, pos2 + 1, range_item); + return -1; + } + + if (pos2 > pos) + { + for (; pos <= pos2; pos++) + { + APPEND_POSITION(pos); + } + } + else + { + for (; pos >= pos2; pos--) + { + APPEND_POSITION(pos); + } + } + } + else + { + APPEND_POSITION(pos); + } + + list_item = strtok_r(0, ",", &list_save); + } + + return 0; +} + +static int parsearg(int argc, FAR char *argv[], FAR struct cfg_s *cfg) +{ + int opt; + int len; + + while ((opt = getopt(argc, argv, ":b:d:f:p:")) != ERROR) + { + switch (opt) + { + case 'b': + if (parse_positions(optarg, cfg->positions, &cfg->count) != 0) + { + return -1; + } + break; + + case 'd': + cfg->delim = optarg; + break; + + case 'f': + len = strlen(optarg); + if (len == 0) + { + fprintf(stderr, "ERROR: Invalid format: '%s'\n", optarg); + return -1; + } + + switch (optarg[len - 1]) + { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + case 'c': + cfg->format = optarg; + break; + + default: + fprintf(stderr, "ERROR: Invalid format: '%s'\n", optarg); + return -1; + } + + break; + + case 'p': + cfg->prefix = optarg; + break; + + case ':': + fprintf(stderr, "ERROR: Option needs a value: '%c'\n", optopt); + return -1; + + case '?': + fprintf(stderr, "ERROR: Unrecognized option: '%c'\n", optopt); + return -1; + + default: + fprintf(stderr, "ERROR: Unhandled getopt: '%c'\n", opt); + return -1; + } + } + + if (optind != argc) + { + fprintf(stderr, "ERROR: Too many arguments\n"); + return -1; + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + uint8_t uniqueid[CONFIG_BOARDCTL_UNIQUEID_SIZE]; + char *formatter; + int i; + + struct cfg_s cfg = { + .format = "02x", + }; + + if (parsearg(argc, argv, &cfg) != 0) + { + return -1; + } + + if (cfg.count == 0) + { + /* Print all bytes if none were specified. */ + + cfg.count = CONFIG_BOARDCTL_UNIQUEID_SIZE; + for (i = 0; i < cfg.count; i++) + { + cfg.positions[i] = i; + } + } + + memset(uniqueid, 0, sizeof(uniqueid)); + if (boardctl(BOARDIOC_UNIQUEID, (uintptr_t)&uniqueid) != OK) + { + fprintf(stderr, "ERROR! board_uniqueid() failed\n"); + return -1; + } + + formatter = malloc(strlen(cfg.format) + 2); + sprintf(formatter, "%%%s", cfg.format); + + if (cfg.prefix != NULL) + { + printf("%s", cfg.prefix); + } + + for (i = 0; i < cfg.count; i++) + { + if (i > 0 && cfg.delim != NULL) + { + printf("%s", cfg.delim); + } + + printf(formatter, uniqueid[cfg.positions[i]]); + } + + putchar('\n'); + free(formatter); + + return EXIT_SUCCESS; +}