ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
book.c
Go to the documentation of this file.
1
14#include "book.h"
15
16#include <string.h>
17
18#include "book_internal.h"
19#include "ra8_attributes.h"
20#include "ra8_check.h"
21
23static const char* const s_tag_book = "book";
24
38RA8_INTERNAL static void internal_copy_object(void* dst, const void* src, size_t len)
39{
40 (void)memcpy(dst, src, len);
41}
42
50typedef enum : uint32_t {
51 k_book_crc_init = 0xFFFFFFFFU,
52 k_book_crc_poly = 0xEDB88320U,
54
55typedef enum : uint8_t {
58
86RA8_PRIV uint32_t priv_book_crc32_extend(uint32_t crc, const uint8_t* data, size_t len)
87{
88 uint32_t state = crc ^ k_book_crc_init;
89 for (size_t i = 0U; i < len; ++i) {
90 state ^= (uint32_t)data[i];
91 for (uint8_t bit = 0U; bit < k_book_crc_bits_per_byte; ++bit) {
92 const uint32_t mask = ((state & 1U) != 0U) ? k_book_crc_init : 0U;
93 state = (state >> 1U) ^ (k_book_crc_poly & mask);
94 }
95 }
96 return state ^ k_book_crc_init;
97}
98
117RA8_INTERNAL static uint32_t internal_crc32(const uint8_t* data, size_t len)
118{
119 return priv_book_crc32_extend(0U, data, len);
120}
121
150RA8_INTERNAL static bool
151internal_table_fits(uint32_t off, uint32_t count, uint32_t elem, uint32_t total)
152{
153 uint64_t end = (uint64_t)off + ((uint64_t)count * (uint64_t)elem);
154 return (off <= total) && (end <= (uint64_t)total);
155}
156
184RA8_INTERNAL static bool internal_image_pixfmts_known(const void* base, const book_header_t* hdr)
185{
186 const book_image_t* imgs = book_images(base);
187 bool known = true;
188 for (uint32_t i = 0U; i < hdr->image_count; ++i) { /* bound: validated image_count */
189 if (imgs[i].pixel_format > (uint8_t)k_book_pixfmt_gray8) {
190 known = false;
191 }
192 }
193 return known;
194}
195
220{
221 const char expect[8] = {'R', 'A', 'B', 'O', 'O', 'K', '1', '\0'};
222 bool ok = true;
223 for (uint8_t i = 0U; i < (uint8_t)sizeof(expect); ++i) {
224 if (hdr->magic[i] != expect[i]) {
225 ok = false;
226 }
227 }
228 return ok;
229}
230
231ra8_err_t book_validate(const void* base, size_t size)
232{
233 RA8_CHECK_NULL_PTR(base, s_tag_book, "validate: null base");
234
235 if (size < sizeof(book_header_t)) {
237 }
238
239 const book_header_t* hdr = (const book_header_t*)base;
240
241 if (!internal_magic_ok(hdr)) {
243 }
246 }
247 /* Unknown feature bits mean the blob relies on a presentation semantic this
248 * firmware does not implement (e.g. a reading-order mode newer than
249 * book_flag_t) -- refuse it rather than silently mis-render it. */
250 if ((hdr->flags & ~(uint32_t)k_book_flag_mask_known) != 0U) {
252 }
253
254 uint32_t total = hdr->total_size;
255 if ((total < sizeof(book_header_t)) || ((size_t)total > size)) {
257 }
258
259 const bool tables_ok =
260 internal_table_fits(hdr->chapter_off, hdr->chapter_count, sizeof(book_chapter_t), total) &&
261 internal_table_fits(hdr->node_off, hdr->node_count, sizeof(book_node_t), total) &&
262 internal_table_fits(hdr->attr_off, hdr->attr_count, sizeof(book_attr_t), total) &&
264 hdr->stylesheet_count,
265 sizeof(book_stylesheet_t),
266 total) &&
267 internal_table_fits(hdr->image_off, hdr->image_count, sizeof(book_image_t), total) &&
268 internal_table_fits(hdr->string_off, hdr->string_size, 1U, total) &&
270 if (!tables_ok) {
272 }
273
274 /* Every image descriptor must name a pixel depth this build can unpack; an
275 * unknown depth is refused (fail-closed) rather than fed to the wrong blit. */
276 if (!internal_image_pixfmts_known(base, hdr)) {
278 }
279
280 const uint8_t* body = &((const uint8_t*)base)[sizeof(book_header_t)];
281 uint32_t body_len = total - (uint32_t)sizeof(book_header_t);
282 if (internal_crc32(body, body_len) != hdr->crc32_val) {
284 }
285
286 return k_ra8_ok;
287}
288
291 uint32_t* out_chunk_bytes,
292 uint64_t* out_total,
293 uint32_t* out_count)
294{
295 RA8_CHECK_NULL_PTR(hdr, s_tag_book, "hdr fields: null hdr");
296 RA8_CHECK_NULL_PTR(out_chunk_bytes, s_tag_book, "hdr fields: null out");
297 const char cmagic[k_book_container_magic_len] = {'R', 'B', 'K', 'C'};
298 for (uint8_t i = 0U; i < k_book_container_magic_len; ++i) {
299 if ((char)hdr[i] != cmagic[i]) {
301 }
302 }
303 uint32_t chunk_bytes = 0U;
304 uint64_t total = 0U;
305 uint32_t count = 0U;
306 uint32_t reserved = 0U;
307 internal_copy_object(&chunk_bytes, &hdr[k_book_cont_off_chunk_bytes], sizeof(chunk_bytes));
308 internal_copy_object(&total, &hdr[k_book_cont_off_total], sizeof(total));
309 internal_copy_object(&count, &hdr[k_book_cont_off_count], sizeof(count));
310 internal_copy_object(&reserved, &hdr[k_book_cont_off_reserved], sizeof(reserved));
311 if ((chunk_bytes == 0U) || (total == 0U) || (reserved != 0U)) {
313 }
314 const uint64_t want_count = (total + (uint64_t)chunk_bytes - 1U) / (uint64_t)chunk_bytes;
315 if ((uint64_t)count != want_count) {
317 }
318 *out_chunk_bytes = chunk_bytes;
319 *out_total = total;
320 *out_count = count;
321 return k_ra8_ok;
322}
323
325RA8_PRIV uint64_t priv_book_container_table_entry(const uint8_t* table, uint32_t idx)
326{
327 uint64_t entry = 0U;
328 internal_copy_object(&entry, &table[(size_t)idx * k_book_container_entry_len], sizeof(entry));
329 return entry;
330}
331
342typedef struct {
343 const uint8_t* table;
344 const uint8_t* payload;
345 uint64_t total;
346 uint64_t payload_len;
347 uint32_t chunk_bytes;
348 uint32_t chunk_count;
350
384 size_t file_len,
385 size_t scratch_cap,
386 book_container_view_t* out_view)
387{
388 if (file_len < k_book_container_header_len) {
390 }
392 &out_view->chunk_bytes,
393 &out_view->total,
394 &out_view->chunk_count);
395 if (err != k_ra8_ok) {
396 return err;
397 }
398 const uint64_t entries = (uint64_t)out_view->chunk_count + 1U;
399 const uint64_t table_bytes = entries * k_book_container_entry_len;
400 if ((uint64_t)file_len < ((uint64_t)k_book_container_header_len + table_bytes)) {
402 }
403 if ((uint64_t)scratch_cap < out_view->total) {
405 }
406 out_view->table = &bytes[k_book_container_header_len];
407 out_view->payload = &out_view->table[table_bytes];
408 out_view->payload_len = (uint64_t)file_len - k_book_container_header_len - table_bytes;
409 uint64_t prev = priv_book_container_table_entry(out_view->table, 0U);
410 if (prev != 0U) {
412 }
413 for (uint32_t i = 1U; i <= out_view->chunk_count; ++i) { /* bound: validated chunk_count */
414 const uint64_t cur = priv_book_container_table_entry(out_view->table, i);
415 if (cur <= prev) {
417 }
418 prev = cur;
419 }
420 if (prev != out_view->payload_len) {
422 }
423 return k_ra8_ok;
424}
425
456 book_inflate_fn inflate,
457 uint8_t* scratch)
458{
459 for (uint32_t i = 0U; i < view->chunk_count; ++i) { /* bound: validated chunk_count */
460 const uint64_t off = priv_book_container_table_entry(view->table, i);
461 const uint64_t next = priv_book_container_table_entry(view->table, i + 1U);
462 const uint64_t dst_off = (uint64_t)i * view->chunk_bytes;
463 uint64_t expected = view->total - dst_off;
464 if (expected > (uint64_t)view->chunk_bytes) {
465 expected = view->chunk_bytes;
466 }
467 size_t produced = 0U;
468 const ra8_err_t err = inflate(&view->payload[(size_t)off],
469 (size_t)(next - off),
470 &scratch[(size_t)dst_off],
471 (size_t)expected,
472 &produced);
473 if (err != k_ra8_ok) {
474 return err;
475 }
476 if (produced != (size_t)expected) {
478 }
479 }
480 return k_ra8_ok;
481}
482
517RA8_INTERNAL static ra8_err_t internal_open_body(const uint8_t* bytes,
518 size_t file_len,
519 book_inflate_fn inflate,
520 void* scratch,
521 size_t scratch_cap,
522 const void** out_base,
523 size_t* out_size)
524{
525 book_container_view_t view = {};
526 ra8_err_t err = internal_container_view(bytes, file_len, scratch_cap, &view);
527 if (err != k_ra8_ok) {
528 return err;
529 }
530 err = internal_inflate_chunks(&view, inflate, (uint8_t*)scratch);
531 if (err != k_ra8_ok) {
532 return err;
533 }
534 err = book_validate(scratch, (size_t)view.total);
535 if (err != k_ra8_ok) {
536 return err;
537 }
538 *out_base = scratch;
539 *out_size = (size_t)view.total;
540 return k_ra8_ok;
541}
542
543ra8_err_t book_open(const void* file,
544 size_t file_len,
545 book_inflate_fn inflate,
546 void* scratch,
547 size_t scratch_cap,
548 const void** out_base,
549 size_t* out_size)
550{
551 RA8_CHECK_NULL_PTR(file, s_tag_book, "open: null file");
552 RA8_CHECK_NULL_PTR(inflate, s_tag_book, "open: null inflate");
553 RA8_CHECK_NULL_PTR(scratch, s_tag_book, "open: null scratch");
554 RA8_CHECK_NULL_PTR(out_base, s_tag_book, "open: null out_base");
555 RA8_CHECK_NULL_PTR(out_size, s_tag_book, "open: null out_size");
556
557 return internal_open_body((const uint8_t*)file,
558 file_len,
559 inflate,
560 scratch,
561 scratch_cap,
562 out_base,
563 out_size);
564}
static bool internal_image_pixfmts_known(const void *base, const book_header_t *hdr)
Whether every image descriptor declares a pixel format this build knows.
Definition book.c:184
static ra8_err_t internal_container_view(const uint8_t *bytes, size_t file_len, size_t scratch_cap, book_container_view_t *out_view)
Parse + bounds-check a resident "RBKC" container against its file.
Definition book.c:383
book_crc_byte_t
Definition book.c:55
@ k_book_crc_bits_per_byte
Reflected updates per input byte.
Definition book.c:56
static bool internal_magic_ok(const book_header_t *hdr)
Whether the header's magic field equals the "RABOOK1" tag.
Definition book.c:219
book_crc_const_t
Constants for the reflected CRC-32/ISO-HDLC used in the trailer.
Definition book.c:50
@ k_book_crc_init
CRC seed and final XOR mask.
Definition book.c:51
@ k_book_crc_poly
Reflected polynomial.
Definition book.c:52
static const char *const s_tag_book
Log tag for book validation diagnostics.
Definition book.c:23
static ra8_err_t internal_open_body(const uint8_t *bytes, size_t file_len, book_inflate_fn inflate, void *scratch, size_t scratch_cap, const void **out_base, size_t *out_size)
Parse, inflate, validate, and publish an already-guarded open.
Definition book.c:517
static uint32_t internal_crc32(const uint8_t *data, size_t len)
Compute CRC-32/ISO-HDLC over one resident byte span.
Definition book.c:117
uint64_t priv_book_container_table_entry(const uint8_t *table, uint32_t idx)
Implementation of priv_book_container_table_entry() – unaligned-safe memcpy load.
Definition book.c:325
uint32_t priv_book_crc32_extend(uint32_t crc, const uint8_t *data, size_t len)
Extend a reflected CRC-32 over one byte span.
Definition book.c:86
static bool internal_table_fits(uint32_t off, uint32_t count, uint32_t elem, uint32_t total)
Implementation of internal_table_fits() – overflow-safe extent check.
Definition book.c:151
static ra8_err_t internal_inflate_chunks(const book_container_view_t *view, book_inflate_fn inflate, uint8_t *scratch)
Inflate every chunk of a validated container view into scratch.
Definition book.c:455
ra8_err_t book_validate(const void *base, size_t size)
Validate that a byte buffer is a well-formed, intact .rabook blob.
Definition book.c:231
ra8_err_t priv_book_container_header_fields(const uint8_t *hdr, uint32_t *out_chunk_bytes, uint64_t *out_total, uint32_t *out_count)
Implementation of priv_book_container_header_fields() – memcpy field decode.
Definition book.c:290
static void internal_copy_object(void *dst, const void *src, size_t len)
Copy an object representation through compatible byte-pointer types.
Definition book.c:38
ra8_err_t book_open(const void *file, size_t file_len, book_inflate_fn inflate, void *scratch, size_t scratch_cap, const void **out_base, size_t *out_size)
Open a .rabook file: check the container, inflate, validate the blob.
Definition book.c:543
Flat, execute-in-place container for a build-time "compiled" e-book.
static const book_image_t * book_images(const void *base)
Base of the image table.
Definition book.h:518
@ k_book_format_version
Current .rabook layout revision.
Definition book.h:86
@ k_book_flag_mask_known
Every bit this firmware understands; a set bit outside this mask fails book_validate().
Definition book.h:151
@ k_book_pixfmt_gray8
8bpp grayscale, 1px/byte (lossless against any grey panel).
Definition book.h:215
@ k_book_container_header_len
Fixed header bytes ahead of the chunk table.
Definition book.h:115
@ k_book_container_entry_len
One chunk-table entry (uint64 LE offset).
Definition book.h:116
@ k_book_container_magic_len
Length of the "RBKC" magic.
Definition book.h:114
ra8_err_t(* book_inflate_fn)(const void *src, size_t src_len, void *dst, size_t dst_cap, size_t *out_len)
Caller-supplied DEFLATE inflater used by book_open().
Definition book.h:656
book DOM-walk helpers shared across the library's translation units.
@ k_book_cont_off_total
uint64 LE: flat-blob inflated total.
@ k_book_cont_off_count
uint32 LE: number of chunks.
@ k_book_cont_off_chunk_bytes
uint32 LE: inflated bytes per chunk.
@ k_book_cont_off_reserved
uint32 LE: reserved, must be 0.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_NO_RECURSION
NASA Power-of-10 Rule 1: no direct or indirect self-call.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_range_check_failed
Value outside range enforced by RA8_CHECK_RANGE / RA8_CHECK_RANGE_TAG.
Definition ra8_err.h:471
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ 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
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
One name="value" attribute on an element.
Definition book.h:317
One spine document (a renderable chapter) plus its TOC label.
Definition book.h:280
Parsed, bounds-checked view of a resident "RBKC" container file.
Definition book.c:342
uint64_t payload_len
Concatenated stream bytes in the file.
Definition book.c:346
uint32_t chunk_bytes
Inflated bytes per chunk (last short).
Definition book.c:347
const uint8_t * table
First chunk-table byte (unaligned).
Definition book.c:343
uint64_t total
Flat-blob inflated total in bytes.
Definition book.c:345
const uint8_t * payload
First byte of the chunk zlib streams.
Definition book.c:344
uint32_t chunk_count
Number of chunks.
Definition book.c:348
Fixed 100-byte prologue describing every table and pool in the blob.
Definition book.h:246
uint32_t format_version
book_version_t of this blob.
Definition book.h:248
uint32_t crc32_val
CRC-32/ISO-HDLC of the body (all bytes after this header).
Definition book.h:270
uint32_t image_off
Offset to the image table.
Definition book.h:265
uint32_t image_pool_size
Image-pool length in bytes.
Definition book.h:269
uint32_t attr_count
Number of attribute records.
Definition book.h:260
uint32_t node_count
Number of DOM nodes.
Definition book.h:258
uint32_t chapter_count
Number of spine chapters.
Definition book.h:256
uint32_t image_count
Number of image descriptors.
Definition book.h:264
uint32_t string_off
Offset to the string pool.
Definition book.h:266
uint32_t attr_off
Offset to the attribute table.
Definition book.h:261
uint32_t node_off
Offset to the node table.
Definition book.h:259
uint32_t string_size
String-pool length in bytes.
Definition book.h:267
uint32_t flags
book_flag_t bits; unknown bits are rejected.
Definition book.h:250
uint32_t stylesheet_off
Offset to the stylesheet table.
Definition book.h:263
char magic[8]
Always "RABOOK1" (7 chars + NUL).
Definition book.h:247
uint32_t chapter_off
Offset to the chapter table.
Definition book.h:257
uint32_t stylesheet_count
Number of preserved stylesheets.
Definition book.h:262
uint32_t image_pool_off
Offset to the image pool.
Definition book.h:268
uint32_t total_size
Total blob length in bytes.
Definition book.h:249
Descriptor for one transcoded image in the image pool.
Definition book.h:354
One DOM node.
Definition book.h:299
A preserved CSS stylesheet and the chapter it scopes to.
Definition book.h:332