|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Implementation of the .rabook blob validator. More...
#include "book.h"#include <string.h>#include "book_internal.h"#include "ra8_attributes.h"#include "ra8_check.h"Go to the source code of this file.
Data Structures | |
| struct | book_container_view_t |
| Parsed, bounds-checked view of a resident "RBKC" container file. More... | |
Enumerations | |
| enum | book_crc_const_t : uint32_t { k_book_crc_init = 0xFFFFFFFFU , k_book_crc_poly = 0xEDB88320U } |
| Constants for the reflected CRC-32/ISO-HDLC used in the trailer. More... | |
| enum | book_crc_byte_t : uint8_t { k_book_crc_bits_per_byte = 8U } |
Functions | |
| static void | internal_copy_object (void *dst, const void *src, size_t len) |
| Copy an object representation through compatible byte-pointer types. | |
| 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. | |
| static uint32_t | internal_crc32 (const uint8_t *data, size_t len) |
| Compute CRC-32/ISO-HDLC over one resident byte span. | |
| 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. | |
| 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. | |
| static bool | internal_magic_ok (const book_header_t *hdr) |
| Whether the header's magic field equals the "RABOOK1" tag. | |
| ra8_err_t | book_validate (const void *base, size_t size) |
| Validate that a byte buffer is a well-formed, intact .rabook blob. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
Variables | |
| static const char *const | s_tag_book = "book" |
| Log tag for book validation diagnostics. | |
Implementation of the .rabook blob validator.
The only non-inline part of book is integrity/bounds validation. Walking a validated blob is pure offset arithmetic and lives entirely in the header.
Definition in file book.c.
| enum book_crc_byte_t : uint8_t |
| enum book_crc_const_t : uint32_t |
| 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.
Parses the "RBKC" container header and chunk table (see book_container_t for the layout), inflates every chunk's zlib stream in order into the caller-owned scratch buffer (expected to live in SDRAM), then runs book_validate() over the reassembled flat blob. On success *out_base is the validated blob base (equal to scratch) ready for the inline accessors. This is the resident open – the whole inflated blob must fit scratch_cap; a book larger than the resident budget is instead read chunk-by-chunk through book_chunked.h + book_src_paged().
| [in] | file | Pointer to the .rabook file bytes (non-NULL). |
| [in] | file_len | Length of file in bytes. |
| [in] | inflate | Decompressor callback (see book_inflate_fn). |
| [out] | scratch | Buffer that receives the inflated blob (non-NULL). |
| [in] | scratch_cap | Capacity of scratch; must be >= the inflated total. |
| [out] | out_base | Receives the validated blob base on success. |
| [out] | out_size | Receives the inflated blob length on success. |
| k_ra8_ok | Container valid, inflated, and blob validated. |
| k_ra8_err_null_ptr | A required pointer argument is NULL. |
| k_ra8_err_invalid_arg | Container magic / header geometry / chunk table is malformed (bad magic, zero chunk size, count disagreeing with the total, non-monotonic table, table end disagreeing with the payload length). |
| k_ra8_err_invalid_size | File too short, scratch_cap too small, or a chunk inflated to a length other than its span. |
| k_ra8_err_range_check_failed | Blob CRC mismatch (from book_validate()). |
Definition at line 543 of file book.c.
References internal_open_body(), RA8_CHECK_NULL_PTR, and s_tag_book.
| ra8_err_t book_validate | ( | const void * | base, |
| size_t | size ) |
Validate that a byte buffer is a well-formed, intact .rabook blob.
Checks, in order: the magic and format_version; that flags sets no bit outside k_book_flag_mask_known (a blob relying on a presentation semantic this firmware does not implement must be rejected, not mis-read); that total_size fits in size; that every table offset plus its extent and every pool lie within total_size; that every image descriptor names a book_image_pixfmt_t this build can unpack (an unknown depth is refused rather than mis-blitted); and finally the CRC-32 of the body. Must be called once before any accessor is used on base; the accessors assume a validated blob and do no bounds checking themselves (they are pure offset arithmetic for XIP).
| [in] | base | Pointer to the candidate blob (may be NULL). |
| [in] | size | Number of readable bytes at base. |
| k_ra8_ok | Blob is well-formed and CRC matches. |
| k_ra8_err_null_ptr | base is NULL. |
| k_ra8_err_invalid_arg | Magic is wrong, the format version is unknown, flags carries an unknown feature bit, or an image declares an unknown pixel format. |
| k_ra8_err_invalid_size | size is too small or a table/pool runs past total_size. |
| k_ra8_err_range_check_failed | CRC-32 of the body does not match the header. |
Definition at line 231 of file book.c.
References book_header_t::attr_count, book_header_t::attr_off, book_header_t::chapter_count, book_header_t::chapter_off, book_header_t::crc32_val, book_header_t::flags, book_header_t::format_version, book_header_t::image_count, book_header_t::image_off, book_header_t::image_pool_off, book_header_t::image_pool_size, internal_crc32(), internal_image_pixfmts_known(), internal_magic_ok(), internal_table_fits(), k_book_flag_mask_known, k_book_format_version, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_range_check_failed, k_ra8_ok, book_header_t::node_count, book_header_t::node_off, RA8_CHECK_NULL_PTR, s_tag_book, book_header_t::string_off, book_header_t::string_size, book_header_t::stylesheet_count, book_header_t::stylesheet_off, and book_header_t::total_size.
Referenced by erb_render_image(), imp_walk_book(), internal_compile_temp(), internal_dispatch_and_cache(), internal_open_body(), main(), and verify_blob().
|
static |
Parse + bounds-check a resident "RBKC" container against its file.
Decodes the fixed header via priv_book_container_header_fields(), verifies the header plus chunk table fit inside file_len, verifies the inflated total fits scratch_cap, then walks the chunk table once to require offset[0] == 0, strict monotonic growth, and offset[chunk_count] == payload_len (the streams exactly tile the rest of the file). On success out_view carries pointers the inflate loop can trust without further checks.
| [in] | bytes | First byte of the container file. |
| [in] | file_len | Readable length of bytes. |
| [in] | scratch_cap | Caller's inflate scratch capacity in bytes. |
| [out] | out_view | Receives the validated view. |
| k_ra8_ok | View populated; geometry fully validated. |
| k_ra8_err_invalid_arg | Bad magic / header fields / chunk-table shape. |
| k_ra8_err_invalid_size | File shorter than header + table, or the inflated total exceeds scratch_cap. |
bytes is non-NULL and points at file_len readable bytes. out_view is non-NULL and writable. out_view extent lies inside the file buffer. out_view is not fully populated and must not be used.Definition at line 383 of file book.c.
References book_container_view_t::chunk_bytes, book_container_view_t::chunk_count, k_book_container_entry_len, k_book_container_header_len, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_ok, book_container_view_t::payload, book_container_view_t::payload_len, priv_book_container_header_fields(), priv_book_container_table_entry(), RA8_INTERNAL, book_container_view_t::table, and book_container_view_t::total.
Referenced by internal_open_body().
|
static |
Copy an object representation through compatible byte-pointer types.
Centralizes the checked project's permitted bytewise object copy.
| [out] | dst | Destination spanning at least len writable bytes. |
| [in] | src | Source spanning at least len readable bytes. |
| [in] | len | Number of bytes to copy. |
dst is writable for len bytes. src is readable for len bytes and does not overlap dst. len destination bytes equal the source bytes on entry. Definition at line 38 of file book.c.
References memcpy(), and RA8_INTERNAL.
Referenced by priv_book_container_header_fields(), and priv_book_container_table_entry().
|
static |
Compute CRC-32/ISO-HDLC over one resident byte span.
Seeds the incremental implementation with zero so the result uses the same finalized wire convention as the streaming validator.
| [in] | data | Readable bytes. |
| [in] | len | Number of bytes in data. |
| UINT32_C(0) | The span's CRC happens to be zero. |
| UINT32_MAX | The span's CRC happens to have every bit set. |
data addresses len bytes when len is non-zero. Definition at line 117 of file book.c.
References priv_book_crc32_extend(), and RA8_INTERNAL.
Referenced by book_validate().
|
static |
Whether every image descriptor declares a pixel format this build knows.
Rejects a blob carrying a book_image_t::pixel_format newer than k_book_pixfmt_gray8 – the same fail-closed stance book_validate() takes on an unknown header feature bit: a depth this firmware cannot unpack must be refused, not fed to the wrong blit and mis-rendered. Every pre-field blob zero-filled the byte (== k_book_pixfmt_gray4), so this never rejects an older gray4 book. Called only after the image table's bounds are validated, so book_images() is in range for all hdr->image_count entries.
| [in] | base | Blob base already bounds-checked by the caller (non-NULL). |
| [in] | hdr | Header view of base whose image table was already validated. |
| true | Every descriptor's pixel_format is <= k_book_pixfmt_gray8. |
| false | At least one descriptor names a depth this firmware cannot decode. |
base and hdr are non-NULL and describe the same blob. Definition at line 184 of file book.c.
References book_images(), book_header_t::image_count, k_book_pixfmt_gray8, and RA8_INTERNAL.
Referenced by book_validate().
|
static |
Inflate every chunk of a validated container view into scratch.
Walks the chunk table in order; chunk i's zlib stream occupies [payload + offset[i], payload + offset[i+1]) and must inflate to exactly min(chunk_bytes, total - i * chunk_bytes) bytes, written at scratch + i * chunk_bytes. A produced-length mismatch on any chunk aborts (truncated / corrupt stream). On success scratch holds the reassembled flat blob of exactly view->total bytes.
| [in] | view | Validated view from internal_container_view(). |
| [in] | inflate | Caller decompressor (see book_inflate_fn). |
| [out] | scratch | Destination for the reassembled blob. |
| k_ra8_ok | Every chunk inflated to its exact span. |
| k_ra8_err_invalid_size | A chunk inflated to the wrong length. |
| k_ra8_err_* | The inflater's own error, returned verbatim. |
view was accepted by internal_container_view() for this scratch capacity. inflate and scratch are non-NULL (checked by the caller). scratch contents are unspecified.scratch.Definition at line 455 of file book.c.
References book_container_view_t::chunk_bytes, book_container_view_t::chunk_count, k_ra8_err_invalid_size, k_ra8_ok, book_container_view_t::payload, priv_book_container_table_entry(), RA8_INTERNAL, book_container_view_t::table, and book_container_view_t::total.
Referenced by internal_open_body().
|
static |
Whether the header's magic field equals the "RABOOK1" tag.
Compares all 8 magic bytes (7 chars + NUL) against the fixed "RABOOK1" signature. Factored out of book_validate() so that function stays within the readability-function-size / NASA Rule 4 statement budget; the check is a pure read over the caller-provided header.
| [in] | hdr | Header view of a blob whose size was already bounds-checked. |
| true | All 8 magic bytes match. |
| false | At least one magic byte differs. |
hdr is non-NULL and points at a blob of at least sizeof(header). Definition at line 219 of file book.c.
References book_header_t::magic, and RA8_INTERNAL.
Referenced by book_validate().
|
static |
Parse, inflate, validate, and publish an already-guarded open.
The argument-checked body of book_open(): builds the container view, inflates every chunk into scratch, validates the reassembled blob, and publishes the base/size outputs. Split from the entry point so the null-guard macros and the staged error chain each stay within the function-size budget.
| [in] | bytes | Container file bytes (non-NULL, caller-checked). |
| [in] | file_len | Readable length of bytes. |
| [in] | inflate | Caller decompressor (non-NULL, caller-checked). |
| [out] | scratch | Destination for the reassembled blob. |
| [in] | scratch_cap | Capacity of scratch in bytes. |
| [out] | out_base | Receives the validated blob base. |
| [out] | out_size | Receives the inflated blob length. |
| k_ra8_ok | Blob inflated, validated, and published. |
| k_ra8_err_invalid_arg | Malformed container header / chunk table. |
| k_ra8_err_invalid_size | Short file, scratch too small, or a chunk inflated to the wrong span. |
| k_ra8_err_range_check_failed | Blob CRC mismatch. |
scratch addresses at least scratch_cap writable bytes. scratch.Definition at line 517 of file book.c.
References book_validate(), internal_container_view(), internal_inflate_chunks(), k_ra8_ok, RA8_INTERNAL, and book_container_view_t::total.
Referenced by book_open().
|
static |
Implementation of internal_table_fits() – overflow-safe extent check.
Returns true when the half-open byte range [off, off + count * elem) lies entirely within a blob of total bytes. Both the start offset and the computed end are promoted to 64-bit before comparison so that no 32-bit arithmetic can wrap on adversarially crafted blob fields, even when count and elem together would overflow a 32-bit product.
| [in] | off | Byte offset of the table's first element within the blob. |
| [in] | count | Number of elements in the table. |
| [in] | elem | Size in bytes of one table element. |
| [in] | total | Total byte length of the blob (value from the header). |
| true | The range [off, off + count * elem) is within total. |
| false | The range overflows or exceeds total bytes. |
total reflects the actual allocation backing the blob pointer. elem is non-zero; passing zero causes the range to collapse to off. Definition at line 151 of file book.c.
Referenced by book_validate().
| 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.
Parse + validate the fixed 24-byte "RBKC" container header.
Definition at line 290 of file book.c.
References internal_copy_object(), k_book_cont_off_chunk_bytes, k_book_cont_off_count, k_book_cont_off_reserved, k_book_cont_off_total, k_book_container_magic_len, k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_PRIV, and s_tag_book.
Referenced by internal_chunked_open_body(), and internal_container_view().
| 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.
Decode one uint64 LE chunk-table entry from unaligned container bytes.
Definition at line 325 of file book.c.
References internal_copy_object(), k_book_container_entry_len, and RA8_PRIV.
Referenced by internal_container_view(), and internal_inflate_chunks().
| 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.
Extend a finalized CRC-32/ISO-HDLC with another byte span.
Computes a CRC-32/ISO-HDLC (reflected polynomial 0xEDB88320) over the byte array [data, data + len). The algorithm seeds the accumulator with k_book_crc_init, folds each byte through the reflected polynomial, then XORs the final value with k_book_crc_init again. The check value over "123456789" is 0xCBF43926, matching Python zlib.crc32_val.
| [in] | crc | Previous finalized CRC value; use zero for the first span. |
| [in] | data | Pointer to the byte array to checksum; must not be NULL. |
| [in] | len | Number of bytes to process; zero preserves crc. |
crc with data. | 0x00000000 | Returned for an empty first span. |
| 0xCBF43926 | Check value for the ASCII string "123456789". |
data is not NULL when len is greater than 0. len does not exceed the size of the allocation pointed to by data. data nor any external state is modified.Definition at line 86 of file book.c.
References k_book_crc_bits_per_byte, k_book_crc_init, k_book_crc_poly, and RA8_PRIV.
Referenced by internal_crc32(), and internal_validate_crc().
|
static |
Log tag for book validation diagnostics.
Definition at line 23 of file book.c.
Referenced by book_open(), book_validate(), and priv_book_container_header_fields().