Browse Source

Moving around stuff

master
Dustin Frisch 7 years ago
parent
commit
39cde89d66
No known key found for this signature in database GPG Key ID: B4C3BF012D9B26BE
  1. 9
      5-concept.tex
  2. 24
      6-1-build_and_deploy.tex
  3. 71
      6-2-update_mechanism.tex

9
5-concept.tex

@ -46,8 +46,15 @@ The memory mapping mechanism of the MCU allows only a single page of 1 MB of fla
As the image to download and flash possibly exceeds the size of free memory heap space, the received data must be written to flash directly.
In contrast, executing the code from the memory mapped flash while writing the same area with the downloaded update leads to unexpected behavior, as the executed code changes immediately to the updated one.
To avoid this, the flash is split into half to contain two firmware ROM slots with different versions, one being executed and one which is being downloaded.
To avoid this, the flash is split into half to contain two firmware ROM slots with different versions, one being executed and one which is being downloaded (see Figure~\ref{fig:memory_layout}).
This standby ROM slot also acts as a safety mechanism if the download fails or is interrupted as the previous version stays intact and can still be used (refer to requirement \ref{req2}).
\begin{figure}[htbp]
\centering\includegraphics[width=.98\linewidth]{flash_layout.pdf}
\caption{The flash layout used for two ROM slots.}
\label{fig:memory_layout}
\end{figure}
In case of an error, the old firmware is kept unchanged and will be used until the successful download of a newer firmware succeeds.
In addition to the two firmware ROM slots, the flash provides room for the bootloader and its configuration.

24
6-1-build_and_deploy.tex

@ -10,8 +10,8 @@ Using this method, the password is stored as \texttt{.drone.sec} file inside the
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.
\begin{lstlisting}[language=,
caption={The \textit{drone} configuration for the \textit{ESPer} project.},
label=lst:drone, basicstyle=\ttfamily\scriptsize]
caption={The \textit{drone} configuration for the \textit{ESPer} project.},
label=lst:drone, basicstyle=\ttfamily\scriptsize]
build:
image: maglab/sming
environment:
@ -74,8 +74,16 @@ Beside the environmental configuration like the WiFi credentials, \textit{MQTT}
In addition, the public key used to verify firmware signatures during updates is derived from the private key and provided as a linker object, which is linked into each firmware image (Listing~\ref{lst:public_key_object}).
This allows to use all the information inside the code without any overhead while being configurable during build time.
As the \textit{ESP-01s} is only equipped with 1 MB of flash, this means that the whole memory is mapped to a contiguous address space (refer to Section \ref{flashlayout}).
Therefore, the second ROM slot can not be re-mapped to have the same start address as the first ROM slot.
While the firmware is executed without any dynamic linking mechanism and the chip does not support position independent code, the addresses used in the ROM slots are dependent to the offset at which the firmware is stored.
This arises the need for building two firmware images, one for each target location.
To do so, a linker script for each of the two ROM slots was created, which is used to create two variations of the same firmware, only differing in ROM placement.
The two resulting firmware image files are both provided for download via \textit{HTTP 1.1} - which one to download depends on the target ROM slot and is selected by the device during the update process.
Listing~\ref{lst:linker_script} shows the only difference between the two linker scripts, where \texttt{\$\{SLOT\}} must be replaced with the slot number according to the current build.
\begin{lstlisting}[caption={Creating the linker object containing the public key.},
label=lst:public_key_object, basicstyle=\ttfamily\scriptsize]
label=lst:public_key_object, basicstyle=\ttfamily\scriptsize]
update_key_pub.bin:
echo -n "$(UPDATE_KEY)" | \
ecdsakeygen -p | \
@ -90,3 +98,13 @@ update_key_pub.o: update_key_pub.bin
The build process will create the two firmware images, 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 images are created and attached to the file.
\begin{lstlisting}[language=,
caption={Linker script to build firmware for two ROM slots.},
label=lst:linker_script, basicstyle=\ttfamily\scriptsize]
irom0_0_seg :
org = ( 0x40200000 // The memory mapping address
+ 0x2010 // Bootloader code and config
+ 1M / 2 * ${SLOT} ), // Offset for the ROM slot
len = ( 1M / 2 - 0x2010 ) // Half ROM size excl. offset
\end{lstlisting}

71
6-2-update_mechanism.tex

