|
cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
|
Firmware slot handling: receive an image into the idle slot, verify it, and install it only once somebody accepts it on the panel. More...
#include <stdbool.h>#include <stddef.h>Go to the source code of this file.
Macros | |
| #define | OTA_ERR_MAX 160U |
| Longest version string kept from an image header, plus NUL elsewhere. | |
Functions | |
| bool | ota_mark_valid (void) |
| Confirm the running image, cancelling the rollback armed by the bootloader. | |
| const char * | ota_running_version (void) |
| The running firmware's version, from the image header. | |
| bool | ota_last_update_failed (void) |
| Whether the last update was installed and then thrown away. | |
| bool | ota_begin (size_t len, const char **err) |
Open the idle slot for an image of len bytes. | |
| bool | ota_write (const void *buf, size_t n) |
Append n bytes to the open slot. | |
| bool | ota_end (char *ver, size_t ver_n, const char **err) |
| Close and verify the received image, then stage it for the panel. | |
| void | ota_abort (void) |
| Give up on an upload in progress. Nothing is installed. Safe always. | |
| bool | ota_receiving (void) |
| Whether an upload is in flight, so a second can be refused. | |
| bool | ota_staged (char *version, size_t version_n, bool *older) |
| Fetch the version of an image that has been received and verified but not yet installed. | |
| bool | ota_commit (bool install) |
| Resolve a staged image. | |
Firmware slot handling: receive an image into the idle slot, verify it, and install it only once somebody accepts it on the panel.
This file owns the flash, not the network. The bytes arrive through the config portal (provision.h), which serves the update page and drives the three-call streaming API below; keeping the two apart means the partition logic is not entangled with a web server, and the portal has exactly one place to POST to.
Why the browser is the courier rather than esp_https_ota, which would be a tenth of the code: because that makes every terminal in the field open a connection to a third party who then knows how many units exist, where they are and which firmware each one runs. A payment terminal should not be the thing that publishes that. So:
you download the image somewhere with internet browser --HTTP--> http://192.168.4.1/api/ota (streamed to flash)
Consequence for the operator: the file has to be on the phone or laptop before they join the terminal's setup network, because that network has no route anywhere. The portal used to offer a release-list check as well; it is gone, along with the URL it fetched — see docs/ota.md.
Threat model. What keeps a stranger's firmware off the device is not the transport and not the admin code: it is the signature (CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT, see sdkconfig.defaults.release). ota_end refuses an image that is not signed by the key this firmware was built against, and it does so before the staged slot can become bootable. On top of that the portal only runs when an operator turns it on from behind the admin code, it closes itself, and nothing reboots until the received version is accepted on the panel — the same "a browser may propose, only the panel may accept" rule the payout addresses follow.
Definition in file ota.h.
| #define OTA_ERR_MAX 160U |
| void ota_abort | ( | void | ) |
Give up on an upload in progress. Nothing is installed. Safe always.
Definition at line 156 of file ota.cpp.
References s_handle, s_receiving, and TAG.
Referenced by ota_post(), and prov_stop().
| bool ota_begin | ( | size_t | len, |
| const char ** | err ) |
Open the idle slot for an image of len bytes.
Erases only the pages that will be written, which on a 1.94 MB slot is a few seconds saved with the operator watching. Refuses a second concurrent upload, a length that is not plausibly firmware, and a device whose partition table has no second app slot at all.
| [in] | len | Exact image length, from Content-Length. |
| [out] | err | Set to a caller-displayable reason on failure; never NULL on return, points at a string literal. |
Definition at line 94 of file ota.cpp.
References lock_ready(), OTA_MIN_IMAGE, refuse(), s_dst, s_handle, s_lock, s_receiving, s_staged, and TAG.
Referenced by ota_post().
| bool ota_commit | ( | bool | install | ) |
Resolve a staged image.
| [in] | install | true to make the staged slot bootable and reboot into it — this call does not return. false to discard the staging, leaving the running slot untouched. |
install true. Definition at line 291 of file ota.cpp.
References OTA_VERSION_MAX, s_lock, s_staged, s_staged_ver, and TAG.
Referenced by btn_event_cb().
| bool ota_end | ( | char * | ver, |
| size_t | ver_n, | ||
| const char ** | err ) |
Close and verify the received image, then stage it for the panel.
The gate. Checks the image's own SHA-256, and — on a signed build — its signature against the public key in the running firmware. An image that fails here never becomes bootable, whoever uploaded it. On success the version is read out of the image that was just verified, never out of anything the browser said about it, and the image is staged: written, valid, and still not bootable.
| [out] | ver | Version from the image header, may be NULL. |
| [in] | ver_n | Capacity of ver. |
| [out] | err | Displayable reason on failure; never NULL on return. |
Definition at line 167 of file ota.cpp.
References ota_running_version(), ota_version_cmp(), OTA_VERSION_MAX, s_dst, s_handle, s_lock, s_receiving, s_staged, s_staged_older, s_staged_ver, and TAG.
Referenced by ota_post().
| bool ota_last_update_failed | ( | void | ) |
Whether the last update was installed and then thrown away.
The failure this exists to name: an image installs, boots, and never reaches ota_mark_valid — because bring-up did not finish, or because somebody power-cycled the terminal during the seconds it takes — so the bootloader reverts to the slot that was working and the panel goes on reading the old version. Correct behaviour, and completely silent: indistinguishable from an update that never happened at all.
Read from the idle slot's state in otadata, so it needs no bookkeeping of its own and clears itself: the next update writes that slot and overwrites the verdict.
Definition at line 221 of file ota.cpp.
Referenced by build_settings(), and ota_mark_valid().
| bool ota_mark_valid | ( | void | ) |
Confirm the running image, cancelling the rollback armed by the bootloader.
Call once, and only once the image has proven it can drive its own hardware — panel, card reader and wallet layer all up. Not the uplink: a router or RPC provider that is down during the first boot is the venue's problem, and waiting on it rolled good images back. Until it is called, a freshly installed image is on probation: any reset that happens first (panic, watchdog, brown-out) sends the next boot back to the slot that was working. Calling it early is the same as not having rollback at all.
No-op on a build without CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE, and on a boot that is not the first after an update.
Definition at line 231 of file ota.cpp.
References ota_last_update_failed(), ota_running_version(), and TAG.
Referenced by pos_boot().
| bool ota_receiving | ( | void | ) |
Whether an upload is in flight, so a second can be refused.
Definition at line 165 of file ota.cpp.
References s_receiving.
Referenced by ota_post(), and ui_task().
| const char * ota_running_version | ( | void | ) |
The running firmware's version, from the image header.
Definition at line 263 of file ota.cpp.
References s_running_ver.
Referenced by build_ota_confirm(), build_settings(), ota_end(), ota_mark_valid(), pos_boot(), and state_get().
| bool ota_staged | ( | char * | version, |
| size_t | version_n, | ||
| bool * | older ) |
Fetch the version of an image that has been received and verified but not yet installed.
| [out] | version | Version from the staged image's header, may be NULL. |
| [in] | version_n | Capacity of version. |
| [out] | older | Set true if the staged version is behind the running one — a downgrade, which the panel must say out loud. May be NULL. |
Definition at line 275 of file ota.cpp.
References s_lock, s_staged, s_staged_older, and s_staged_ver.
Referenced by build_ota_confirm(), ota_post(), and ui_task().
| bool ota_write | ( | const void * | buf, |
| size_t | n ) |
Append n bytes to the open slot.
Definition at line 145 of file ota.cpp.
References s_handle, s_receiving, and TAG.
Referenced by ota_post().