dist/tools: add firmware metadata generator#6919
dist/tools: add firmware metadata generator#6919kYc0o wants to merge 6 commits intoRIOT-OS:masterfrom
Conversation
745cc1b to
75b06f7
Compare
aabadie
left a comment
There was a problem hiding this comment.
A few inline comments. Didn't test locally.
|
|
||
| #define FW_METADATA_BIN "firmware-metadata.bin" | ||
|
|
||
| typedef struct FW_metadata { |
There was a problem hiding this comment.
This doesn't seem to follow coding conventions, why not use the explicit name: firmware_metadata ? and firmware_metadata_t below ?
Makefile.include
Outdated
| endif # BUILD_IN_DOCKER | ||
|
|
||
| firmware-metadata: all generate-metadata | ||
| $(Q)$(FW_METADATA)/bin/./generate-metadata $(BINFILE) $(VERSION) $(APPID) $(METADATA_FILE) |
There was a problem hiding this comment.
do you really need the ./ in $(Q)$(FW_METADATA)/bin/./generate-metadata ?
| all: bin bin/generate-metadata | ||
|
|
||
| bin: | ||
| mkdir bin |
There was a problem hiding this comment.
maybe use -p to avoid messages like mkdir: cannot create directory ‘bin’: File exists
| follows: | ||
|
|
||
| ```c | ||
| typedef struct FW_metadata { |
There was a problem hiding this comment.
same comment as below about structure name
| @@ -0,0 +1,163 @@ | |||
| /* | |||
| * Copyright (c) 2016, Mark Solters <msolters@gmail.com>. | |||
| * 2016, Francisco Acosta <francisco.acosta@inria.fr> | |||
There was a problem hiding this comment.
I think you should simply put Inria in the copyright
| fclose(firmware_bin); | ||
|
|
||
| /* | ||
| * TODO Sign hash |
There was a problem hiding this comment.
Do you plan to address this ?
There was a problem hiding this comment.
Yes, it will come in a following up PR.
There was a problem hiding this comment.
So I guess it can be removed from this one.
| } | ||
|
|
||
| /* Generate FW image metadata */ | ||
|
|
There was a problem hiding this comment.
this empty line is not needed
|
|
||
| (void)argc; | ||
|
|
||
| if (!argv[1]) { |
There was a problem hiding this comment.
Can you just check argc value and display the usage in case it's < 4 ?
|
|
||
| all: bin bin/generate-metadata | ||
|
|
||
| bin: |
|
|
||
| CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 | ||
|
|
||
| all: bin bin/generate-metadata |
| bin: | ||
| mkdir bin | ||
|
|
||
| bin/generate-metadata: $(METADATA_HDR) $(METADATA_SRC) |
f527342 to
13d5d9b
Compare
| bin/: | ||
| mkdir -p bin | ||
|
|
||
| bin/generate-metadata: bin/ $(METADATA_HDR) $(METADATA_SRC) |
There was a problem hiding this comment.
bin/ should be a pre-requirement instead of a requirement. A pre-requirement only needs to exist, but a newer timestamp does not force a rebuild. Creating bin/generate-metadata will touch bin/, which will tell make to recreate bin/generate-metadata in its next invocation. Pre-requirements are placed after the requirements, separated by a pipe.
There was a problem hiding this comment.
Oh! Ok I understand now. However, don't we actually want bin as a requirement? What's really the difference? Anyways,bin can only exists if a build was triggered, and if I understand correctly the contents cannot be changed by other means.
There was a problem hiding this comment.
When a file is changed, then the modification timestamp of its parent folder gets updated. A newer timestamp of a requirement of $X tells Make to rebuild $X (in here $X's parent directory is its requirement). So updating $X will make $X look outdated to Make. Every time you run Make it will update $X, which wastes a tiny amount of wall clock time.
As a rule of thumb directories should always be prerequirements, not requirements, unless you are doing something really odd. :)
There was a problem hiding this comment.
OK, thanks for the explanation, I'll modify this file accordingly.
| @@ -0,0 +1,19 @@ | |||
| RIOTBASE := ../../.. | |||
There was a problem hiding this comment.
I think this line should be:
RIOTBASE ?= $(CURDIR)/../../..
There was a problem hiding this comment.
I think since dist/tools/ is a path that will always exists in any clone of RIOT, we don't really need to define $(CURDIR), and so the relative path will always be the same.
|
@Kijewski addressed. |
aabadie
left a comment
There was a problem hiding this comment.
Added a few other comments
| @@ -0,0 +1,35 @@ | |||
| # Metadata generator for firmware verification | |||
| This program will generate a binary file containing a metadata structure as | |||
There was a problem hiding this comment.
Minor: use present instead of future.
This program generates a binary file...
| } firmware_metadata_t; | ||
| ``` | ||
|
|
||
| This structure will be filled with the data obtained from the firmware. |
There was a problem hiding this comment.
Same here: This structure is filled with...
|
|
||
| _\<output-path\>_\: The path for fimrware_metadata.bin | ||
|
|
||
| The results will be printed if the operation is successful, and a binary |
There was a problem hiding this comment.
Same, with if the sense is conditional (something like might be). Also use present:
If the operation succeeds, the results is printed out and a binary called "firmware-metadata.bin" is created (written?)
There was a problem hiding this comment.
Looking at generate-metadata.c this is not totally true: the user can set a custom output filename.
| fclose(firmware_bin); | ||
|
|
||
| /* | ||
| * TODO Sign hash |
There was a problem hiding this comment.
So I guess it can be removed from this one.
|
@kYc0o, what's the status here ? |
|
Just addressed your comments. |
aabadie
left a comment
There was a problem hiding this comment.
Changes are good to me here. ACK
|
@Kijewski all ok for you? |
|
@kYc0o, Murdock is reporting errors, can you have a look ? |
|
It's again related to the pic32 boards... @kaspar030 there is something wrong in the toolchain of Murdock2? BTW it needs rebase. |
I meant squash. |
|
|
||
| _\<appid\>_\: ID for the application in 32-bit HEX | ||
|
|
||
| _\<output-path\>_\: The path for fimrware_metadata.bin |
There was a problem hiding this comment.
fimrware_metadata.bin => firmware_metadata.bin
|
|
||
| If the operation succeeds, the results are printed out and a binary called | ||
| "firmware-metadata.bin" is written, if no _output-path_ option is specified, | ||
| in which case the file is written to the given path with the given name. |
There was a problem hiding this comment.
in which case should be removed
|
Just tested it and had problems: generate a segfault. Here is what gdb says: Leaving the output path empty works fine. |
|
|
||
| Where: | ||
|
|
||
| _\<firmware.bin\>\:_ The firmware in binary format |
There was a problem hiding this comment.
Maybe use <firmware.bin> instead so it is better readable in raw text?
There was a problem hiding this comment.
I don't get exactly what you mean...
There was a problem hiding this comment.
I think @kaspar030 means "use ` ` around <firmware.bin>". +1 on my side
|
@aabadie addressed comments. Your problem is that you didn't give a file name for the binary with the metadata. I fixed the README.md to be explicit about this. |
aabadie
left a comment
There was a problem hiding this comment.
A few other comments mainly rephrasing in the README to make things crystal clear.
| To use, you should call `generate-metadata` with the following arguments: | ||
|
|
||
| ```console | ||
| ./generate-metadata <firmware.bin> <version> <appid> <output-path> |
There was a problem hiding this comment.
<output-path> should be <output-filename> for clarity
There was a problem hiding this comment.
I think <output-filename> would lead to confusion, since we need the full path plus the file name.
| This structure is filled with the data obtained from the firmware. | ||
|
|
||
| ## Usage | ||
| To use, you should call `generate-metadata` with the following arguments: |
There was a problem hiding this comment.
To use it, call generate-metadata with the following arguments:
| _\<output-path/filename.bin\>_\: The path and name of the metadata binary file | ||
|
|
||
| If the operation succeeds, the results are printed out and a binary called | ||
| "firmware-metadata.bin" is written, if no _output-path_ option is specified. |
There was a problem hiding this comment.
This is confusing as first sight.
There was a problem hiding this comment.
What's the confusion?
| @@ -0,0 +1,36 @@ | |||
| # Metadata generator for firmware verification | |||
| This program generates a binary file containing a metadata structure as | |||
There was a problem hiding this comment.
Maybe add an empty line after title.
Quick question: does the file only contain the metadata or the metadata + the initial firmware ? If it's the second case, it should be more explicit. Otherwise, one can easily understand that the generated binary file only contain the struct.
There was a problem hiding this comment.
Maybe add an empty line after title.
What this will change?
uick question: does the file only contain the metadata or the metadata + the initial firmware ? If it's the second case, it should be more explicit. Otherwise, one can easily understand that the generated binary file only contain the struct.
It is the first case.
|
|
||
| Where: | ||
|
|
||
| _\<firmware.bin\>\:_ The firmware in binary format |
There was a problem hiding this comment.
I think @kaspar030 means "use ` ` around <firmware.bin>". +1 on my side
| char firmware_metadata_path[128]; | ||
|
|
||
| if (argc < 4) { | ||
| puts("Usage: generate-metadata <BINFILE> <VERSION> <APPID> [output path]"); |
There was a problem hiding this comment.
s/output path/output filename/
There was a problem hiding this comment.
I still think output path is ok...
|
|
||
| sha256_init(&firmware_sha256); | ||
|
|
||
| while((bytes_read = fread(firmware_buffer, 1, sizeof(firmware_buffer), firmware_bin))) { |
| /* Output metadata .bin file */ | ||
| FILE *metadata_bin; | ||
|
|
||
| uint32_t firmware_size = 0; |
There was a problem hiding this comment.
Does it matter for a native C program? In that case all the variables should be declared static in this program.
|
Actually, I don't think that beautify a lot the README would be of any use. This tool is not really meant to be used by a final user, but called automatically by the build system when building firmware updates like in the subsequent PRs. |
|
@aabadie everything good here for you? |
kaspar030
left a comment
There was a problem hiding this comment.
Let's not merge this until we have a set of PR's that actually enable OTA.
What do you mean with that? I'm about to push the last PR which enables the "updates fetch" using CoAP (though the transport method is TFTP). That would be the last PR regarding this topic. |
|
#7167 adds the firmware downloading for OTA updates. I think with this PR the firmware update functionality is complete. |
|
Closing in favour of #7457. |
Since #6450 became a bit complicated to manage, I'll start to split the work in several PRs, with the aim to ease review and have a better picture of the approach.
This PR adds a firmware metadata generator, which will produce a binary file representing a structure of this kind:
as a simplified way to characterise the contents of a firmware, while adding some security features as the sha256 hash for integrity check, as well as a field for a signed hash, which will come in a following PR.
This approach will use the current RIOT implementation of sha256 to allow portability.
To test the firmware generator, you can run the following command for any RIOT example or application:
make firmware-metadata VERSION=0x1 APPID=0xabcd1234using
VERSION=0x1andAPPID=0xabcd1234as examples.The ultimate goal is to put this metadata at the beginning of any firmware, to use it e.g. for a firmware update. This feature will come in an upcoming PR, stay tuned.