@ -20,51 +20,14 @@ Every time a message is received on this topic, a fetch attempt for the meta-inf
This allows faster roll-outs of updates and finer control for manual maintenance.
\subsubsection{Reprogramming the device}
As the \textit{ESP-01s} is only equipped with 1 MB of flash, this means that the whole memory is mapped to a contiguous address space (refer to Section \ref{flashlayout}).
Therefore, the second ROM slot can not be re-mapped to have the same start address as the first ROM slot.
While the firmware is executed without any dynamic linking mechanism and the chip does not support position independent code, the addresses used in the ROM slots are dependent to the offset at which the firmware is stored.
This arises the need for building two firmware images, one for each target location.
To do so, a linker script for each of the two ROM slots was created, which is used to create two variations of the same firmware, only differing in ROM placement.
The two resulting firmware image files are both provided for download via \textit{HTTP 1.1} - which one to download depends on the target ROM slot and is selected by the device during the update process.
Listing~\ref{lst:linker_script} shows the only difference between the two linker scripts, where \texttt{\$\{SLOT\}} must be replaced with the slot number according to the current build.
\begin{lstlisting}[language=,
caption={Linker script to build firmware for two ROM slots.},
label=lst:linker_script, basicstyle=\ttfamily\scriptsize]
irom0_0_seg :
org = ( 0x40200000 // The memory mapping address
+ 0x2000 // Bootloader code and config
+ 0x10 // Data offset after header
+ 1M / 2 * ${SLOT} // Offset for the ROM slot
),
len = ( 1M / 2 - 0x2010 )// Half ROM size excl. bootloader
\end{lstlisting}
For installing a firmware update, the new firmware image file is downloaded using an HTTP GET request.
\subsubsection{Verifying the cryptographic signature}
While the image is being downloaded, each chunk received in the download stream is used to update the \textit{SHA256} hash before it is written to the flash.
When the write has been finished, the next chunk is received and the process continues until all chunks have been received.
After the download of a new ROM has been finished successfully, the calculated hash is checked against the cryptographically signed hash provided in the meta-information file triggering the update using the \textit{curve25519} public key provided by the running firmware.
Only if the firmware is considered valid, the bootloader configuration is altered to boot into the new ROM slot and the device is rebooted.
\subsubsection{Reconfiguring the boot process}
For the bootloader, \textit{rBoot}\cite{rBoot} has been choosen as it is integrated within the \textit{Sming} framework and allows to boot to multiple ROM slots.
For configuration, an \textit{rBoot} specific structure is placed in the flash at a well-known location directly after the space reserved for the bootloader code.
This structure contains, among other things, the target offsets for all known ROMs and the number of the ROM to boot from on next reboot.
\begin{figure}[htbp]
\centering\includegraphics[width=.98\linewidth]{flash_layout.pdf}
\caption{The flash layout used for two ROM slots.}
\label{fig:memory_layout}
\end{figure}
To calculate the origin of application data for each ROM slot, the available memory of 1 MB is split in half and an offset of the size of the bootloader code and its configuration (0x2000 bytes) is added.
For alignment and easy debugging, the second block is shifted by the same amount of bytes as the first block.
The gap of 8192 bytes is available to applications to store data, which can persist over application updates.
The firmware files provided on the update server are the exact same ones as used to initially flash the chip for the according version.
Using the same files for flashing and updating allows better debugging by eliminating errors related to the update process itself and eases development and initial installation.
Listing~\ref{lst:choosing_rom} shows the algorithm used to determine the download address and reconfigure the bootloader.
The update server provides these files in the exact same way as it provides the meta-information files, but the path pattern differs: the suffixes \texttt{.rom0} and \texttt{.rom1} are used to provide the firmware image files for the first and second slot respectively.
For installing a firmware update, the new firmware image file is downloaded using an \textit{HTTP 1.1} \texttt{GET} request.
\begin{lstlisting}[caption={Configuring the updater to download the right firmware image and update the booloader accordingly.},
label=lst:choosing_rom, basicstyle=\ttfamily\scriptsize]
label=lst:choosing_rom, basicstyle=\ttfamily\scriptsize]
#define URL_ROM(slot) (( URL "/" DEVICE ".rom" slot ))
// Select rom slot to flash
@ -80,9 +43,21 @@ if (bootconf.current_rom == 0) {
}
\end{lstlisting}
The firmware files provided on the update server are the exact same ones as used to initially flash the chip for the according version.
Using the same files for flashing and updating allows better debugging by eliminating errors related to the update process itself and eases development and initial installation.
Listing~\ref{lst:choosing_rom} shows the algorithm used to determine the download address and reconfigure the bootloader.
The update server provides these files in the exact same way as it provides the meta-information files, but the path pattern differs: the suffixes \texttt{.rom0} and \texttt{.rom1} are used to provide the firmware image files for the first and second slot respectively.
For installing a firmware update, the new firmware image file is downloaded using an \textit{HTTP 1.1} \texttt{GET} request.
\subsubsection{Verifying the cryptographic signature}
While the image is being downloaded, each chunk received in the download stream is used to update the \textit{SHA256} hash before it is written to the flash.
When the write has been finished, the next chunk is received and the process continues until all chunks have been received.
After the download of a new ROM has been finished successfully, the calculated hash is checked against the cryptographically signed hash provided in the meta-information file triggering the update using the \textit{curve25519} public key provided by the running firmware.
Only if the firmware is considered valid, the bootloader configuration is altered to boot into the new ROM slot and the device is rebooted.
\subsubsection{Reconfiguring the boot process}
For the bootloader, \textit{rBoot}\cite{rBoot} has been choosen as it is integrated within the \textit{Sming} framework and allows to boot to multiple ROM slots.
For configuration, an \textit{rBoot} specific structure is placed in the flash at a well-known location directly after the space reserved for the bootloader code.
This structure contains, among other things, the target offsets for all known ROMs and the number of the ROM to boot from on next reboot.
To calculate the origin of each ROM slot, the available memory of 1 MB is split in half and an offset of the size of the bootloader code and its configuration (0x2010 bytes) is added.
For alignment and easy debugging, the second block is shifted by the same amount of bytes as the first block.
The gap of 8192 bytes is available to applications to store data, which can persist over application updates.
The bootloader knows about the offsets of both ROM slots and is able to boot these.
To decide which ROM slot is booted, a default is stored in the configuration area.
The bootloader will boot the default ROM slot on normal startup but uses the other ROM slot as fallback if the default ROM slot is corrupted. To switch to the other ROM slot after successful upgrade, the default slot is changed and the device is restarted.
Loading…
Cancel
Save