1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

dist/tools: add genhdr tool to generate RIOT image headers

In order to use the RIOT bootloader (riotboot) a header needs to
be created and placed before the firmware. This tool generates
such a header with the expected information by the bootloader.

Co-authored-by: Kaspar Schleiser <kaspar@schleiser.de>
This commit is contained in:
Francisco Acosta 2018-09-25 01:59:12 +02:00 committed by Kaspar Schleiser
parent 2df0abfd70
commit a638f31bce
5 changed files with 259 additions and 0 deletions

39
dist/tools/riotboot_gen_hdr/Makefile vendored Normal file
View File

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

39
dist/tools/riotboot_gen_hdr/common.c vendored Normal file
View File

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

31
dist/tools/riotboot_gen_hdr/common.h vendored Normal file
View File

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

114
dist/tools/riotboot_gen_hdr/genhdr.c vendored Normal file
View File

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

36
dist/tools/riotboot_gen_hdr/main.c vendored Normal file
View File

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