ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_ota_parse.c File Reference

Phase-5 OTA configuration + manifest parsing helpers. More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_ota.h"
#include "ra8_ota_internal.h"
Include dependency graph for ra8_ota_parse.c:

Go to the source code of this file.

Enumerations

enum  ra8_ota_internal_const_t : uint32_t {
  k_ra8_ota_json_skip_max = 8U ,
  k_ra8_ota_u32_decimal_digits = 12U ,
  k_ra8_ota_u32_decimal_base = 10U ,
  k_ra8_ota_hex_alpha_offset = 10U ,
  k_ra8_ota_hex_invalid_nibble = 0xFFU ,
  k_ra8_ota_hex_chars_per_byte = 2U ,
  k_ra8_ota_hex_nibble_shift = 4U ,
  k_ra8_ota_hex_buf_bytes = 257U
}
 Internal numeric constants used by JSON / hex helpers. More...

Functions

bool priv_ota_char_in_range (char c, char lo, char hi)
 Pure char-in-range predicate – see header for full contract.
bool priv_ota_download_state_invalid (uint32_t state_idle_val, uint32_t state_downloading_val, uint32_t state)
 Pure download-state-invalid predicate – see header for full contract.
static ra8_err_t internal_validate_cfg_net (const ra8_ota_cfg_t *cfg)
 Validate the network function-pointer block of cfg.
static ra8_err_t internal_validate_cfg_crypto (const ra8_ota_cfg_t *cfg)
 Validate the crypto function-pointer block of cfg.
static ra8_err_t internal_validate_cfg_flash (const ra8_ota_cfg_t *cfg)
 Validate the flash function-pointer block of cfg.
ra8_err_t priv_ota_validate_cfg (const ra8_ota_cfg_t *cfg)
 Validate the entire OTA configuration descriptor.
static ra8_err_t internal_json_str (const char *json, const char *key, char *dst, uint32_t cap)
 Locate "key" inside a JSON-ish buffer and copy its string value (assumes minimal, well-formed manifest).
ra8_err_t priv_ota_json_u32 (const char *json, const char *key, uint32_t *out_v)
 Parse a decimal "key": NNN field out of a JSON-ish buffer.
static uint8_t internal_hex_nibble (char c)
 Decode a single hex nibble.
static uint32_t internal_hex_decode (const char *in, uint8_t *out, uint32_t out_cap)
 Decode a hex string into bytes.
static ra8_err_t internal_manifest_decode_crypto (const char *json, ra8_ota_manifest_t *out)
 Pull the sha256 + signature hex blobs out of a JSON manifest.
ra8_err_t priv_ota_manifest_decode (const char *json, ra8_ota_manifest_t *out)
 Decode every field of a JSON manifest into an ra8_ota_manifest_t.

Variables

static const char *const s_tag = "ra8_ota"
 Module log tag (private copy; immutable literal).

Detailed Description

Phase-5 OTA configuration + manifest parsing helpers.

Companion translation unit to ra8_ota.c. Holds the pure, state-free parsing and validation surface so the orchestration TU stays under the per-file line budget:

Every function here is pure with respect to module state – none of them read or write the mutable statics owned by ra8_ota.c. The read-only log tag is duplicated locally (cheap, correct for an immutable literal). No malloc anywhere (NASA Rule 3); every loop has a static upper bound (NASA Rule 2).

Since
0.1.0

Definition in file ra8_ota_parse.c.

Enumeration Type Documentation

◆ ra8_ota_internal_const_t

enum ra8_ota_internal_const_t : uint32_t

Internal numeric constants used by JSON / hex helpers.

Enumerator
k_ra8_ota_json_skip_max 

Max JSON whitespace/quote skip.

k_ra8_ota_u32_decimal_digits 

Max decimal digits in a uint32.

k_ra8_ota_u32_decimal_base 

Base for decimal parsing.

k_ra8_ota_hex_alpha_offset 

Offset added for 'a'..'f'/'A'..'F'.

k_ra8_ota_hex_invalid_nibble 

Sentinel for invalid hex nibble.

k_ra8_ota_hex_chars_per_byte 

Two hex chars per encoded byte.

k_ra8_ota_hex_nibble_shift 

Shift for high nibble in a byte.

k_ra8_ota_hex_buf_bytes 

Capacity of stack hex buffer.

Definition at line 48 of file ra8_ota_parse.c.

Function Documentation

◆ internal_hex_decode()

uint32_t internal_hex_decode ( const char * in,
uint8_t * out,
uint32_t out_cap )
static

Decode a hex string into bytes.

Returns the number of bytes decoded, or 0 on a malformed input.

Walks the input two characters at a time, calling internal_hex_nibble on each. Rejects odd-length input or any non-hex character by returning 0.

