The purpose of this repository is to provide templates that implement a mechanism to update a device that allows it to return to a previous working state in case the update fails with these considerations:
-
The device provides a webpage at http://<your_device_ip>:8080 to receive a new image.
-
The device uses two redundant set of partitions, named A and B. Each set has a
boot
and arootfs
. -
The images are generated using
buildroot 2022.08.1
which implementsSWUpdate 2022.05
. -
The supported devices are
Raspberry Pi 2B
andRaspberry Pi Compute Module 4
.
When the device is running from one of those sets of partitions and an update is requested, the device will:
-
Write the set of partitions that is not in use with the image received.
-
Once completed, the device will restart to test the updated set of partitions.
-
If it is able to boot, it will update a file that will tell it to use that set of partitions for the next boots.
In case that the process is interrupted at any point before the last step the device will keep using the set of partitions that was not updated.
This repo also serves as a starting point to test related improvements over its basic purpose. Currently the following is due to be solved:
-
Investigate how to prevent and deal with possible corruptions of the filesystem.
-
The current
web-app
at/board/raspberrypi/generic/overlay_swupdate/var/www/swupdate/
is a copy of the one shipped withSWUpdate 2021.04
. Investigate why a newer version can't be used. For reference, a copy from SWUpdate repo (from 22-10-18) is provided at the folderswupdate_from_2022_10_18
.
For the CM4
it requires EEPROM updated to pieeprom-2022-10-18.bin
at least.
🛠Pull requests are welcome!🛠
SWUpdate deploys a web page to receive the new image provided by the user and writes it to the device.
The reboot mechanism is provided by a custom rebootp
command implemented originally by the PINN project because the original reboot
command does not inject booth the partition number and tryboot arguments required to switch partitions.
An init script called S80swupdate
is in charge of testing if the device is starting from the expected boot partition after an update has been performed making the change permanent for that case.
The autoboot
mechanism and its option tryboot_a_b are implemented to let the device to idenfity the current working boot partition and the one to test when requested by a rebootp
using the tryboot
argument.
There are variants of images to try autoboot
and tryboot
with no SWUpdate
on them.
Besides using this repo in your existing Buildroot installation using the external mechanism, there is also the option to use this docker-buildroot repo that provides a fast and convenient way to start working right away and keep multiple and independent instances for different targets at the same time.
Those are the instructions for the later case, as the ones to use your existing Buildroot installation are contained in Buildroot's documentation:
# Get a clone of [docker-buildroot][docker_buildroot], if not already present in your system:
git clone https://github.com/vidalastudillo/docker-buildroot
# Get a clone of this repo to be placed at the folder `externals/pi_swupdate`:
git clone https://github.com/maovidal/buildroot_pi_swupdate externals/pi_swupdate
# Build the Docker image:
docker build -t "advancedclimatesystems/buildroot" .
2. Setup each data-only containers for the board and mechanism you want to use.
Please note that:
-
You can setup all of them and even run them simultaneously (Determined by the amount of resources available on your hardware).
-
Each
data-only container
will contain 2 volumes at/root/buildroot/dl
and/buildroot_output
. -
Buildroot
downloads all data to the first volume, the last volume is used as build cache, cross compiler and build results organized in these folders:./externals/pi_swupdate/
: Theexternal
folder with the configs, packages, overlays and other related files../images/pi_swupdate/
: with the images to be flashed into your device.- Also, the
./target/pi_swupdate/
folder is provided to allow checking the building process.
-
To tell the
Builroot container
whichdata-only container
to use, one helper script is provided (Described in the next section in this document). -
name
will be used on the scripts to refer to this specific build.
Below you'll find the commands to setup the data-only container for every option available. Those commands will:
1. Create a data-only container
2. Set the external mechanism and returns a the value to confirm it has been recorded
3. Set the default configuration
docker run -i --name br_output_PiSWU_Pi2 advancedclimatesystems/buildroot /bin/echo "Demo SWUpdate on Pi2." && \
./externals/pi_swupdate/run_pi2.sh make BR2_EXTERNAL=/root/buildroot/externals/pi_swupdate -s printvars VARS='BR2_EXTERNAL_PISWU_CFG_PATH' && \
./externals/pi_swupdate/run_pi2.sh make pi2_defconfig
docker run -i --name br_output_PiSWU_CM4 advancedclimatesystems/buildroot /bin/echo "Demo SWUpdate on CM4." && \
./externals/pi_swupdate/run_cm4.sh make BR2_EXTERNAL=/root/buildroot/externals/pi_swupdate -s printvars VARS='BR2_EXTERNAL_PISWU_CFG_PATH' && \
./externals/pi_swupdate/run_cm4.sh make cm4_defconfig
Besides the above, other containers are provided if you just want pre-fabricated definitions to test/develop based on the tryboot
and autoboot
mechanisms. The resulting images don't offer SWUpdate
support.
docker run -i --name br_output_PiSWU_Pi2_tryboot advancedclimatesystems/buildroot /bin/echo "Demo to test tryboot mechanism on Pi2." && \
./externals/pi_swupdate/run_pi2_tryboot.sh make BR2_EXTERNAL=/root/buildroot/externals/pi_swupdate -s printvars VARS='BR2_EXTERNAL_PISWU_CFG_PATH' && \
./externals/pi_swupdate/run_pi2_tryboot.sh make pi2_tryboot_defconfig
docker run -i --name br_output_PiSWU_Pi2_autoboot advancedclimatesystems/buildroot /bin/echo "Demo to test autoboot mechanism on Pi2." && \
./externals/pi_swupdate/run_pi2_autoboot.sh make BR2_EXTERNAL=/root/buildroot/externals/pi_swupdate -s printvars VARS='BR2_EXTERNAL_PISWU_CFG_PATH' && \
./externals/pi_swupdate/run_pi2_autoboot.sh make pi2_autoboot_defconfig
docker run -i --name br_output_PiSWU_CM4_tryboot advancedclimatesystems/buildroot /bin/echo "Demo to test tryboot mechanism on CM4." && \
./externals/pi_swupdate/run_cm4_tryboot.sh make BR2_EXTERNAL=/root/buildroot/externals/pi_swupdate -s printvars VARS='BR2_EXTERNAL_PISWU_CFG_PATH' && \
./externals/pi_swupdate/run_cm4_tryboot.sh make cm4_tryboot_defconfig
docker run -i --name br_output_PiSWU_CM4_autoboot advancedclimatesystems/buildroot /bin/echo "Demo to test autoboot mechanism on CM4." && \
./externals/pi_swupdate/run_cm4_autoboot.sh make BR2_EXTERNAL=/root/buildroot/externals/pi_swupdate -s printvars VARS='BR2_EXTERNAL_PISWU_CFG_PATH' && \
./externals/pi_swupdate/run_cm4_autoboot.sh make cm4_autoboot_defconfig
A small helper script for each option has been provided to ease the use of the containers:
The ones related to the Pi2 and CM4 boards, with SWUpdate support are:
./externals/pi_swupdate/run_pi2.sh
./externals/pi_swupdate/run_cm4.sh
The ones just to test the tryboot
, autoboot
mechanisms are:
./externals/pi_swupdate/run_pi2_tryboot.sh
./externals/pi_swupdate/run_pi2_autoboot.sh
./externals/pi_swupdate/run_cm4_tryboot.sh
./externals/pi_swupdate/run_cm4_autoboot.sh
All those scripts are modified versions of the one at ./scripts/run.sh
that use their related data only
containers providing separated results.
Then you can use usual commands like this in the case of the CM4
board based on the autoboot
mechanism:
./externals/pi_swupdate/run_cm4_autoboot.sh make menuconfig
./externals/pi_swupdate/run_cm4_autoboot.sh make linux-rebuild
./externals/pi_swupdate/run_cm4_autoboot.sh make linux-menuconfig
./externals/pi_swupdate/run_cm4_autoboot.sh make all
In case you need to reload the default definitions, here there are the commands for every definition variant (please note that this will ovewrite your changes):
./externals/pi_swupdate/run_pi2.sh make pi2_defconfig
./externals/pi_swupdate/run_pi2_tryboot.sh make pi2_tryboot_defconfig
./externals/pi_swupdate/run_pi2_autoboot.sh make pi2_autoboot_defconfig
./externals/pi_swupdate/run_cm4.sh make cm4_defconfig
./externals/pi_swupdate/run_cm4_tryboot.sh make cm4_tryboot_defconfig
./externals/pi_swupdate/run_cm4_autoboot.sh make cm4_autoboot_defconfig
Once an image has been built it will be located in the folder ./images/pi_swupdate/
on your host (ie. images/pi_swupdate/cm4_autoboot/sdcard.img
) that can be flashed to the Pi
following the official Raspberry Pi documentation.
By default, once started, the Pi
will provide:
- A SSH server. You can login with the default
root
andhi
as a password. (Please use change those credentials and implement security mechanism according to your needs). - A web page at http://<your_device_ip>:8080
- A
./check.sh
script that will tell you what mountpoints are available.
You can drop the SWUpdate image
named MyProduct.swu
found at ./images/pi_swupdate/<variant>/
to that web page. You will see how the device proceeds with the image update and inform the results.
You may want to use again ./check.sh
to see the new mountpoints available.
The following partitions are created on the device's eMMC:
boot_a
located atmmcblk0p1
: Contains the boot information when the set A is the working one.boot_b
located atmmcblk0p2
: Contains the boot information when the set B is the working one.persistent
located atmmcblk0p3
: A non volatile (of course) VFAT partition available to the user to keep information that will survive images updates.rootfs_a
located atmmcblk0p5
: The root filesystem when the set A is the working one.rootfs_b
located atmmcblk0p6
: The root filesystem when the set B is the working one.
Testing tryboot
can be done as follows:
-
Starting the pi once energized:
-
Issue
rebootp 2
ThePi
will reboot into boot 2 and its default config.txt asks to load rootfs 6 You can check that with./check.sh
that should report rootfs 6 as the mountpoint -
Issue
rebootp 1
ThePi
will reboot into boot 1 and its default config.txt asks to load rootfs 5 You can check that with./check.sh
reports rootfs 5 as the mountpoint -
Issue
rebootp '2 tryboot'
ThePi
will reboot into boot 2 whose tryboot.txt has a cmdline_from_a that asks rootfs 5 You can check that with./check.sh
reports rootfs 5 as the mountpoint -
Issue
rebootp '1 tryboot'
ThePi
will reboot into boot 1 whose tryboot.txt has a cmdline_from_b that asks rootfs 6 You can check that with./check.sh
reports rootfs 6 as the mountpoint
autoboot.txt
is an undocumented mechanism of Raspberry Pi to boot from a particular partition.
The following partitions are created on the device's eMMC:
persistent
located atmmcblk0p1
: Contains theautoboot.txt
file that will tell thePi
from which parition to boot. ThePi2
variant also contains a filebootcode.bin
.boot_a
located atmmcblk0p2
: Contains the boot information when the set A is the working one.boot_b
located atmmcblk0p3
: Contains the boot information when the set B is the working one.rootfs_a
located atmmcblk0p5
: The root filesystem when the set A is the working one.rootfs_b
located atmmcblk0p6
: The root filesystem when the set B is the working one.
Testing autoboot
can be done as follows:
-
Starting the pi once energized: The
Pi
will boot from 2 and use rootfs 5. -
Issue
set_boot_partition_b.sh
and thenreboot
orrebootp
ThePi
will boot from 3 and use rootfs 6. -
Issue
set_boot_partition_a.sh
and thenreboot
orrebootp
ThePi
will boot from 2 and use rootfs 5. -
Issue
rebootp 3
ThePi
will reboot into boot 3 and its default config.txt asks to load rootfs 6 You can check that with./check.sh
that should report rootfs 6 as the mountpoint -
Issue
rebootp 2
ThePi
will reboot into boot 2 and its default config.txt asks to load rootfs 5 You can check that with./check.sh
reports rootfs 5 as the mountpoint
Also, you can test tryboot
-
Issue
rebootp '3 tryboot'
ThePi
will reboot into boot 3 whose tryboot.txt has a cmdline_from_a that asks rootfs 5 You can check that with./check.sh
reports rootfs 5 as the mountpoint -
Issue
rebootp '2 tryboot'
ThePi
will reboot into boot 2 whose tryboot.txt has a cmdline_from_b that asks rootfs 6 You can check that with./check.sh
reports rootfs 6 as the mountpoint
This software is licensed under MIT License.
© 2022 Mauricio Vidal.