ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_c6link_mdl_transfer.c
Go to the documentation of this file.
1
14
16
17#include <stdint.h>
18#include <string.h>
19
20#include "ra8_attributes.h"
22
30
52 const char* url,
53 const char* destination,
54 const ra8_mdl_transfer_config_t* config,
55 const ra8_mdl_transfer_result_t* result)
56{
57 if ((link == nullptr) || (url == nullptr) || (destination == nullptr) || (config == nullptr) ||
58 (result == nullptr)) {
59 return k_ra8_err_null_ptr;
60 }
61 if ((config->storage.begin == nullptr) || (config->storage.write == nullptr) ||
62 (config->storage.commit == nullptr) || (config->storage.abort == nullptr) ||
63 (config->storage.ctx == nullptr) || (config->sha256.init == nullptr) ||
64 (config->sha256.update == nullptr) || (config->sha256.final == nullptr) ||
65 (config->sha256.ctx == nullptr)) {
66 return k_ra8_err_null_ptr;
67 }
68 if ((uint32_t)config->format > (uint32_t)k_mdl_format_rabook) {
70 }
71 if ((config->format != k_mdl_format_loose) && (config->storage.validate == nullptr)) {
72 return k_ra8_err_null_ptr;
73 }
74 const uint64_t byte_budget = (uint64_t)config->chunk_bytes * config->max_chunks;
75 if ((config->chunk_bytes == 0U) || (config->chunk_bytes > k_ra8_mdl_chunk_data_max) ||
76 (config->max_chunks == 0U) || (byte_budget > k_ra8_mdl_transfer_bytes_max)) {
78 }
79 return k_ra8_ok;
80}
81
102 ra8_err_t cause)
103{
104 ra8_err_t cancel_result = k_ra8_ok;
105 ra8_err_t abort_result = k_ra8_ok;
106 if (state->session.active) {
107 cancel_result = ra8_c6link_mdl_cancel(state->link, &state->session);
108 }
109 if (state->storage_active) {
110 abort_result = state->config->storage.abort(state->config->storage.ctx);
111 state->storage_active = false;
112 }
113 if (cause != k_ra8_ok) {
114 return cause;
115 }
116 return (cancel_result != k_ra8_ok) ? cancel_result : abort_result;
117}
118
138 const ra8_mdl_chunk_t* chunk,
139 uint64_t* bytes_stored)
140{
141 if (*bytes_stored > (UINT64_MAX - chunk->data_len)) {
143 }
144 uint16_t written = 0U;
145 ra8_err_t err =
146 config->storage.write(config->storage.ctx, chunk->data, chunk->data_len, &written);
147 if (err != k_ra8_ok) {
148 return err;
149 }
150 if (written != chunk->data_len) {
152 }
153 err = config->sha256.update(config->sha256.ctx, chunk->data, chunk->data_len);
154 if (err == k_ra8_ok) {
155 *bytes_stored += written;
156 }
157 return err;
158}
159
183 const ra8_mdl_chunk_t* chunk,
184 uint64_t bytes_stored,
185 uint32_t chunks_received,
187{
188 if ((!chunk->has_sha256) || (chunk->total_bytes != bytes_stored)) {
190 }
191 uint8_t digest[k_ra8_mdl_sha256_bytes] = {};
192 ra8_err_t err = state->config->sha256.final(state->config->sha256.ctx, digest);
193 if (err != k_ra8_ok) {
194 return err;
195 }
196 if (memcmp(digest, chunk->sha256, sizeof(digest)) != 0) {
198 }
199 if (state->config->storage.validate != nullptr) {
200 err = state->config->storage.validate(state->config->storage.ctx, bytes_stored, digest);
201 if (err != k_ra8_ok) {
202 return err;
203 }
204 }
205 err = state->config->storage.commit(state->config->storage.ctx);
206 if (err == k_ra8_ok) {
207 *result = (ra8_mdl_transfer_result_t){
208 .bytes_stored = bytes_stored,
209 .chunks_received = chunks_received,
210 .format = state->config->format,
211 .response = chunk->response,
212 };
213 memcpy(result->sha256, digest, sizeof(digest));
214 state->storage_active = false;
215 }
216 return err;
217}
218
221 const ra8_mdl_chunk_t* chunk,
222 uint64_t bytes_stored,
223 uint32_t chunks_received,
225{
226 mdl_transfer_state_t state = {.config = config, .storage_active = true};
227 return internal_mdl_transfer_commit(&state, chunk, bytes_stored, chunks_received, result);
228}
229
255 const char* url,
256 const char* destination,
257 const ra8_mdl_transfer_config_t* config,
260{
261 const ra8_err_t validation =
262 internal_mdl_transfer_validate(link, url, destination, config, result);
263 if (validation != k_ra8_ok) {
264 return validation;
265 }
266 *result = (ra8_mdl_transfer_result_t){};
267 state->link = link;
268 state->config = config;
269 ra8_err_t err = config->storage.begin(config->storage.ctx, destination);
270 if (err != k_ra8_ok) {
271 return err;
272 }
273 state->storage_active = true;
274 err = config->sha256.init(config->sha256.ctx);
275 if (err == k_ra8_ok) {
276 const ra8_mdl_request_t request = {
277 .url = url,
278 .format = config->format,
279 .http = config->http,
280 };
281 err = ra8_c6link_mdl_start_request(link, &request, &state->session);
282 }
283 return err;
284}
285
287 const char* url,
288 const char* destination,
289 const ra8_mdl_transfer_config_t* config,
291{
292 mdl_transfer_state_t state = {};
293 ra8_err_t err = internal_mdl_transfer_begin(link, url, destination, config, result, &state);
294 if (!state.storage_active) {
295 return err;
296 }
297 uint64_t bytes_stored = 0U;
298 for (uint32_t pull = 0U; (pull < config->max_chunks) && (err == k_ra8_ok); pull++) {
299 if ((config->cancel_requested != nullptr) && config->cancel_requested(config->cancel_ctx)) {
301 break;
302 }
303 ra8_mdl_chunk_t chunk = {};
304 err = ra8_c6link_mdl_next(link, &state.session, config->chunk_bytes, &chunk);
305 if ((err == k_ra8_ok) && (chunk.state == k_ra8_mdl_state_downloading)) {
306 err = internal_mdl_transfer_store(config, &chunk, &bytes_stored);
307 } else if ((err == k_ra8_ok) && (chunk.state == k_ra8_mdl_state_complete)) {
308 err = internal_mdl_transfer_commit(&state, &chunk, bytes_stored, pull + 1U, result);
309 return (err == k_ra8_ok) ? k_ra8_ok : internal_mdl_transfer_abort(&state, err);
310 // mcdc-deactivated: ra8_c6link_mdl_transfer CANCELLED dispatch guard; whenever this arm is evaluated with err == k_ra8_ok the state is necessarily CANCELLED, so the second operand cannot be flipped. DOWNLOADING and COMPLETE are consumed by the two preceding arms, ACCEPTED and every unassigned state value are rejected by internal_mdl_chunk_semantics_valid's default arm before ra8_c6link_mdl_next returns, and FAILED must carry a nonzero status by that same validator, which internal_mdl_accept_chunk returns verbatim -- so a FAILED chunk always arrives with err != k_ra8_ok.
311 } else if ((err == k_ra8_ok) && (chunk.state == k_ra8_mdl_state_cancelled)) {
313 }
314 }
315 // mcdc-deactivated: ra8_c6link_mdl_transfer exhausted-budget timeout guard; `state.session.active` is constant-true whenever err == k_ra8_ok here. The loop leaves err == k_ra8_ok only by exhausting max_chunks, and the session is deactivated only by a terminal response -- COMPLETE returns from inside the loop, CANCELLED sets err = k_ra8_err_cancelled, and FAILED returns its mandatory nonzero status -- so no reachable path arrives here with an inactive session and no earlier cause.
316 if ((err == k_ra8_ok) && state.session.active) {
317 err = k_ra8_err_timeout;
318 }
319 return internal_mdl_transfer_abort(&state, err);
320}
@ k_mdl_format_loose
Leave loose page images.
Definition mdl_format.h:36
@ k_mdl_format_rabook
Chunked reader-native book (.rabook).
Definition mdl_format.h:44
Annotation-attribute framework macros for ra8-firmware.
#define RA8_TEST_HELPER
Mark a symbol as externally-linked but only callable from tests.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_checksum_mismatch
Stored / transmitted checksum does not match computed value.
Definition ra8_err.h:465
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_timeout
Operation exceeded its time budget.
Definition ra8_err.h:188
@ k_ra8_err_cancelled
Operation cancelled before completion.
Definition ra8_err.h:229
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
@ k_ra8_mdl_chunk_data_max
Maximum raw body bytes in one chunk.
@ k_ra8_mdl_sha256_bytes
SHA-256 digest size in bytes.
@ k_ra8_mdl_state_cancelled
Job ended through explicit cancellation.
@ k_ra8_mdl_state_complete
Response carries terminal size and digest.
@ k_ra8_mdl_state_downloading
Response carries non-empty ordered bytes.
State that must be unwound together after storage begins.
ra8_c6link_t * link
Active media RPC link.
ra8_mdl_session_t session
Correlated remote session.
const ra8_mdl_transfer_config_t * config
Injected storage/hash seams.
bool storage_active
Whether local temporary storage needs abort.
One correlated bounded raw-byte response.
ra8_mdl_http_response_t response
Terminal HTTP metadata.
uint8_t data[k_ra8_mdl_chunk_data_max]
Bounded raw body bytes.
uint16_t data_len
Valid bytes in data.
uint64_t total_bytes
Advertised or independently counted total.
uint8_t sha256[k_ra8_mdl_sha256_bytes]
Complete-body SHA-256.
ra8_mdl_state_t state
DOWNLOADING or terminal state.
bool has_sha256
Whether sha256 is valid.
Complete typed HTTPS request accepted by protocol version 3.
RA8-local state for one accepted remote artifact job.
bool active
Whether next/cancel is currently valid.
ra8_err_t(* update)(void *ctx, const uint8_t *data, uint16_t len)
Feed one ordered byte span to the running hash.
ra8_err_t(* init)(void *ctx)
Reset the caller-owned context for a SHA-256 operation.
void * ctx
Hash context passed to every function.
ra8_err_t(* final)(void *ctx, uint8_t out[k_ra8_mdl_sha256_bytes])
Finalise the hash into the caller-provided digest.
ra8_err_t(* write)(void *ctx, const uint8_t *data, uint16_t len, uint16_t *written)
Append len bytes and report the exact number persisted.
ra8_err_t(* commit)(void *ctx)
Atomically publish the complete temporary object.
void * ctx
Backend context passed to every function.
ra8_err_t(* begin)(void *ctx, const char *destination)
Create private temporary state for destination.
ra8_err_t(* validate)(void *ctx, uint64_t total_bytes, const uint8_t sha256[k_ra8_mdl_sha256_bytes])
Validate artifact identity and structure before publication.
ra8_err_t(* abort)(void *ctx)
Destroy temporary state; valid after every successful begin.
ra8_mdl_sha256_iface_t sha256
Independent running digest.
void * cancel_ctx
Context for cancel_requested.
mdl_format_t format
Requested and validated artifact.
ra8_mdl_cancel_requested_fn cancel_requested
Optional cooperative cancel query.
ra8_mdl_http_policy_t http
Forwarded downloader request policy.
uint16_t chunk_bytes
Maximum bytes requested per pull.
uint32_t max_chunks
Absolute number of permitted pulls.
ra8_mdl_storage_iface_t storage
Transactional RA8-local destination.
uint8_t sha256[k_ra8_mdl_sha256_bytes]
Independently verified digest.