ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fmt_stream_rabook.c
Go to the documentation of this file.
1
10
11#include <stddef.h>
12#include <stdint.h>
13#include <string.h>
14
15#include "book_chunked.h"
16#include "miniz.h"
17#include "ra8_attributes.h"
18#include "ra8_fmt_stream.h"
19
28
30typedef struct {
33
50static ra8_err_t internal_text(const ra8_fmt_sink_t* report, const char* text)
51{
52 return report->write(report->ctx, (const uint8_t*)text, strlen(text));
53}
54
73static ra8_err_t internal_u64(const ra8_fmt_sink_t* report, uint64_t value, uint32_t width)
74{
75 char reverse[k_report_digits];
76 char rendered[k_report_digits];
77 uint32_t count = 0U;
78 do {
79 reverse[count++] = (char)('0' + (char)(value % k_report_radix));
80 value /= k_report_radix;
81 } while (value != 0U);
82 while (width > count) {
83 const ra8_err_t rc = internal_text(report, " ");
84 if (rc != k_ra8_ok) {
85 return rc;
86 }
87 --width;
88 }
89 for (uint32_t i = 0U; i < count; ++i) {
90 rendered[i] = reverse[count - i - 1U];
91 }
92 return report->write(report->ctx, (const uint8_t*)rendered, count);
93}
94
112static ra8_err_t internal_field(const ra8_fmt_sink_t* report, const char* label, uint64_t value)
113{
114 ra8_err_t rc = internal_text(report, label);
115 if (rc == k_ra8_ok) {
116 rc = internal_u64(report, value, 0U);
117 }
118 return (rc == k_ra8_ok) ? internal_text(report, "\n") : rc;
119}
120
140static ra8_err_t internal_exact_read(void* opaque, uint64_t offset, uint8_t* bytes, uint32_t len)
141{
142 source_adapter_t* adapter = (source_adapter_t*)opaque;
143 if ((adapter == nullptr) || (adapter->source == nullptr) || ((bytes == nullptr) && (len != 0U))) {
144 return k_ra8_err_null_ptr;
145 }
146 const ra8_fmt_source_t* source = adapter->source;
147 if ((offset > source->size) || ((uint64_t)len > (source->size - offset))) {
149 }
150 size_t done = 0U;
151 while (done < (size_t)len) {
152 size_t got = 0U;
153 const size_t ask = (size_t)len - done;
154 const ra8_err_t rc = source->read_at(source->ctx, offset + done, &bytes[done], ask, &got);
155 if (rc != k_ra8_ok) {
156 return rc;
157 }
158 if ((got == 0U) || (got > ask)) {
160 }
161 done += got;
162 }
163 return k_ra8_ok;
164}
165
185static ra8_err_t
186internal_inflate(const void* src, size_t src_len, void* dst, size_t dst_cap, size_t* out_len)
187{
188 if ((src == nullptr) || (dst == nullptr) || (out_len == nullptr)) {
189 return k_ra8_err_null_ptr;
190 }
191 const size_t result = tinfl_decompress_mem_to_mem(
192 dst,
193 dst_cap,
194 src,
195 src_len,
196 (int)(TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF));
197 if (result == TINFL_DECOMPRESS_MEM_TO_MEM_FAILED) {
199 }
200 *out_len = result;
201 return k_ra8_ok;
202}
203
223 const ra8_fmt_source_t* source,
224 const book_chunked_t* reader)
225{
226 ra8_err_t rc = internal_text(report, "RBKC rabook container: ");
227 if (rc == k_ra8_ok) {
228 rc = internal_u64(report, source->size, 0U);
229 }
230 if (rc == k_ra8_ok) {
231 rc = internal_text(report, " bytes\n");
232 }
233 if (rc == k_ra8_ok) {
234 rc = internal_field(report, " chunk_bytes : ", reader->chunk_bytes);
235 }
236 if (rc == k_ra8_ok) {
237 rc = internal_field(report, " inflated_total : ", reader->inflated_total);
238 }
239 if (rc == k_ra8_ok) {
240 rc = internal_field(report, " chunk_count : ", reader->chunk_count);
241 }
242 return (rc == k_ra8_ok) ? internal_field(report, " reserved : ", 0U) : rc;
243}
244
264static ra8_err_t
265internal_row(const ra8_fmt_sink_t* report, uint32_t idx, uint64_t begin, uint64_t end)
266{
267 ra8_err_t rc = internal_text(report, " ");
268 if (rc == k_ra8_ok) {
269 rc = internal_u64(report, idx, k_report_idx_width);
270 }
271 if (rc == k_ra8_ok) {
272 rc = internal_u64(report, begin, k_report_num_width + 1U);
273 }
274 if (rc == k_ra8_ok) {
275 rc = internal_u64(report, end, k_report_num_width + 1U);
276 }
277 if (rc == k_ra8_ok) {
278 rc = internal_u64(report, end - begin, k_report_num_width + 1U);
279 }
280 return (rc == k_ra8_ok) ? internal_text(report, "\n") : rc;
281}
282
300static ra8_err_t
301internal_table(const ra8_fmt_sink_t* report, const book_chunked_t* reader, bool verbose)
302{
303 if (!verbose) {
304 return k_ra8_ok;
305 }
306 ra8_err_t rc = internal_text(report, " entry start end length\n");
307 uint32_t rows = reader->chunk_count;
308 if (rows > k_report_rows) {
309 rows = k_report_rows;
310 }
311 for (uint32_t i = 0U; (i < rows) && (rc == k_ra8_ok); ++i) {
312 const uint64_t begin = reader->payload_off + reader->table[i];
313 const uint64_t end = reader->payload_off + reader->table[i + 1U];
314 rc = internal_row(report, i, begin, end);
315 }
316 return rc;
317}
318
339 const ra8_fmt_source_t* source,
340 const book_chunked_t* reader,
341 bool verbose)
342{
343 ra8_err_t rc = internal_header(report, source, reader);
344 if (rc == k_ra8_ok) {
345 rc = internal_table(report, reader, verbose);
346 }
347 return (rc == k_ra8_ok)
348 ? internal_text(report, "verdict: VALID (chunk table monotonic and complete)\n")
349 : rc;
350}
351
353 bool verbose,
355 const ra8_fmt_sink_t* report)
356{
357 if ((source == nullptr) || (source->read_at == nullptr) || (workspace == nullptr) ||
358 (workspace->table == nullptr) || (workspace->compressed == nullptr) ||
359 (workspace->chunk == nullptr) || (workspace->scratch == nullptr) || (report == nullptr) ||
360 (report->write == nullptr)) {
361 return k_ra8_err_null_ptr;
362 }
363 source_adapter_t adapter = {.source = source};
364 book_chunked_t reader = {};
365 ra8_err_t rc = book_chunked_open(&reader,
367 &adapter,
368 source->size,
370 workspace->table,
371 workspace->table_cap,
372 workspace->compressed,
373 workspace->compressed_cap);
374 book_header_t header = {};
375 if (rc == k_ra8_ok) {
376 rc = book_chunked_validate_strict(&reader,
377 workspace->chunk,
378 workspace->chunk_cap,
379 workspace->scratch,
380 workspace->scratch_cap,
381 &header);
382 }
383 if ((rc == k_ra8_ok) && (source->validate != nullptr)) {
384 rc = source->validate(source->ctx, source->size);
385 }
386 if (rc != k_ra8_ok) {
387 (void)internal_text(report, "verdict: INVALID (strict RBKC/RABOOK1 validation failed)\n");
388 return rc;
389 }
390 return internal_report(report, source, &reader, verbose);
391}
Demand-paged chunk reader for the "RBKC" .rabook container.
ra8_err_t book_chunked_validate_strict(book_chunked_t *rd, uint8_t *chunk, uint32_t chunk_cap, uint8_t *scratch, uint32_t scratch_cap, book_header_t *out_header)
Strictly validate the complete flat blob behind an open RBKC reader.
ra8_err_t book_chunked_open(book_chunked_t *rd, ra8_vsource_read_fn file_read, void *file_ctx, uint64_t file_len, book_inflate_fn inflate, uint64_t *table_buf, uint32_t table_cap_entries, uint8_t *staging, uint32_t staging_cap)
Open a chunked .rabook container for demand-paged chunk reads.
static ra8_err_t internal_inflate(const void *source, size_t source_bytes, void *destination, size_t destination_capacity, size_t *output_bytes)
Inflate one zlib-wrapped RBKC chunk without heap allocation.
Definition main.c:405
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ 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_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
Caller-workspace I/O contracts for portable format-tool engines.
static ra8_err_t internal_report(const ra8_fmt_sink_t *report, const ra8_fmt_source_t *source, const book_chunked_t *reader, bool verbose)
Emit a validated header, optional inventory, and stable verdict.
static ra8_err_t internal_inflate(const void *src, size_t src_len, void *dst, size_t dst_cap, size_t *out_len)
Inflate one RFC 1950 stream through miniz caller storage.
ra8_err_t ra8_fmt_rabook_inspect_stream(const ra8_fmt_source_t *source, bool verbose, ra8_fmt_rabook_inspect_workspace_t *workspace, const ra8_fmt_sink_t *report)
Strictly inspect one streamed RBKC container and its RABOOK1 payload.
static ra8_err_t internal_table(const ra8_fmt_sink_t *report, const book_chunked_t *reader, bool verbose)
Emit the bounded chunk inventory when verbose output is enabled.
static ra8_err_t internal_header(const ra8_fmt_sink_t *report, const ra8_fmt_source_t *source, const book_chunked_t *reader)
Emit the established RBKC header block.
static ra8_err_t internal_row(const ra8_fmt_sink_t *report, uint32_t idx, uint64_t begin, uint64_t end)
Emit one established-width chunk inventory row.
static ra8_err_t internal_u64(const ra8_fmt_sink_t *report, uint64_t value, uint32_t width)
Render one unsigned value with optional left padding.
static ra8_err_t internal_field(const ra8_fmt_sink_t *report, const char *label, uint64_t value)
Emit a labelled unsigned field and its terminating newline.
report_constant_t
Bounded report formatting constants.
@ k_report_digits
Digits required for uint64_t.
@ k_report_num_width
Legacy byte-column width.
@ k_report_idx_width
Legacy entry-column width.
@ k_report_rows
Maximum verbose inventory rows.
@ k_report_radix
Decimal digit radix.
static ra8_err_t internal_exact_read(void *opaque, uint64_t offset, uint8_t *bytes, uint32_t len)
Adapt legal short positioned reads to one exact book read.
static ra8_err_t internal_text(const ra8_fmt_sink_t *report, const char *text)
Append one NUL-terminated literal to the report sink.
size_t strlen(const char *s)
Calculate string length.
One open chunked .rabook file: parsed geometry + caller storage.
uint64_t inflated_total
Served flat-blob length.
const uint64_t * table
Chunk offsets.
uint32_t chunk_count
Chunk count.
uint32_t chunk_bytes
Inflated bytes per chunk.
uint64_t payload_off
First stream file offset.
Fixed 100-byte prologue describing every table and pool in the blob.
Definition book.h:246
Caller-owned storage for strict streamed RBKC/RABOOK1 inspection.
uint8_t * compressed
One compressed chunk.
uint32_t compressed_cap
Compressed chunk capacity.
uint64_t * table
Decoded RBKC offset entries.
uint32_t table_cap
Entries available at table.
uint8_t * scratch
Strict validator workspace.
uint8_t * chunk
One inflated chunk.
uint32_t chunk_cap
Inflated chunk capacity.
uint32_t scratch_cap
Validator workspace capacity.
Injected append-only sink.
Immutable, randomly readable input object.
uint64_t size
Exact object byte length.
void * ctx
Backend-owned context.
ra8_fmt_source_validate_fn validate
Optional stability callback.
jof_pread_fn read_at
Positioned-read callback.
Positioned-source binding for the exact book-reader callback.
const ra8_fmt_source_t * source
Borrowed immutable source.