Browse Source

Build process and signing

master
Dustin Frisch 7 years ago
parent
commit
a856f58301
No known key found for this signature in database GPG Key ID: B4C3BF012D9B26BE
  1. 36
      6-1-build_and_deploy.tex

36
6-1-build_and_deploy.tex

@ -1,10 +1,10 @@
\subsection{Build infrastructure and automatic deployment}
The CI system, which is based on \textit{drone} \cite{drone} allows to execute commands, whenever a new version is published into the \textit{Git} repository.
A corresponding \textit{drone} configuration file has been added to the source code as \texttt{.drone.yml} (Listing~\ref{lst:drone}).
A corresponding \textit{drone} configuration called \texttt{.drone.yml} exists beside the source code (Listing~\ref{lst:drone}).
Within this configuration file, settings relevant to the build process are provided to the build environment.
First, the \texttt{CONFIG=maglab} option lets the build system use an additional configuration file (\texttt{Configurion.mk.maglab}), which is stored inside the framework repository and provides information, such as the WiFi SSID.
To keep the WiFi password secret, it is not written down in the configuration file.
First, the \texttt{CONFIG=maglab} option lets the build system use an additional configuration file (\texttt{Configurion.mk.maglab}), which is stored inside the framework repository and provides environment specific information, such as the WiFi SSID.
To keep secrets like the WiFi password unexposed, it is not written down in the configuration file.
Instead, to include secrets into a build process while allowing to keep the configuration public, \textit{drone} allows to encrypt these with a repository specific key.
Using this method, the password is stored as \texttt{.drone.sec} file inside the repository from where it is injected into the build environment.
Also noticeable in Listing~\ref{lst:drone} is the firmware version, which is configured to be the first 8 letters of the \textit{Git} commit hash uniquely identifying a version of the source code.
@ -63,10 +63,32 @@ Device* getDevice() {
\end{lstlisting}
The actual compilation of the source code is mainly controlled using two \textit{Makefiles}.
The main \textit{Makefile} is built to accept a parameter for device type identifiers called \texttt{DEVICE}, and to create its whole output inside a subdirectory specific to the device type.
An additional \textit{Makefile} scans a project subdirectory and uses each directory in there as a container for device specific code.
For each of these directories, the main \textit{Makefile} is called and the subdirectories name is used as the value of the \texttt{DEVICE} parameter.
The first one is a helper \textit{Makefile} built to accept a parameter for device type identifiers called \texttt{DEVICE}, and to create its whole output inside a subdirectory specific to the device type.
In addition, the primary \textit{Makefile} scans a project subdirectory and uses each directory in there as a container for device specific code.
For each of these directories, the helper \textit{Makefile} is called and the subdirectories name is used as the value of the \texttt{DEVICE} parameter.
By splitting the build and recompiling the framework each time before intermixing it with the device specific code, the device type identifier can be used inside the shared framework code.
While building a devices firmware, the meta-information file used during updates is also created and stored beside the binary firmware image.
For development, each device can be build separately by using the device type identifier as \textit{Makefile} target.
In addition, the prefix \texttt{/flash} can be used to flash a specific firmware.
In addition, the suffix \texttt{/flash} can be used to flash a specific firmware to the device.
While building the firmware binaries for a device, the build environment provides some constants which are baked into the resulting firmware image.
Beside the environmental configuration like the \textit{WiFi} credentials, \textit{MQTT} topics and other configurable tweaks, the current device and version identifiers are provided as compile-time constants.
In addition, the public key used to verify firmware signatures during updates is derived from the private key and provided as an linker object which is linked into each firmware image (~\ref{lst:public_key_object}).
This allows to use all the information inside the code without any overhead while being configurable during build time.
\begin{lstlisting}[caption={Creating the linker object containing the public key.},
label=lst:public_key_object, basicstyle=\ttfamily\scriptsize]
update_key_pub.bin:
echo -n "$(UPDATE_KEY)" | \
ecdsakeygen -p | \
xxd -r -p > "$@"
update_key_pub.o: update_key_pub.bin
$(OBJCOPY) -I binary $< \
-B xtensa \
-O elf32-xtensa-le $@
\end{lstlisting}
The build process will create the two firmware binaries, one for each ROM slot, and the meta-information file.
To create the meta-information file, the current version identifier is written to the \texttt{.version} file.
After the build, the signatures for both firmware binaries are created and attached to the file.
Loading…
Cancel
Save