diff --git a/dist/tools/riotboot_gen_hdr/Makefile b/dist/tools/riotboot_gen_hdr/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dd57e45f27107856e5c16abc913baacd2e98fe62 --- /dev/null +++ b/dist/tools/riotboot_gen_hdr/Makefile @@ -0,0 +1,39 @@ +RIOTBASE := ../../.. +RIOT_INCLUDE := $(RIOTBASE)/sys/include +RIOT_CORE_INC := $(RIOTBASE)/core/include +NATIVE_INCLUDE := $(RIOTBASE)/cpu/native/include +COMMON_SRC := common.c +COMMON_HDR := common.h + +RIOT_HDR_SRC := \ + $(RIOTBASE)/sys/checksum/fletcher32.c \ + $(RIOTBASE)/sys/riotboot/hdr.c + +RIOT_HDR_HDR := $(RIOT_INCLUDE)/riotboot/hdr.h \ + $(RIOT_INCLUDE)/checksum/fletcher32.h \ + $(RIOTBASE)/core/include/byteorder.h + +GENHDR_SRC := $(COMMON_SRC) $(RIOT_HDR_SRC) \ + main.c genhdr.c + +GENHDR_HDR := $(COMMON_HDR) $(RIOT_HDR_HDR) + +CFLAGS += -g -I. -O3 -Wall -Wextra -pedantic -std=c99 + +ifeq ($(QUIET),1) + Q=@ +else + Q= +endif + +all: bin/genhdr + +bin/: + $(Q)mkdir -p bin + +bin/genhdr: $(GENHDR_HDR) $(GENHDR_SRC) Makefile | bin/ + $(Q)$(CC) $(CFLAGS) -I$(RIOT_INCLUDE) -I$(RIOT_CORE_INC) \ + -I$(NATIVE_INCLUDE) $(GENHDR_SRC) -o $@ + +clean: + $(Q)rm -rf bin/ diff --git a/dist/tools/riotboot_gen_hdr/common.c b/dist/tools/riotboot_gen_hdr/common.c new file mode 100644 index 0000000000000000000000000000000000000000..c3cb771b6a15c183369e5d91a5c5bc14c06b11f4 --- /dev/null +++ b/dist/tools/riotboot_gen_hdr/common.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file LICENSE for more details. + */ + +/** + * @file + * @brief Common tools for RIOT images header generation + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + */ + +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +int to_file(const char *filename, void *buf, size_t len) +{ + int fd; + + if (strcmp("-", filename)) { + fd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + } + else { + fd = STDOUT_FILENO; + } + + if (fd > 0) { + ssize_t res = write(fd, buf, len); + close(fd); + return res == (ssize_t)len; + } + else { + return fd; + } +} diff --git a/dist/tools/riotboot_gen_hdr/common.h b/dist/tools/riotboot_gen_hdr/common.h new file mode 100644 index 0000000000000000000000000000000000000000..f3380d8ffb4b3d777cb9048e8f58f9636d573a0a --- /dev/null +++ b/dist/tools/riotboot_gen_hdr/common.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file LICENSE for more details. + */ + +#ifndef COMMON_H +#define COMMON_H + +#include <stddef.h> + +#ifdef __cplusplus + extern "C" { +#endif + +/** + * @brief Write len bytes of a given buffer into a file + * + * @param[out] filename name of the file to be written + * @param[in] buf a pointer to the buffer which needs to be written + * @param[in] len the number of bytes from buf to be written + * + */ +int to_file(const char *filename, void *buf, size_t len); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* COMMON_H */ diff --git a/dist/tools/riotboot_gen_hdr/genhdr.c b/dist/tools/riotboot_gen_hdr/genhdr.c new file mode 100644 index 0000000000000000000000000000000000000000..f8559d589fddc002ff07c0a1ad94af9b6666ae46 --- /dev/null +++ b/dist/tools/riotboot_gen_hdr/genhdr.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016 Inria + * 2017 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file LICENSE for more details. + * + */ + +/** + * @author Francisco Acosta <francisco.acosta@inria.fr> + * @author Kaspar Schleiser <kaspar@schleiser.de> + */ + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> + +#include "riotboot/hdr.h" +#include "common.h" + +/** + * @brief Alignment required to set VTOR in Cortex-M0+/3/4/7 + */ +#define HDR_ALIGN (256) + +static void populate_hdr(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr) +{ + /* ensure the buffer and header have 0's */ + memset(hdr, '\0', sizeof(riotboot_hdr_t)); + + /* Generate image header */ + hdr->magic_number = RIOTBOOT_MAGIC; + hdr->version = ver; + hdr->start_addr = addr; + + /* calculate header checksum */ + hdr->chksum = riotboot_hdr_checksum(hdr); +} + +int genhdr(int argc, char *argv[]) +{ + const char generate_usage[] = "<IMG_BIN> <APP_VER> <START_ADDR> <HDR_LEN> <outfile|->"; + + /* riotboot_hdr buffer */ + uint8_t *hdr_buf; + + /* arguments storage variables */ + long app_ver_arg = 0; + long start_addr_arg = 0; + long hdr_len_arg = 0; + + /* header variables */ + size_t hdr_len = 0; + uint32_t app_ver = 0; + uint32_t start_addr = 0; + + /* helpers */ + errno = 0; + char *p; + + if (argc < 6) { + fprintf(stderr, "usage: genhdr generate %s\n", generate_usage); + return -1; + } + + app_ver_arg = strtol(argv[2], &p, 0); + if (errno != 0 || *p != '\0' || app_ver_arg > UINT32_MAX) { + fprintf(stderr, "Error: APP_VER not valid!\n"); + } + else { + app_ver = app_ver_arg; + } + + start_addr_arg = strtol(argv[3], &p, 0); + if (errno != 0 || *p != '\0' || start_addr_arg > UINT32_MAX) { + fprintf(stderr, "Error: START_ADDR not valid!\n"); + } + else { + start_addr = start_addr_arg; + } + + hdr_len_arg = strtol(argv[4], &p, 0); + if (errno != 0 || *p != '\0' || hdr_len_arg % HDR_ALIGN || hdr_len_arg > UINT32_MAX) { + fprintf(stderr, "Error: HDR_LEN not valid!\n"); + return -1; + } + else { + hdr_len = hdr_len_arg; + } + + /* prepare a 0 initialised buffer for riotboot_hdr_t */ + hdr_buf = calloc(1, hdr_len); + if (hdr_buf == NULL) { + fprintf(stderr, "Error: not enough memory!\n"); + return -1; + } + + populate_hdr((riotboot_hdr_t*)hdr_buf, app_ver, start_addr); + + /* Write the header */ + if (!to_file(argv[5], hdr_buf, hdr_len)) { + fprintf(stderr, "Error: cannot write output\n"); + free(hdr_buf); + return 1; + } + + free(hdr_buf); + + return 0; +} diff --git a/dist/tools/riotboot_gen_hdr/main.c b/dist/tools/riotboot_gen_hdr/main.c new file mode 100644 index 0000000000000000000000000000000000000000..6288fa29edda6b155c743e25f77e57aa8cceb8d1 --- /dev/null +++ b/dist/tools/riotboot_gen_hdr/main.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de> + * 2018 Inria + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file LICENSE for more details. + */ + +/** + * @file + * @brief Header generation tool for RIOT firmware images + * + * @author Francisco Acosta <francisco.acosta@inria.fr> + * @author Kaspar Schleiser <kaspar@schleiser.de> + */ + +#include <stdio.h> +#include <string.h> + +int genhdr(int argc, char *argv[]); + +int main(int argc, char *argv[]) +{ + char *usage = "genhdr generate [args]"; + + if (argc < 2) { + goto usage; + } + else if (!strcmp(argv[1], "generate")) { + return genhdr(argc - 1, &argv[1]); + } + +usage: + fprintf(stderr, "usage: %s\n", usage); + return 1; +}