ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fmt_portable_main.c
Go to the documentation of this file.
1
10
11#include <stddef.h>
12#include <stdint.h>
13#include <string.h>
14#include <unistd.h>
15
16#include "ra8_attributes.h"
19#include "ra8_fmt_stream.h"
20
30
32typedef enum : uint8_t {
37
54static ra8_err_t internal_text(const ra8_fmt_sink_t* sink, const char* text)
55{
56 return sink->write(sink->ctx, (const uint8_t*)text, strlen(text));
57}
58
75static ra8_err_t internal_u64(const ra8_fmt_sink_t* sink, uint64_t value)
76{
77 char reverse[k_cli_decimal_chars];
78 size_t count = 0U;
79 do {
80 reverse[count++] = (char)('0' + (char)(value % k_cli_decimal_radix));
81 value /= k_cli_decimal_radix;
82 } while (value != 0U);
83 char text[k_cli_decimal_chars];
84 for (size_t i = 0U; i < count; ++i) {
85 text[i] = reverse[count - i - 1U];
86 }
87 return sink->write(sink->ctx, (const uint8_t*)text, count);
88}
89
105static void internal_error_status(const ra8_fmt_sink_t* sink, const char* prefix, ra8_err_t status)
106{
107 ra8_err_t rc = internal_text(sink, prefix);
108 if (rc == k_ra8_ok) {
109 rc = internal_u64(sink, (uint64_t)status);
110 }
111 if (rc == k_ra8_ok) {
112 (void)internal_text(sink, ")\n");
113 }
114}
115
137static bool
138internal_parse(int argc, char** argv, const char** input, const char** format, bool* verbose)
139{
140 for (int i = 2; i < argc; ++i) {
141 if ((strcmp(argv[i], "--verbose") == 0) || (strcmp(argv[i], "-v") == 0)) {
142 *verbose = true;
143 } else if ((strcmp(argv[i], "--format") == 0) && ((i + 1) < argc)) {
144 *format = argv[++i];
145 } else if ((strcmp(argv[i], "--in") == 0) && ((i + 1) < argc)) {
146 *input = argv[++i];
147 } else if ((strcmp(argv[i], "--out") == 0) && ((i + 1) < argc)) {
148 ++i;
149 } else if ((argv[i][0] != '-') && (*input == nullptr)) {
150 *input = argv[i];
151 } else {
152 return false;
153 }
154 }
155 return true;
156}
157
175static ra8_err_t
176internal_format(const ra8_fmt_source_t* source, const char* explicit_name, cli_format_t* format)
177{
178 *format = k_cli_format_none;
179 if (explicit_name != nullptr) {
180 if (strcmp(explicit_name, "jof") == 0) {
181 *format = k_cli_format_jof;
182 } else if (strcmp(explicit_name, "rabook") == 0) {
183 *format = k_cli_format_rabook;
184 }
185 return k_ra8_ok;
186 }
187 uint8_t magic[4U];
188 size_t got = 0U;
189 const ra8_err_t rc = source->read_at(source->ctx, 0U, magic, sizeof(magic), &got);
190 if (rc != k_ra8_ok) {
191 return rc;
192 }
193 if ((got == sizeof(magic)) && (memcmp(magic, "JOF1", sizeof(magic)) == 0)) {
194 *format = k_cli_format_jof;
195 } else if ((got == sizeof(magic)) && (memcmp(magic, "RBKC", sizeof(magic)) == 0)) {
196 *format = k_cli_format_rabook;
197 }
198 return k_ra8_ok;
199}
200
216 const jof_audit_requirements_t* need)
217{
218 ra8_err_t rc = internal_text(sink, "ra8_fmt: JOF inspect workspace too small: records ");
219 if (rc == k_ra8_ok) {
220 rc = internal_u64(sink, need->record_count);
221 }
222 if (rc == k_ra8_ok) {
223 rc = internal_text(sink, "/65536, tile ");
224 }
225 if (rc == k_ra8_ok) {
226 rc = internal_u64(sink, need->tile_bytes);
227 }
228 if (rc == k_ra8_ok) {
229 rc = internal_text(sink, "/4194304, scratch ");
230 }
231 if (rc == k_ra8_ok) {
232 rc = internal_u64(sink, need->scratch_bytes);
233 }
234 if (rc == k_ra8_ok) {
235 (void)internal_text(sink, "/4718848\n");
236 }
237}
238
259static int internal_run_jof(const ra8_fmt_source_t* source,
260 bool verbose,
261 ra8_fmt_cli_workspace_t* workspace,
262 const ra8_fmt_sink_t* output,
263 const ra8_fmt_sink_t* errors)
264{
265 jof_audit_requirements_t need = {};
266 ra8_err_t rc = jof_audit_requirements(source->read_at, source->ctx, source->size, &need);
267 if (rc != k_ra8_ok) {
268 internal_error_status(errors, "JOF parse FAILED (rc=", rc);
269 return (int)k_cli_exit_fail;
270 }
274 internal_workspace_error(errors, &need);
275 return (int)k_cli_exit_fail;
276 }
277 const size_t records_bytes = sizeof(jof_audit_record_t) * (size_t)k_ra8_fmt_cli_record_cap;
278 ra8_fmt_jof_inspect_workspace_t inspect_workspace = {
279 .records = (jof_audit_record_t*)workspace->bytes,
280 .record_cap = k_ra8_fmt_cli_record_cap,
281 .tile = &workspace->bytes[records_bytes],
282 .tile_cap = k_ra8_fmt_cli_tile_cap,
283 .scratch = &workspace->bytes[records_bytes + k_ra8_fmt_cli_tile_cap],
284 .scratch_cap = k_ra8_fmt_cli_scratch_cap,
285 };
286 rc = ra8_fmt_jof_inspect_stream(source, verbose, &inspect_workspace, output);
287 return (rc == k_ra8_ok) ? (int)k_cli_exit_ok : (int)k_cli_exit_fail;
288}
289
309static int internal_run_rabook(const ra8_fmt_source_t* source,
310 bool verbose,
311 ra8_fmt_cli_workspace_t* workspace,
312 const ra8_fmt_sink_t* output)
313{
314 const size_t table_bytes = (size_t)k_ra8_fmt_cli_rbkc_table_cap * sizeof(uint64_t);
315 ra8_fmt_rabook_inspect_workspace_t inspect_workspace = {
316 .table = (uint64_t*)workspace->bytes,
317 .table_cap = k_ra8_fmt_cli_rbkc_table_cap,
318 .compressed = &workspace->bytes[table_bytes],
319 .compressed_cap = k_ra8_fmt_cli_rbkc_compressed_cap,
320 .chunk = &workspace->bytes[table_bytes + k_ra8_fmt_cli_rbkc_compressed_cap],
321 .chunk_cap = k_ra8_fmt_cli_rbkc_chunk_cap,
322 .scratch =
323 &workspace
325 .scratch_cap = k_ra8_fmt_cli_rbkc_scratch_cap,
326 };
327 const ra8_err_t rc = ra8_fmt_rabook_inspect_stream(source, verbose, &inspect_workspace, output);
328 return (rc == k_ra8_ok) ? (int)k_cli_exit_ok : (int)k_cli_exit_fail;
329}
330
354static int internal_open(const char* input,
355 const char* explicit_name,
356 bool verbose,
357 ra8_fmt_cli_workspace_t* workspace,
358 bool* handled,
359 const ra8_fmt_sink_t* errors)
360{
361 ra8_fmt_host_source_t host_source = {.fd = -1};
362 ra8_err_t rc = priv_fmt_host_source_open(input, k_cli_input_cap, &host_source);
364 if (rc == k_ra8_ok) {
365 rc = internal_format(&host_source.source, explicit_name, &format);
366 }
367 if (rc != k_ra8_ok) {
368 internal_error_status(errors, "ra8_fmt: cannot open inspect input (rc=", rc);
369 return (int)k_cli_exit_fail;
370 }
371 if (format == k_cli_format_none) {
372 priv_fmt_host_source_close(&host_source);
373 *handled = false;
374 return (int)k_cli_exit_ok;
375 }
376 ra8_fmt_host_fd_sink_t output_state = {.fd = STDOUT_FILENO};
377 const ra8_fmt_sink_t output = priv_fmt_host_fd_sink(&output_state);
378 const int status = (format == k_cli_format_jof)
379 ? internal_run_jof(&host_source.source, verbose, workspace, &output, errors)
380 : internal_run_rabook(&host_source.source, verbose, workspace, &output);
381 priv_fmt_host_source_close(&host_source);
382 return status;
383}
384
386 char** argv,
387 ra8_fmt_cli_workspace_t* workspace,
388 bool* handled)
389{
390 if ((handled == nullptr) || (workspace == nullptr)) {
391 return (int)k_cli_exit_fail;
392 }
393 *handled = false;
394 if ((argc < 2) || (strcmp(argv[1], "inspect") != 0)) {
395 return (int)k_cli_exit_ok;
396 }
397 const char* input = nullptr;
398 const char* format = nullptr;
399 bool verbose = false;
400 ra8_fmt_host_fd_sink_t error_state = {.fd = STDERR_FILENO};
401 const ra8_fmt_sink_t errors = priv_fmt_host_fd_sink(&error_state);
402 if (!internal_parse(argc, argv, &input, &format, &verbose)) {
403 *handled = true;
404 (void)internal_text(&errors, "ra8_fmt: invalid inspect arguments\n");
405 return (int)k_cli_exit_usage;
406 }
407 *handled = true;
408 if (input == nullptr) {
409 (void)internal_text(&errors, "ra8_fmt: no input file given\n");
410 return (int)k_cli_exit_usage;
411 }
412 return internal_open(input, format, verbose, workspace, handled, &errors);
413}
ra8_err_t jof_audit_requirements(jof_pread_fn pread, void *pread_ctx, uint64_t total_size, jof_audit_requirements_t *out)
Parse an atlas and report exact caller-storage requirements.
Definition jof_audit.c:237
Annotation-attribute framework macros for ra8-firmware.
#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).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Raw file-descriptor adapters for the portable format-tool contracts.
ra8_err_t priv_fmt_host_source_open(const char *path, uint64_t max_size, ra8_fmt_host_source_t *out)
Open a bounded, regular, non-symlink input object.
ra8_fmt_sink_t priv_fmt_host_fd_sink(ra8_fmt_host_fd_sink_t *state)
Obtain the exact-write portable sink for a raw descriptor.
void priv_fmt_host_source_close(ra8_fmt_host_source_t *source)
Close an open host source; safe after failed open.
static void internal_workspace_error(const ra8_fmt_sink_t *sink, const jof_audit_requirements_t *need)
Report exact workspace requirements and capacities.
static int internal_open(const char *input, const char *explicit_name, bool verbose, ra8_fmt_cli_workspace_t *workspace, bool *handled, const ra8_fmt_sink_t *errors)
Open, classify, and inspect one bounded host source.
static ra8_err_t internal_format(const ra8_fmt_source_t *source, const char *explicit_name, cli_format_t *format)
Resolve an explicit name or four-byte container magic.
static int internal_run_rabook(const ra8_fmt_source_t *source, bool verbose, ra8_fmt_cli_workspace_t *workspace, const ra8_fmt_sink_t *output)
Bind the existing shared high-water to strict RBKC workspaces.
static ra8_err_t internal_text(const ra8_fmt_sink_t *sink, const char *text)
Append one literal through an injected sink.
cli_const_t
Exit values and explicit composition workspace budgets.
@ k_cli_decimal_chars
Maximum unsigned decimal digits.
@ k_cli_exit_fail
Command ran and failed.
@ k_cli_exit_ok
Successful command.
@ k_cli_input_cap
Maximum accepted input (256 MiB).
@ k_cli_decimal_radix
Status-code formatting radix.
@ k_cli_exit_usage
Invalid command line.
static bool internal_parse(int argc, char **argv, const char **input, const char **format, bool *verbose)
Parse the established inspect command arguments.
cli_format_t
Supported inspect-container classifications.
@ k_cli_format_none
Unknown or unsupported container.
@ k_cli_format_jof
JOF1 band-tile atlas.
@ k_cli_format_rabook
RBKC chunked RABOOK1 container.
static int internal_run_jof(const ra8_fmt_source_t *source, bool verbose, ra8_fmt_cli_workspace_t *workspace, const ra8_fmt_sink_t *output, const ra8_fmt_sink_t *errors)
Execute inspection after CLI ownership and source resolution.
static void internal_error_status(const ra8_fmt_sink_t *sink, const char *prefix, ra8_err_t status)
Emit one error line with an integer status.
static ra8_err_t internal_u64(const ra8_fmt_sink_t *sink, uint64_t value)
Append an unsigned decimal through an injected sink.
int priv_fmt_try_portable_inspect(int argc, char **argv, ra8_fmt_cli_workspace_t *workspace, bool *handled)
Try strict streamed JOF or RBKC inspection.
Caller-workspace CLI composition for every supported tool verb.
@ k_ra8_fmt_cli_record_cap
All legal JOF audit records.
@ k_ra8_fmt_cli_scratch_cap
Stored-tile bound bytes.
@ k_ra8_fmt_cli_rbkc_scratch_cap
Strict book work.
@ k_ra8_fmt_cli_rbkc_table_cap
At most 65,536 chunks plus end.
@ k_ra8_fmt_cli_rbkc_compressed_cap
One stored chunk.
@ k_ra8_fmt_cli_tile_cap
Decoded-tile bytes (4 MiB).
@ k_ra8_fmt_cli_rbkc_chunk_cap
One inflated chunk.
Caller-workspace I/O contracts for portable format-tool engines.
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.
ra8_err_t ra8_fmt_jof_inspect_stream(const ra8_fmt_source_t *source, bool verbose, const ra8_fmt_jof_inspect_workspace_t *workspace, const ra8_fmt_sink_t *report)
Inspect one JOF source through callbacks and caller storage.
int strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
size_t strlen(const char *s)
Calculate string length.
One decoded tile's stored window and content evidence.
Definition jof_audit.h:38
Exact caller-storage requirements derived from a parsed atlas.
Definition jof_audit.h:53
uint32_t scratch_bytes
Stored-stream scratch (zero for raw).
Definition jof_audit.h:56
uint32_t record_count
Record entries required.
Definition jof_audit.h:54
uint32_t tile_bytes
Decoded tile-buffer bytes required.
Definition jof_audit.h:55
One explicit, shared composition-root workspace for portable verbs.
uint8_t bytes[k_ra8_fmt_cli_workspace_bytes]
Shared named storage.
Append sink backed by a caller-owned descriptor.
Open raw-fd source and its portable view.
ra8_fmt_source_t source
Portable positioned-read view.
Exact caller-owned storage used by streaming JOF inspection.
Caller-owned storage for strict streamed RBKC/RABOOK1 inspection.
Injected append-only sink.
ra8_fmt_sink_write_fn write
Exact append callback.
void * ctx
Backend-owned context.
Immutable, randomly readable input object.
uint64_t size
Exact object byte length.
void * ctx
Backend-owned context.
jof_pread_fn read_at
Positioned-read callback.