rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
fw_image.h File Reference

The panel's application image, read from memory: what it is, whether it is whole, and whether it is one this panel should run. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "fw_sha256.h"

Go to the source code of this file.

Data Structures

struct  fw_version_t
struct  fw_image_info_t

Macros

#define FW_HEAD_BYTES   288u
 Image header, first segment header and the application descriptor.
#define FW_IMAGE_MAGIC   0xE9u
#define FW_CHIP_ESP32P4   0x0012u
 esp_chip_id_t of the ESP32-P4: ESP_CHIP_ID_ESP32P4, 0x0012, in ESP-IDF's esp_app_format.h.
#define FW_DESC_MAGIC   0xABCD5432uL
#define FW_PROJECT   "rcbench-panel"
 The CMake project name, which the descriptor carries.
#define FW_TEXT_MAX   32u
 esp_app_desc_t.version and .project_name, terminator included.
#define FW_MAX_SEGMENTS   16u

Enumerations

enum  fw_err_t {
  FW_OK = 0 , FW_ERR_EMPTY , FW_ERR_SHORT , FW_ERR_TOO_BIG ,
  FW_ERR_NOT_IMAGE , FW_ERR_CHIP , FW_ERR_NO_DESC , FW_ERR_PROJECT ,
  FW_ERR_VERSION , FW_ERR_NO_HASH , FW_ERR_LENGTH , FW_ERR_HASH ,
  FW_ERR_READ , FW_ERR_RUNNING , FW_ERR_MEMORY , FW_ERR_FLASH ,
  FW_ERR_BUSY , FW_ERR_COUNT
}
enum  fw_offer_t { FW_OFFER_NEWER = 0 , FW_OFFER_OLDER , FW_OFFER_REBUILD , FW_OFFER_INSTALLED }
 What a checked image is to the panel running now. More...

Functions

const char * fw_err_str (fw_err_t e)
 The English name of e, for the console.
bool fw_version_parse (const char *text, size_t n, fw_version_t *out)
 Parses "MAJOR.MINOR.PATCH" from at most n bytes of text: digits only, each number 0 to 65535, terminated by '\0' or by the end of the field.
int fw_version_cmp (fw_version_t a, fw_version_t b)
 Compares two versions.
fw_err_t fw_image_head (const uint8_t *head, uint32_t have, uint32_t bytes, uint32_t slot, fw_image_info_t *out)
 Checks the first have bytes of an image of bytes in all, for a slot of slot bytes: size, magic, chip, descriptor, project and version.
fw_err_t fw_image_check (const uint8_t *img, uint32_t bytes, uint32_t slot, fw_image_info_t *out)
 Checks a whole image of bytes at img for a slot of slot bytes: everything fw_image_head() checks, then that the segments add up to the image's length and that the last 32 bytes are the SHA-256 of all bytes before them.
fw_offer_t fw_offer (const fw_image_info_t *running, const fw_image_info_t *image)
 Classifies a checked image against the panel running now.
bool fw_offer_installable (fw_offer_t o)
 Whether an offer is one INSTALL may act on.

Detailed Description

The panel's application image, read from memory: what it is, whether it is whole, and whether it is one this panel should run.

An ESP-IDF (Espressif Internet-of-Things Development Framework) app image starts with a 24-byte image header (first byte 0xE9, the chip ID at offset 12, the hash flag at 23), then the first segment's 8-byte header, then the 256-byte application descriptor (esp_app_desc_t) at offset 32: magic word 0xABCD5432, version at 48, project name at 80, the ELF (Executable and Linkable Format) file's SHA-256 at 176. The segments follow, then padding and a checksum byte to the next 16-byte boundary, then the SHA-256 of every byte before it.

Two depths of check. fw_image_head() reads the first FW_HEAD_BYTES, which is what an image says about itself. fw_image_check() reads the whole image and is the gate before the first erase: header, chip, descriptor, project name, version, length, size against the slot and the appended SHA-256. Neither knows where the bytes came from.

Pure C, no ESP-IDF.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ FW_DESC_MAGIC

#define FW_DESC_MAGIC   0xABCD5432uL

magic word of the application descriptor

◆ FW_IMAGE_MAGIC

#define FW_IMAGE_MAGIC   0xE9u

