ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_storage.c
Go to the documentation of this file.
1
16#include "mdl_storage.h"
17
18#include <stdint.h>
19#include <string.h>
20
21#include "mdl_hash.h"
22#include "ra8_attributes.h"
23
25typedef enum : uint32_t {
26 k_storage_io_calls = 2000001U,
29
32 uintptr_t begin;
33 uintptr_t end;
35
37typedef struct {
38 uint64_t size_bytes;
39 uint64_t hash;
40 uint8_t* buffer;
41 uint32_t buffer_bytes;
43
63internal_make_span(const void* pointer, uint32_t bytes, internal_storage_span_t* out)
64{
65 if ((pointer == nullptr) || (bytes == 0U)) {
67 }
68 const uintptr_t begin = (uintptr_t)pointer;
69 if ((uintptr_t)bytes > (UINTPTR_MAX - begin)) {
71 }
72 *out = (internal_storage_span_t){.begin = begin, .end = begin + (uintptr_t)bytes};
73 return k_ra8_ok;
74}
75
92 const internal_storage_span_t* right)
93{
94 return (left->begin < right->end) && (right->begin < left->end);
95}
96
120 void* file_workspace,
121 uint32_t file_workspace_bytes,
122 void* transaction_workspace,
123 uint32_t transaction_workspace_bytes,
124 uint8_t* io_buffer,
125 uint32_t io_buffer_bytes)
126{
128 ra8_err_t err = internal_make_span(storage, (uint32_t)sizeof(*storage), &spans[0]);
129 if (err == k_ra8_ok) {
130 err = internal_make_span(file_workspace, file_workspace_bytes, &spans[1]);
131 }
132 if (err == k_ra8_ok) {
133 err = internal_make_span(transaction_workspace, transaction_workspace_bytes, &spans[2]);
134 }
135 if (err == k_ra8_ok) {
136 err = internal_make_span(io_buffer, io_buffer_bytes, &spans[3]);
137 }
138 if (err != k_ra8_ok) {
139 return err;
140 }
141 for (uint32_t left = 0U; left < (uint32_t)k_storage_span_count; ++left) {
142 for (uint32_t right = left + 1U; right < (uint32_t)k_storage_span_count; ++right) {
143 if (internal_overlap(&spans[left], &spans[right])) {
145 }
146 }
147 }
148 return k_ra8_ok;
149}
150
168RA8_INTERNAL static bool internal_aligned(const void* pointer, uint8_t alignment)
169{
170 if ((pointer == nullptr) || (alignment == 0U)) {
171 return false;
172 }
173 return ((uintptr_t)pointer & ((uintptr_t)alignment - 1U)) == 0U;
174}
175
177 const fw_fs_t* fs,
178 void* file_workspace,
179 uint32_t file_workspace_bytes,
180 void* transaction_workspace,
181 uint32_t transaction_workspace_bytes,
182 uint8_t* io_buffer,
183 uint32_t io_buffer_bytes)
184{
185 if (storage == nullptr) {
187 }
188 if ((fs == nullptr) || (file_workspace == nullptr) || (transaction_workspace == nullptr) ||
189 (io_buffer == nullptr) || (io_buffer_bytes == 0U)) {
191 }
193 file_workspace,
194 file_workspace_bytes,
195 transaction_workspace,
196 transaction_workspace_bytes,
197 io_buffer,
198 io_buffer_bytes);
199 if (err != k_ra8_ok) {
200 return err;
201 }
202 fw_fs_caps_t caps = {};
203 err = fw_fs_get_caps(fs, &caps);
204 if (err != k_ra8_ok) {
205 return err;
206 }
207 const uint32_t required = (uint32_t)k_fw_fs_cap_namespace | (uint32_t)k_fw_fs_cap_stream |
208 (uint32_t)k_fw_fs_cap_transactions;
209 if ((caps.flags & required) != required) {
211 }
212 if ((file_workspace_bytes < caps.file_workspace_bytes) ||
213 (transaction_workspace_bytes < caps.transaction_workspace_bytes)) {
214 return k_ra8_err_no_mem;
215 }
216 if (!internal_aligned(file_workspace, caps.file_workspace_align) ||
217 !internal_aligned(transaction_workspace, caps.transaction_workspace_align)) {
219 }
220 const mdl_storage_t candidate = {.fs = fs,
221 .file_workspace = file_workspace,
222 .transaction_workspace = transaction_workspace,
223 .io_buffer = io_buffer,
224 .file_workspace_bytes = file_workspace_bytes,
225 .transaction_workspace_bytes = transaction_workspace_bytes,
226 .io_buffer_bytes = io_buffer_bytes};
227 *storage = candidate;
228 return k_ra8_ok;
229}
230
250{
251 if (transaction->active) {
252 const ra8_err_t aborted = fw_fs_transaction_abort(transaction);
253 if (aborted != k_ra8_ok) {
254 return aborted;
255 }
256 }
257 return primary;
258}
259
281 const uint8_t* source,
282 uint32_t length,
283 uint32_t* calls)
284{
285 uint32_t offset = 0U;
286 while (offset < length) {
287 if (*calls >= (uint32_t)k_storage_io_calls) {
289 }
290 uint32_t written = 0U;
291 const ra8_err_t err =
292 fw_fs_transaction_write(transaction, source + offset, length - offset, &written);
293 ++(*calls);
294 if (err != k_ra8_ok) {
295 return err;
296 }
297 if (written == 0U) {
299 }
300 offset += written;
301 }
302 return k_ra8_ok;
303}
304
325{
326 if ((ctx == nullptr) || (staged == nullptr)) {
328 }
329 const staged_identity_t* const expected = (const staged_identity_t*)ctx;
330 uint64_t size = 0U;
331 ra8_err_t err = fw_fs_file_size(staged, &size);
332 if (err != k_ra8_ok) {
333 return err;
334 }
335 if (size != expected->size_bytes) {
337 }
338 uint64_t hash = 0U;
339 err =
340 mdl_hash_stream(staged, expected->size_bytes, expected->buffer, expected->buffer_bytes, &hash);
341 if (err != k_ra8_ok) {
342 return err;
343 }
344 return (hash == expected->hash) ? k_ra8_ok : k_ra8_err_protocol_error;
345}
346
367 const char* destination,
369{
370 fw_fs_stat_t stat = {};
371 const ra8_err_t err = fw_fs_stat(&storage->fs->names, destination, &stat);
372 if (err != k_ra8_ok) {
373 return err;
374 }
375 if (!stat.exists) {
377 return k_ra8_ok;
378 }
379 if (stat.type != k_fw_fs_node_file) {
381 }
383 return k_ra8_ok;
384}
385
405internal_source_size(const mdl_storage_t* storage, const char* source, uint64_t* size)
406{
407 fw_fs_stat_t stat = {};
408 const ra8_err_t err = fw_fs_stat(&storage->fs->names, source, &stat);
409 if (err != k_ra8_ok) {
410 return err;
411 }
412 if (!stat.exists) {
413 return k_ra8_err_not_found;
414 }
415 if (stat.type != k_fw_fs_node_file) {
417 }
418 if (stat.size_bytes > (uint64_t)k_mdl_hash_max_file_bytes) {
420 }
421 *size = stat.size_bytes;
422 return k_ra8_ok;
423}
424
445 const char* source,
446 const char* destination,
447 fw_fs_file_t* source_file,
448 fw_fs_transaction_t* transaction,
449 uint64_t* size)
450{
451 ra8_err_t err = internal_source_size(storage, source, size);
453 if (err == k_ra8_ok) {
454 err = internal_policy(storage, destination, &policy);
455 }
456 if (err == k_ra8_ok) {
457 err = fw_fs_open(&storage->fs->streams,
458 source,
460 source_file,
461 storage->file_workspace,
462 storage->file_workspace_bytes);
463 }
464 if (err != k_ra8_ok) {
465 return err;
466 }
467 err = fw_fs_transaction_begin(&storage->fs->transactions,
468 destination,
469 policy,
470 transaction,
471 storage->transaction_workspace,
473 if (err != k_ra8_ok) {
474 (void)fw_fs_close(source_file);
475 }
476 return err;
477}
478
500 fw_fs_file_t* source,
501 fw_fs_transaction_t* transaction,
502 uint64_t size,
503 uint64_t* hash)
504{
505 uint64_t remaining = size;
506 uint64_t digest = (uint64_t)k_mdl_fnv_offset;
507 uint32_t read_calls = 0U;
508 uint32_t write_calls = 0U;
509 ra8_err_t err = k_ra8_ok;
510 while ((remaining > 0U) && (read_calls < (uint32_t)k_storage_io_calls)) {
511 const uint32_t wanted = (remaining < (uint64_t)storage->io_buffer_bytes)
512 ? (uint32_t)remaining
513 : storage->io_buffer_bytes;
514 uint32_t read = 0U;
515 err = fw_fs_read(source, storage->io_buffer, wanted, &read);
516 ++read_calls;
517 if ((err != k_ra8_ok) || (read == 0U) || ((uint64_t)read > remaining)) {
518 err = (err == k_ra8_ok) ? k_ra8_fail : err;
519 break;
520 }
521 digest = mdl_hash_bytes_seed(storage->io_buffer, read, digest);
522 err = internal_write_all(transaction, storage->io_buffer, read, &write_calls);
523 if (err != k_ra8_ok) {
524 break;
525 }
526 remaining -= read;
527 }
528 if ((err == k_ra8_ok) && (remaining != 0U)) {
530 }
531 uint32_t trailing = 0U;
532 if (err == k_ra8_ok) {
533 err = fw_fs_read(source, storage->io_buffer, 1U, &trailing);
534 }
535 if ((err == k_ra8_ok) && (trailing != 0U)) {
536 err = k_ra8_fail;
537 }
538 *hash = digest;
539 return err;
540}
541
543mdl_storage_copy_atomic(mdl_storage_t* storage, const char* source, const char* destination)
544{
545 if ((storage == nullptr) || (storage->fs == nullptr) || (source == nullptr) ||
546 (destination == nullptr)) {
548 }
549 if (strcmp(source, destination) == 0) {
551 }
552 fw_fs_file_t source_file = {};
553 fw_fs_transaction_t transaction = {};
554 uint64_t size = 0U;
555 ra8_err_t err =
556 internal_begin_copy(storage, source, destination, &source_file, &transaction, &size);
557 if (err != k_ra8_ok) {
558 return err;
559 }
560 uint64_t hash = 0U;
561 err = internal_copy_payload(storage, &source_file, &transaction, size, &hash);
562 const ra8_err_t closed = fw_fs_close(&source_file);
563 if (err == k_ra8_ok) {
564 err = closed;
565 }
566 if (err != k_ra8_ok) {
567 return internal_abort(&transaction, err);
568 }
569
570 const staged_identity_t identity = {.size_bytes = size,
571 .hash = hash,
572 .buffer = storage->io_buffer,
573 .buffer_bytes = storage->io_buffer_bytes};
574 err = fw_fs_transaction_validate(&transaction, internal_validate_stage, (void*)&identity);
575 if (err != k_ra8_ok) {
576 return internal_abort(&transaction, err);
577 }
578 bool published = false;
579 err = fw_fs_transaction_commit(&transaction, &published);
580 if ((err == k_ra8_ok) && !published) {
582 }
583 return internal_abort(&transaction, err);
584}
585
606 mdl_storage_t* storage,
607 const char* destination,
609{
610 if ((writer == nullptr) || (storage == nullptr) || (storage->fs == nullptr) ||
611 (destination == nullptr) || writer->transaction.active ||
612 ((policy != k_fw_fs_txn_create_new) && (policy != k_fw_fs_txn_replace_atomic))) {
614 }
615 fw_fs_transaction_t transaction = {};
616 const ra8_err_t err = fw_fs_transaction_begin(&storage->fs->transactions,
617 destination,
618 policy,
619 &transaction,
620 storage->transaction_workspace,
622 if (err != k_ra8_ok) {
623 return err;
624 }
625 *writer = (mdl_storage_txn_t){.storage = storage,
626 .transaction = transaction,
627 .size_bytes = 0U,
628 .hash = (uint64_t)k_mdl_fnv_offset,
629 .write_calls = 0U};
630 return k_ra8_ok;
631}
632
634mdl_storage_txn_begin(mdl_storage_txn_t* writer, mdl_storage_t* storage, const char* destination)
635{
636 if ((writer == nullptr) || (storage == nullptr) || (storage->fs == nullptr) ||
637 (destination == nullptr) || writer->transaction.active) {
639 }
641 const ra8_err_t err = internal_policy(storage, destination, &policy);
642 return (err == k_ra8_ok) ? internal_txn_begin(writer, storage, destination, policy) : err;
643}
644
646 mdl_storage_t* storage,
647 const char* destination)
648{
649 return internal_txn_begin(writer, storage, destination, k_fw_fs_txn_create_new);
650}
651
652ra8_err_t mdl_storage_txn_write(mdl_storage_txn_t* writer, const uint8_t* bytes, uint32_t length)
653{
654 if ((writer == nullptr) || (writer->storage == nullptr) || !writer->transaction.active ||
655 ((bytes == nullptr) && (length != 0U))) {
657 }
658 if ((uint64_t)length > ((uint64_t)k_mdl_hash_max_file_bytes - writer->size_bytes)) {
660 }
661 uint32_t offset = 0U;
662 while (offset < length) {
663 if (writer->write_calls >= (uint32_t)k_storage_io_calls) {
665 }
666 uint32_t written = 0U;
667 const ra8_err_t err =
668 fw_fs_transaction_write(&writer->transaction, bytes + offset, length - offset, &written);
669 ++writer->write_calls;
670 if (err != k_ra8_ok) {
671 return err;
672 }
673 if (written == 0U) {
675 }
676 writer->hash = mdl_hash_bytes_seed(bytes + offset, (size_t)written, writer->hash);
677 writer->size_bytes += (uint64_t)written;
678 offset += written;
679 }
680 return k_ra8_ok;
681}
682
684{
685 if (writer == nullptr) {
687 }
688 if (writer->transaction.active) {
689 const ra8_err_t err = fw_fs_transaction_abort(&writer->transaction);
690 if (err != k_ra8_ok) {
691 return err;
692 }
693 }
694 *writer = (mdl_storage_txn_t){};
695 return k_ra8_ok;
696}
697
699{
700 if ((writer == nullptr) || (writer->storage == nullptr) || !writer->transaction.active) {
702 }
703 const staged_identity_t identity = {.size_bytes = writer->size_bytes,
704 .hash = writer->hash,
705 .buffer = writer->storage->io_buffer,
706 .buffer_bytes = writer->storage->io_buffer_bytes};
707 ra8_err_t err =
709 if (err == k_ra8_ok) {
710 bool published = false;
711 err = fw_fs_transaction_commit(&writer->transaction, &published);
712 if ((err == k_ra8_ok) && !published) {
714 }
715 }
716 if (err != k_ra8_ok) {
717 const ra8_err_t aborted = mdl_storage_txn_abort(writer);
718 return (aborted == k_ra8_ok) ? err : aborted;
719 }
720 *writer = (mdl_storage_txn_t){};
721 return k_ra8_ok;
722}
ra8_err_t fw_fs_open(const fw_fs_stream_port_t *streams, const char *path, fw_fs_open_mode_t mode, fw_fs_file_t *file, void *workspace, uint32_t workspace_size)
Open a file into a caller-owned handle and backend workspace.
Definition fw_if_fs.c:648
ra8_err_t fw_fs_get_caps(const fw_fs_t *fs, fw_fs_caps_t *out)
Copy the immutable capability snapshot from a complete binding.
Definition fw_if_fs.c:468
ra8_err_t fw_fs_transaction_abort(fw_fs_transaction_t *transaction)
Close and remove an unpublished staging artifact.
Definition fw_if_fs.c:976
ra8_err_t fw_fs_stat(const fw_fs_namespace_t *names, const char *path, fw_fs_stat_t *out)
Query a path; a miss is success with out->exists == false.
Definition fw_if_fs.c:480
ra8_err_t fw_fs_transaction_validate(fw_fs_transaction_t *transaction, fw_fs_validate_fn_t validator, void *validator_ctx)
Flush/reopen the stage and ask validator to inspect it read-only.
Definition fw_if_fs.c:929
ra8_err_t fw_fs_read(fw_fs_file_t *file, uint8_t *dst, uint32_t cap, uint32_t *out_read)
Read up to cap bytes; zero bytes is EOF.
Definition fw_if_fs.c:699
ra8_err_t fw_fs_transaction_begin(const fw_fs_transaction_port_t *port, const char *destination, fw_fs_transaction_policy_t policy, fw_fs_transaction_t *transaction, void *workspace, uint32_t workspace_size)
Create a hidden sibling staging file for one destination.
Definition fw_if_fs.c:850
ra8_err_t fw_fs_transaction_write(fw_fs_transaction_t *transaction, const uint8_t *source, uint32_t length, uint32_t *out_written)
Append bytes to the private staging artifact.
Definition fw_if_fs.c:892
ra8_err_t fw_fs_close(fw_fs_file_t *file)
Close and consume an open handle.
Definition fw_if_fs.c:783
ra8_err_t fw_fs_transaction_commit(fw_fs_transaction_t *transaction, bool *out_published)
Publish a validated stage.
Definition fw_if_fs.c:951
ra8_err_t fw_fs_file_size(fw_fs_file_t *file, uint64_t *out_size)
Report the open file's current length.
Definition fw_if_fs.c:758
@ k_fw_fs_node_file
Regular byte stream.
@ k_fw_fs_open_read
Existing file, read-only.
fw_fs_transaction_policy_t
Destination policy for a staged transaction.
@ k_fw_fs_txn_create_new
Commit only when destination is absent.
@ k_fw_fs_txn_replace_atomic
Atomically replace an existing file.
@ k_fw_fs_cap_stream
Regular-file stream operations are available.
@ k_fw_fs_cap_namespace
Metadata and namespace operations are available.
@ k_fw_fs_cap_transactions
Staged publication operations are available.
static ra8_err_t internal_validate_stage(void *ctx, fw_fs_file_t *staged)
Dispatch structural validation for one staged artifact.
Content-identity hashing (FNV-1a 64) for the media downloader's persistent library state.
@ k_mdl_hash_max_file_bytes
Exact file hash bound.
Definition mdl_hash.h:37
@ k_mdl_fnv_offset
FNV-1a 64 offset basis.
Definition mdl_hash.h:35
ra8_err_t mdl_hash_stream(fw_fs_file_t *file, uint64_t file_size, uint8_t *buffer, uint32_t buffer_bytes, uint64_t *out)
Hash exactly one snapshotted extent from an already-open stream.
Definition mdl_hash.c:63
uint64_t mdl_hash_bytes_seed(const void *data, size_t len, uint64_t seed)
Continue an FNV-1a 64 fold over a byte range from a running state.
Definition mdl_hash.c:21
ra8_err_t mdl_storage_txn_write(mdl_storage_txn_t *writer, const uint8_t *bytes, uint32_t length)
Append one complete caller chunk, tolerating bounded short writes.
static ra8_err_t internal_abort(fw_fs_transaction_t *transaction, ra8_err_t primary)
Abort an active transaction and preserve cleanup failure visibility.
static ra8_err_t internal_copy_payload(mdl_storage_t *storage, fw_fs_file_t *source, fw_fs_transaction_t *transaction, uint64_t size, uint64_t *hash)
Copy and hash one exact source payload into a transaction.
mdl_storage_limits_t
Bounded I/O progress limits for a complete copy.
Definition mdl_storage.c:25
@ k_storage_io_calls
Short-I/O and EOF call ceiling.
Definition mdl_storage.c:26
@ k_storage_span_count
Output plus workspace span count.
Definition mdl_storage.c:27
static ra8_err_t internal_policy(const mdl_storage_t *storage, const char *destination, fw_fs_transaction_policy_t *out)
Select create-new or truthful atomic replacement policy.
static ra8_err_t internal_txn_begin(mdl_storage_txn_t *writer, mdl_storage_t *storage, const char *destination, fw_fs_transaction_policy_t policy)
Begin a streaming writer with one explicit publication policy.
static ra8_err_t internal_source_size(const mdl_storage_t *storage, const char *source, uint64_t *size)
Resolve and validate one regular bounded source file.
ra8_err_t mdl_storage_txn_begin_new(mdl_storage_txn_t *writer, mdl_storage_t *storage, const char *destination)
Begin one streamed create-new publication without replacement.
static ra8_err_t internal_validate_stage(void *ctx, fw_fs_file_t *staged)
Validate staged size and identity through its generic read handle.
static bool internal_aligned(const void *pointer, uint8_t alignment)
Return whether one pointer satisfies a backend alignment contract.
ra8_err_t mdl_storage_txn_abort(mdl_storage_txn_t *writer)
Abort and clear one streamed transaction.
ra8_err_t mdl_storage_copy_atomic(mdl_storage_t *storage, const char *source, const char *destination)
Copy a regular file through a validated atomic transaction.
static ra8_err_t internal_begin_copy(mdl_storage_t *storage, const char *source, const char *destination, fw_fs_file_t *source_file, fw_fs_transaction_t *transaction, uint64_t *size)
Open the copy source and begin its publication transaction.
ra8_err_t mdl_storage_txn_commit(mdl_storage_txn_t *writer)
Independently validate and publish a completed streamed transaction.
static ra8_err_t internal_write_all(fw_fs_transaction_t *transaction, const uint8_t *source, uint32_t length, uint32_t *calls)
Write all of one buffer while rejecting zero-progress success.
ra8_err_t mdl_storage_init(mdl_storage_t *storage, const fw_fs_t *fs, void *file_workspace, uint32_t file_workspace_bytes, void *transaction_workspace, uint32_t transaction_workspace_bytes, uint8_t *io_buffer, uint32_t io_buffer_bytes)
Validate and retain one filesystem plus caller-owned workspaces.
static ra8_err_t internal_make_span(const void *pointer, uint32_t bytes, internal_storage_span_t *out)
Convert one non-empty caller region into an address interval.
Definition mdl_storage.c:63
static ra8_err_t internal_validate_spans(mdl_storage_t *storage, void *file_workspace, uint32_t file_workspace_bytes, void *transaction_workspace, uint32_t transaction_workspace_bytes, uint8_t *io_buffer, uint32_t io_buffer_bytes)
Validate that output and operational workspaces are pairwise disjoint.
static bool internal_overlap(const internal_storage_span_t *left, const internal_storage_span_t *right)
Return whether two validated half-open intervals share a byte.
Definition mdl_storage.c:91
ra8_err_t mdl_storage_txn_begin(mdl_storage_txn_t *writer, mdl_storage_t *storage, const char *destination)
Begin one streamed create or truthful atomic replacement.
Injected portable storage resources for downloader domain code.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_fail
Generic unspecified failure.
Definition ra8_err.h:133
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
Definition ra8_err.h:429
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
@ 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 strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
Static properties and workspace requirements of one bound port.
uint32_t file_workspace_bytes
State bytes required by open.
uint8_t transaction_workspace_align
Required transaction alignment.
uint8_t file_workspace_align
Required file-state alignment.
uint32_t flags
OR of fw_fs_capability_t.
uint32_t transaction_workspace_bytes
State bytes required by begin.
Caller-owned open file; fields are private to the facade.
Result of a portable metadata query.
uint64_t size_bytes
File length; zero for a directory.
bool exists
False means a clean lookup miss.
fw_fs_node_type_t type
Kind of node at the path.
One complete composition-root filesystem binding.
fw_fs_stream_port_t streams
Byte-stream operations.
fw_fs_namespace_t names
Namespace operations.
fw_fs_transaction_port_t transactions
Staged publication.
Caller-owned transaction; fields are private to the facade.
bool active
Begin succeeded.
One overflow-checked half-open caller-storage interval.
Definition mdl_storage.c:31
uintptr_t end
One-past-last byte address.
Definition mdl_storage.c:33
uintptr_t begin
First byte address.
Definition mdl_storage.c:32
One non-reentrant downloader filesystem dependency bundle.
Definition mdl_storage.h:40
uint32_t transaction_workspace_bytes
Transaction workspace extent.
Definition mdl_storage.h:46
uint32_t file_workspace_bytes
File workspace extent.
Definition mdl_storage.h:45
void * transaction_workspace
Transaction backend state.
Definition mdl_storage.h:43
uint8_t * io_buffer
Caller-owned stream scratch.
Definition mdl_storage.h:44
const fw_fs_t * fs
Injected portable filesystem.
Definition mdl_storage.h:41
void * file_workspace
Open-file backend state.
Definition mdl_storage.h:42
uint32_t io_buffer_bytes
Stream scratch extent.
Definition mdl_storage.h:47
Caller-owned streaming publication transaction with running identity.
Definition mdl_storage.h:58
uint64_t hash
Running FNV-1a identity.
Definition mdl_storage.h:62
mdl_storage_t * storage
Exclusively borrowed storage binding.
Definition mdl_storage.h:59
fw_fs_transaction_t transaction
Active private filesystem stage.
Definition mdl_storage.h:60
uint64_t size_bytes
Exact bytes accepted into the stage.
Definition mdl_storage.h:61
uint32_t write_calls
Bounded backend write-call tally.
Definition mdl_storage.h:63
Expected staged identity retained during validation.
Definition mdl_storage.c:37
uint64_t hash
FNV identity.
Definition mdl_storage.c:39
uint32_t buffer_bytes
Scratch extent.
Definition mdl_storage.c:41
uint64_t size_bytes
Exact staged length.
Definition mdl_storage.c:38
uint8_t * buffer
Caller-owned scratch.
Definition mdl_storage.c:40