ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
comic_wrapped.c
Go to the documentation of this file.
1
28#include <stddef.h>
29#include <stdint.h>
30#include <string.h>
31
32#include "comic.h"
33#include "comic_internal.h"
34#include "ra8_attributes.h"
35#include "ra8_check.h"
36#include "unarch_gzip.h"
37#include "unarch_io.h"
38#include "unarch_xz.h"
39
48typedef enum : uint16_t {
49 k_wrap_hdr_bytes = (uint16_t)((sizeof(unarch_mem_t) + ((size_t)k_comic_wrap_align - 1U)) &
50 ~((size_t)k_comic_wrap_align - 1U)),
53
80 void* ctx,
81 uint64_t size,
82 bool is_gzip,
83 uint8_t* payload,
84 size_t payload_cap,
85 void* xz_scratch,
86 uint32_t xz_scratch_len,
87 size_t* out_len)
88{
89 if (is_gzip) {
90 return unarch_gzip_unwrap(read, ctx, size, payload, payload_cap, nullptr, out_len);
91 }
92 return unarch_xz_unwrap(read,
93 ctx,
94 size,
95 payload,
96 payload_cap,
97 xz_scratch,
98 xz_scratch_len,
99 nullptr,
100 out_len);
101}
102
119RA8_INTERNAL static bool internal_arena_valid(uint8_t* arena, size_t arena_cap)
120{
121 uintptr_t arena_address = 0U;
122 static_assert(sizeof(arena_address) == sizeof(arena),
123 "uintptr_t must preserve pointer representation");
124 (void)memcpy((void*)&arena_address, (const void*)&arena, sizeof(arena_address));
125 return ((arena_address % (uintptr_t)k_comic_wrap_align) == 0U) &&
126 (arena_cap > (size_t)k_wrap_hdr_bytes);
127}
128
154 uint8_t* payload,
155 size_t inner_len,
156 comic_page_t* pages,
157 uint32_t page_cap,
158 char* names,
159 uint32_t names_cap,
160 uint8_t* arena)
161{
162 /* Nesting bomb: a wrapper inside the wrapper is rejected before any inner
163 * decode -- the one reachable depth bound in this pipeline. Both probes are
164 * read into locals rather than tested in place, and the whole helper has a
165 * single exit. */
166 const bool inner_gzip = unarch_gzip_magic(payload, inner_len);
167 const bool inner_xz = unarch_xz_magic(payload, inner_len);
169 if (!inner_gzip) {
170 if (!inner_xz) {
171 /* The flat-memory descriptor lives at the arena start so it out-lives
172 * this call: page extraction keeps reading through it. */
173 void* const header_slot = arena;
174 unarch_mem_t* const memory = (unarch_mem_t*)header_slot;
175 memory->base = payload;
176 memory->len = inner_len;
177 err = comic_open(c,
179 memory,
180 (uint64_t)inner_len,
181 pages,
182 page_cap,
183 names,
184 names_cap);
185 }
186 }
187 return err;
188}
189
191 comic_read_fn read,
192 void* ctx,
193 uint64_t size,
194 comic_page_t* pages,
195 uint32_t page_cap,
196 char* names,
197 uint32_t names_cap,
198 uint8_t* arena,
199 size_t arena_cap,
200 void* xz_scratch,
201 uint32_t xz_scratch_len)
202{
204 static const char* const s_tag_wrap = "comic_wrap";
205 RA8_CHECK_NULL_PTR(c, s_tag_wrap, "wrapped open: null c");
206 RA8_CHECK_NULL_PTR(read, s_tag_wrap, "wrapped open: null read");
207 RA8_CHECK_NULL_PTR(arena, s_tag_wrap, "wrapped open: null arena");
208 if (size == 0U) {
210 }
211 uint8_t sig[k_comic_magic_len] = {};
212 const size_t got = read(ctx, 0U, sig, sizeof(sig));
213 const bool is_gzip = unarch_gzip_magic(sig, got);
214 const bool is_xz = unarch_xz_magic(sig, got);
215 if (!is_gzip && !is_xz) {
216 /* Not a wrapper: the ordinary container detect owns it. */
217 return comic_open(c, read, ctx, size, pages, page_cap, names, names_cap);
218 }
219 if (!internal_arena_valid(arena, arena_cap)) {
221 }
222 uint8_t* payload = &arena[k_wrap_hdr_bytes];
223 const size_t payload_cap = arena_cap - (size_t)k_wrap_hdr_bytes;
224 size_t inner_len = 0U;
225 const ra8_err_t uerr = internal_unwrap(read,
226 ctx,
227 size,
228 is_gzip,
229 payload,
230 payload_cap,
231 xz_scratch,
232 xz_scratch_len,
233 &inner_len);
234 if (uerr != k_ra8_ok) {
235 return uerr;
236 }
237 return internal_open_unwrapped(c, payload, inner_len, pages, page_cap, names, names_cap, arena);
238}
Unified demand-paged reader for comic-book archives – CBZ (ZIP) and CBR (RAR).
@ k_comic_wrap_align
Required unwrap-arena alignment, bytes.
Definition comic.h:400
size_t(* comic_read_fn)(void *ctx, uint64_t offset, void *buf, size_t len)
Seek+read backing over the comic-archive bytes.
Definition comic.h:95
ra8_err_t comic_open(comic_t *c, comic_read_fn read, void *ctx, uint64_t size, comic_page_t *pages, uint32_t page_cap, char *names, uint32_t names_cap)
Open a comic archive (CBZ or CBR) and build its sorted page index.
Definition comic.c:390
@ k_comic_magic_len
Bytes read to detect the container magic.
Definition comic.h:117
Cross-TU seams between the comic facade and its CBZ / CBR backends.
static ra8_err_t internal_unwrap(comic_read_fn read, void *ctx, uint64_t size, bool is_gzip, uint8_t *payload, size_t payload_cap, void *xz_scratch, uint32_t xz_scratch_len, size_t *out_len)
Decode the gzip / XZ wrapper into the arena's payload region.
ra8_err_t comic_open_wrapped(comic_t *c, comic_read_fn read, void *ctx, uint64_t size, comic_page_t *pages, uint32_t page_cap, char *names, uint32_t names_cap, uint8_t *arena, size_t arena_cap, void *xz_scratch, uint32_t xz_scratch_len)
Open a comic that may be gzip- or XZ-wrapped (.cbt.gz, .tar.xz).
static bool internal_arena_valid(uint8_t *arena, size_t arena_cap)
Check wrapper-arena alignment and payload capacity.
wrap_dims_t
Arena layout constants for the wrapped open.
@ k_wrap_hdr_bytes
Descriptor slot at the arena start (aligned sizeof).
static ra8_err_t internal_open_unwrapped(comic_t *c, uint8_t *payload, size_t inner_len, comic_page_t *pages, uint32_t page_cap, char *names, uint32_t names_cap, uint8_t *arena)
Reject nested wrappers and open the decoded inner comic.
Annotation-attribute framework macros for ra8-firmware.
#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_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_decomp_depth
Container nesting-depth cap breached (ra8_decomp_limits_t).
Definition ra8_err.h:520
@ 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 entry in the resident, sorted page index.
Definition comic.h:140
One open comic archive: backing, kind, page index, and backend state.
Definition comic.h:179
Bounded flat-memory backing for unarch_read_fn.
Definition unarch_io.h:79
const uint8_t * base
First readable byte of the flat view.
Definition unarch_io.h:80
size_t len
Readable length in bytes.
Definition unarch_io.h:81
Clean-room gzip member decoder (RFC 1952) over the miniz DEFLATE core.
ra8_err_t unarch_gzip_unwrap(unarch_read_fn read, void *ctx, uint64_t size, uint8_t *out, size_t out_cap, const ra8_decomp_limits_t *limits, size_t *out_len)
Decode one whole gzip member from a read seam into a caller arena.
bool unarch_gzip_magic(const uint8_t *sig, size_t sig_len)
Whether sig begins with the gzip member magic (1F 8B).
Shared seek+read seam and flat-memory backing for the unarchivers.
size_t unarch_mem_read(void *ctx, uint64_t offset, void *buf, size_t len)
unarch_read_fn over a flat unarch_mem_t view.
Definition unarch_io.c:24
Bounded, fail-closed XZ/LZMA2 decoding over the vendored xz-embedded.
bool unarch_xz_magic(const uint8_t *sig, size_t sig_len)
Whether sig begins with the XZ stream header magic.
Definition unarch_xz.c:77
ra8_err_t unarch_xz_unwrap(unarch_read_fn read, void *ctx, uint64_t size, uint8_t *out, size_t out_cap, void *scratch, uint32_t scratch_len, const ra8_decomp_limits_t *limits, size_t *out_len)
Decode one whole XZ stream from a read seam into a caller arena.
Definition unarch_xz.c:351