first byte of an ESP-IDF app image

◆ FW_MAX_SEGMENTS

#define FW_MAX_SEGMENTS   16u

ESP_IMAGE_MAX_SEGMENTS.

Enumeration Type Documentation

◆ fw_err_t

enum fw_err_t

Why an image is refused; FW_OK is none of them.

Enumerator
FW_ERR_EMPTY 

0 bytes

FW_ERR_SHORT 

shorter than its own header or segments say

FW_ERR_TOO_BIG 

larger than the slot it would go into

FW_ERR_NOT_IMAGE 

first byte is not 0xE9

FW_ERR_CHIP 

built for another chip

FW_ERR_NO_DESC 

no application descriptor at offset 32

FW_ERR_PROJECT 

another project's application

FW_ERR_VERSION 

version is not MAJOR.MINOR.PATCH

FW_ERR_NO_HASH 

built without the appended SHA-256

FW_ERR_LENGTH 

longer than its segments, or a segment overruns

FW_ERR_HASH 

the appended SHA-256 does not match

FW_ERR_READ 

the source broke off before the last byte

FW_ERR_RUNNING 

the image is the build that is running

FW_ERR_MEMORY 

no buffer to stage the image in

FW_ERR_FLASH 

an erase, a write or the final check failed

FW_ERR_BUSY 

another image is being received or waits

◆ fw_offer_t

enum fw_offer_t

What a checked image is to the panel running now.

Enumerator
FW_OFFER_NEWER 

a higher version

FW_OFFER_OLDER 

a lower version: allowed, and the question says

FW_OFFER_REBUILD 

the same version, another build (ELF SHA-256)

FW_OFFER_INSTALLED 

the build that is running: not offered

Function Documentation

◆ fw_err_str()

const char * fw_err_str ( fw_err_t e)

The English name of e, for the console.

Parameters
ethe result
Returns
the name, static

◆ fw_image_check()

fw_err_t fw_image_check ( const uint8_t * img,
uint32_t bytes,
uint32_t slot,
fw_image_info_t * out )

Checks a whole image of bytes at img for a slot of slot bytes: everything fw_image_head() checks, then that the segments add up to the image's length and that the last 32 bytes are the SHA-256 of all bytes before them.

out is filled on FW_OK.

Parameters
imgthe image
bytesthe length of the image
slotthe size of the slot, bytes
outwhat the image says about itself
Returns
FW_OK or the first check that failed

◆ fw_image_head()

fw_err_t fw_image_head ( const uint8_t * head,
uint32_t have,
uint32_t bytes,
uint32_t slot,
fw_image_info_t * out )

Checks the first have bytes of an image of bytes in all, for a slot of slot bytes: size, magic, chip, descriptor, project and version.

The length and the hash need the whole image and are not checked. have below FW_HEAD_BYTES with bytes at or above it reads as the source failing (FW_ERR_READ). out is filled on FW_OK.

Parameters
headthe first bytes of the image
havethe number of bytes at head
bytesthe length of the image
slotthe size of the slot, bytes
outwhat the image says about itself
Returns
FW_OK or the first check that failed

◆ fw_offer()

fw_offer_t fw_offer ( const fw_image_info_t * running,
const fw_image_info_t * image )

Classifies a checked image against the panel running now.

Parameters
runningthe running image
imagethe image offered
Returns
what the image is to the panel

◆ fw_offer_installable()

bool fw_offer_installable ( fw_offer_t o)

Whether an offer is one INSTALL may act on.

Parameters
othe offer
Returns
true when INSTALL may act on it

◆ fw_version_cmp()

int fw_version_cmp ( fw_version_t a,
fw_version_t b )

Compares two versions.

Parameters
athe first version
bthe second version
Returns
negative, zero or positive as a is older, the same or newer

◆ fw_version_parse()

bool fw_version_parse ( const char * text,
size_t n,
fw_version_t * out )

Parses "MAJOR.MINOR.PATCH" from at most n bytes of text: digits only, each number 0 to 65535, terminated by '\0' or by the end of the field.

Anything else ("4184795", "0.19.0-dirty", "1..2") is false.

Parameters
textthe version text
nthe bytes of text that may be read
outthe version, written on success
Returns
true when the text parses