Parameters
[in]inNUL-terminated hex string.
[out]outDestination byte buffer.
[in]out_capCapacity of out in bytes.
Returns
Number of bytes written into out.
Return values
0Malformed input or capacity exceeded.
Precondition
in and out non-NULL.
in is NUL-terminated.
Postcondition
On success out[0..return-1] holds the decoded bytes.
On failure out content is unspecified.
Note
Static helper; pure function.
Since
0.1.0

Definition at line 407 of file ra8_ota_parse.c.

References internal_hex_nibble(), k_ra8_ota_hex_chars_per_byte, k_ra8_ota_hex_invalid_nibble, k_ra8_ota_hex_nibble_shift, and strlen().

Referenced by internal_manifest_decode_crypto().

◆ internal_hex_nibble()

uint8_t internal_hex_nibble ( char c)
static

Decode a single hex nibble.

Returns 0xFFU on invalid input.

Maps '0'..'9' to 0..9 and 'a'..'f' / 'A'..'F' to 10..15 via k_ra8_ota_hex_alpha_offset. Any other character returns k_ra8_ota_hex_invalid_nibble (0xFFU).

Parameters
[in]cCandidate hex character.
Returns
Nibble value 0..15.
Return values
k_ra8_ota_hex_invalid_nibbleCharacter is not a hex digit.
Precondition
None.
Postcondition
No state mutated.
Note
Static helper; pure function.
Since
0.1.0
Precondition
Module has been initialized.
Postcondition
Side effects bounded to documented state.

Definition at line 369 of file ra8_ota_parse.c.

References k_ra8_ota_hex_alpha_offset, k_ra8_ota_hex_invalid_nibble, and priv_ota_char_in_range().

Referenced by internal_hex_decode().

◆ internal_json_str()

ra8_err_t internal_json_str ( const char * json,
const char * key,
char * dst,
uint32_t cap )
static

Locate "key" inside a JSON-ish buffer and copy its string value (assumes minimal, well-formed manifest).

Uses strstr to find key, walks past the next ", captures everything up to the matching close-quote and copies it into dst with a trailing NUL. Not a general JSON parser – the manifest format is intentionally minimal.

Parameters
[in]jsonSource bytes (NUL-terminated).
[in]keyKey name to look for, e.g. "\"version\\"\".
[out]dstDestination string buffer.
[in]capCapacity of dst.
Returns
ra8_err_t outcome.
Return values
k_ra8_okString value copied into dst.
k_ra8_err_invalid_argKey not found or quotes missing.
k_ra8_err_invalid_sizeValue would not fit in dst.
Precondition
All pointer arguments are non-NULL.
json is NUL-terminated.
Postcondition
On success dst is a NUL-terminated copy of the value.
On failure dst content is undefined.
Note
Static helper; pure function.
Since
0.1.0

Definition at line 266 of file ra8_ota_parse.c.

References k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_ok, memcpy(), strchr(), strlen(), and strstr().

Referenced by internal_manifest_decode_crypto(), and priv_ota_manifest_decode().

◆ internal_manifest_decode_crypto()

ra8_err_t internal_manifest_decode_crypto ( const char * json,
ra8_ota_manifest_t * out )
static

Pull the sha256 + signature hex blobs out of a JSON manifest.

Locates the "sha256" and "signature" string fields via internal_json_str, hex-decodes them with internal_hex_decode into the manifest struct, and validates lengths.

Parameters
[in]jsonNUL-terminated JSON payload.
[out]outManifest struct to populate.
Returns
ra8_err_t outcome.
Return values
k_ra8_okBoth fields decoded.
k_ra8_err_invalid_argField missing or wrong byte length.
Precondition
Both pointers non-NULL.
json is NUL-terminated.
Postcondition
On success out->image_sha256 and out->signature populated.
On failure out content is undefined.
Note
Static helper; pure function.
Since
0.1.0

Definition at line 457 of file ra8_ota_parse.c.

References ra8_ota_manifest_t::image_sha256, internal_hex_decode(), internal_json_str(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_ota_hex_buf_bytes, k_ra8_ota_sha256_bytes, k_ra8_ota_signature_max_bytes, ra8_ota_manifest_t::signature, and ra8_ota_manifest_t::signature_len.

Referenced by priv_ota_manifest_decode().

◆ internal_validate_cfg_crypto()

ra8_err_t internal_validate_cfg_crypto ( const ra8_ota_cfg_t * cfg)
static

Validate the crypto function-pointer block of cfg.

Confirms the four crypto callbacks (sha256_init/update/final and ecdsa_verify) are all wired up. Required to hash and authenticate downloaded firmware images.

Parameters
[in]cfgCaller configuration (already verified non-NULL).
Returns
ra8_err_t outcome.
Return values
k_ra8_okAll crypto function pointers set.
k_ra8_err_null_ptrA required crypto function pointer is NULL.
Precondition
cfg is non-NULL.
Module is in the process of being initialized.
Postcondition
Returns k_ra8_ok iff every crypto pointer is non-NULL.
No state mutated.
Note
Static helper; pure validation function.
Since
0.1.0

Definition at line 164 of file ra8_ota_parse.c.

References ra8_ota_cfg_t::crypto, ra8_ota_crypto_iface_t::ecdsa_verify, k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, ra8_ota_crypto_iface_t::sha256_final, ra8_ota_crypto_iface_t::sha256_init, and ra8_ota_crypto_iface_t::sha256_update.

Referenced by priv_ota_validate_cfg().

◆ internal_validate_cfg_flash()

ra8_err_t internal_validate_cfg_flash ( const ra8_ota_cfg_t * cfg)
static

Validate the flash function-pointer block of cfg.

Confirms erase/program/set_startup/readback callbacks are wired up and the configured bank_size_bytes is non-zero and below the firmware-wide cap.

Parameters
[in]cfgCaller configuration (already verified non-NULL).
Returns
ra8_err_t outcome.
Return values
k_ra8_okAll flash callbacks set, bank size sane.
k_ra8_err_null_ptrA required flash callback is NULL.
k_ra8_err_invalid_argbank_size_bytes is zero or above the cap.
Precondition
cfg is non-NULL.
Module is in the process of being initialized.
Postcondition
Returns k_ra8_ok iff all callbacks are present and the bank size is sane.
No state mutated.
Note
Static helper; pure validation function.
Since
0.1.0

Definition at line 197 of file ra8_ota_parse.c.

References ra8_ota_flash_iface_t::bank_size_bytes, ra8_ota_flash_iface_t::erase, ra8_ota_cfg_t::flash, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_ota_max_image_bytes, ra8_ota_flash_iface_t::program, RA8_CHECK_NULL_PTR, ra8_ota_flash_iface_t::readback, s_tag, and ra8_ota_flash_iface_t::set_startup.

Referenced by priv_ota_validate_cfg().

◆ internal_validate_cfg_net()

ra8_err_t internal_validate_cfg_net ( const ra8_ota_cfg_t * cfg)
static

Validate the network function-pointer block of cfg.

Confirms cfg->net.open, cfg->net.read and cfg->net.close are all non-NULL. Required for the OTA module to fetch manifests and image chunks.

Parameters
[in]cfgCaller configuration (already verified non-NULL by priv_ota_validate_cfg).
Returns
ra8_err_t outcome.
Return values
k_ra8_okAll net function pointers set.
k_ra8_err_null_ptrA required net function pointer is NULL.
Precondition
cfg is non-NULL.
Module is in the process of being initialized.
Postcondition
Returns k_ra8_ok iff every net pointer is non-NULL.
No state mutated.
Note
Static helper; pure validation function.
Since
0.1.0

Definition at line 133 of file ra8_ota_parse.c.

References ra8_ota_net_iface_t::close, k_ra8_ok, ra8_ota_cfg_t::net, ra8_ota_net_iface_t::open, RA8_CHECK_NULL_PTR, ra8_ota_net_iface_t::read, and s_tag.

Referenced by priv_ota_validate_cfg().

◆ priv_ota_char_in_range()

bool priv_ota_char_in_range ( char c,
char lo,
char hi )

Pure char-in-range predicate – see header for full contract.

Pure predicate: ASCII char is in inclusive range [lo, hi].

Promoted helper so the line-455 AND can be driven under MC/DC.

Parameters
[in]cCharacter under test.
[in]loInclusive lower bound.
[in]hiInclusive upper bound.
Returns
Boolean predicate.
Return values
truec is in [lo, hi].
falseOutside.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 76 of file ra8_ota_parse.c.

Referenced by internal_hex_nibble().

◆ priv_ota_download_state_invalid()

bool priv_ota_download_state_invalid ( uint32_t state_idle_val,
uint32_t state_downloading_val,
uint32_t state )

Pure download-state-invalid predicate – see header for full contract.

Pure predicate: state is neither IDLE nor DOWNLOADING.

Promoted helper so the line-990 AND can be driven under MC/DC.

Parameters
[in]state_idle_valNumeric value of k_ra8_ota_state_idle.
[in]state_downloading_valNumeric value of k_ra8_ota_state_downloading.
[in]stateCandidate state value.
Returns
Boolean reject predicate.
Return values
trueCaller returns invalid-state.
falseState permits operation.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 98 of file ra8_ota_parse.c.

Referenced by ra8_ota_download_to_inactive_bank().

◆ priv_ota_json_u32()

ra8_err_t priv_ota_json_u32 ( const char * json,
const char * key,
uint32_t * out_v )

Parse a decimal "key": NNN field out of a JSON-ish buffer.

Parse a JSON-style "key": <decimal> field into a u32.

Locates key via strstr, skips past colon/quote/whitespace (bounded by k_ra8_ota_json_skip_max) then accumulates a base-10 value out of up to k_ra8_ota_u32_decimal_digits digit characters. Both inner loops are statically bounded (NASA Rule 2).

Parameters
[in]jsonSource JSON bytes (NUL-terminated).
[in]keyKey string including its quotes, e.g. "\"size\\"\".
[out]out_vReceives the parsed value on success.
Returns
ra8_err_t outcome.
Return values
k_ra8_okValue parsed into *out_v.
k_ra8_err_invalid_argKey not found or no digits after the colon.
Precondition
All pointer arguments are non-NULL.
json is NUL-terminated.
Postcondition
On success *out_v reflects the parsed unsigned value.
On failure *out_v is unchanged.
Note
Static helper; pure function.
Since
0.1.0

Definition at line 316 of file ra8_ota_parse.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_ota_json_skip_max, k_ra8_ota_u32_decimal_base, k_ra8_ota_u32_decimal_digits, strlen(), and strstr().

Referenced by priv_ota_manifest_decode().

◆ priv_ota_manifest_decode()

ra8_err_t priv_ota_manifest_decode ( const char * json,
ra8_ota_manifest_t * out )

Decode every field of a JSON manifest into an ra8_ota_manifest_t.

Zeroes *out then pulls version, url, size and finally the cryptographic fields (via internal_manifest_decode_crypto). The size is bounded by k_ra8_ota_max_image_bytes.

Parameters
[in]jsonNUL-terminated JSON payload.
[out]outDestination struct (filled even on partial errors).
Returns
ra8_err_t outcome.
Return values
k_ra8_okManifest fully decoded.
k_ra8_err_invalid_argRequired field missing or zero size.
k_ra8_err_invalid_sizeImage size above firmware-wide cap.
Precondition
Both pointers non-NULL.
json is NUL-terminated.
Postcondition
On success *out is fully populated.
On failure *out may hold a partial decode.
Note
Static helper; pure function.
Since
0.1.0

Definition at line 506 of file ra8_ota_parse.c.

References ra8_ota_manifest_t::image_size_bytes, ra8_ota_manifest_t::image_url, internal_json_str(), internal_manifest_decode_crypto(), k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_ok, k_ra8_ota_max_image_bytes, k_ra8_ota_url_max_bytes, k_ra8_ota_version_str_bytes, memset(), priv_ota_json_u32(), and ra8_ota_manifest_t::version.

Referenced by ra8_ota_check_for_update().

◆ priv_ota_validate_cfg()

ra8_err_t priv_ota_validate_cfg ( const ra8_ota_cfg_t * cfg)

Validate the entire OTA configuration descriptor.

Composes the net/crypto/flash sub-validators and verifies the manifest URL is non-empty. Promoted from TU-private static linkage so the parsing TU (ra8_ota_parse.c) can own it while ra8_ota_init in ra8_ota.c keeps calling it. The single gate every public ra8_ota_init call must pass before the module captures the config.

Parameters
[in]cfgCaller configuration (may be NULL – checked here).
Returns
ra8_err_t outcome.
Return values
k_ra8_okConfiguration is valid.
k_ra8_err_null_ptrcfg or a sub-pointer is NULL.
k_ra8_err_invalid_argBank size out of range or empty URL.
Precondition
Module init is in progress (no concurrent OTA operation).
Caller has not yet committed cfg to s_cfg.
Postcondition
Returns k_ra8_ok iff every required field is populated.
No module state mutated.
Note
Internal cross-TU helper; pure validation function.
MC/DC:
Exposes the cfg->manifest_url[0] == '\0' empty-URL gate plus the composed net/crypto/flash null-pointer checks on production source.
Since
0.1.0

Definition at line 212 of file ra8_ota_parse.c.

References internal_validate_cfg_crypto(), internal_validate_cfg_flash(), internal_validate_cfg_net(), k_ra8_err_invalid_arg, k_ra8_ok, ra8_ota_cfg_t::manifest_url, RA8_CHECK_NULL_PTR, RA8_PRIV, and s_tag.

Referenced by ra8_ota_init().

Variable Documentation

◆ s_tag

const char* const s_tag = "ra8_ota"
static

Module log tag (private copy; immutable literal).

Definition at line 42 of file ra8_ota_parse.c.