ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
31
32#include <capstone/capstone.h>
33#include <ctype.h>
34#include <stdalign.h>
35#include <stddef.h>
36#include <stdint.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <sys/stat.h>
41#include <time.h>
42#include <unicorn/unicorn.h>
43#include <unistd.h>
44
45#include "board_console.h"
46#include "board_input.h"
47#include "board_net.h"
48#include "board_overlay.h"
49#include "board_periph.h"
50#include "board_periph_eink.h"
51#include "board_periph_modem.h"
52#include "board_periph_sd.h"
53#include "board_usb.h"
54#include "board_usb_host.h"
55#include "board_view.h"
56#include "emu_args.h"
57#include "emu_console.h"
58#include "emu_cpu1.h"
59#include "emu_elf.h"
61#include "emu_engine.h"
62#include "emu_exc.h"
64#include "emu_memmap.h"
65#include "emu_mmio.h"
66#include "emu_mpu.h"
67#include "emu_prof.h"
68#include "emu_run.h"
69#include "emu_seams.h"
70#include "emu_trace.h"
71#include "emu_tz.h"
72#include "emu_usbh_seam.h"
73#include "emu_view.h"
74
80alignas(max_align_t) static uint8_t
82
97{
98 const emu_memmap_result_t result = emu_memmap_open(memory);
99 if (result.status == k_emu_memmap_ok) {
100 return true;
101 }
102 (void)priv_emu_io_errf("ra8_emulator: memory backing failed (%u): logical=%llu os=%d\n",
103 (unsigned int)result.status,
104 (unsigned long long)result.logical_backing_bytes,
105 result.os_error);
106 return false;
107}
108
129RA8_INTERNAL static const char*
130internal_main_apply_panel(const emu_args_t* args, uint16_t* view_w, uint16_t* view_h)
131{
132 static board_panel_t s_panel = {};
133 bool have_panel = false;
134 if (args->panel_path != nullptr) {
135 have_panel = load_panel(args->panel_path, &s_panel);
136 if (have_panel && !args->size_set) {
137 *view_w = s_panel.width;
138 *view_h = s_panel.height;
139 }
140 }
141 return (have_panel && (s_panel.name[0] != '\0')) ? s_panel.name : "ra8_emulator";
142}
143
159 uint16_t view_w,
160 uint16_t view_h,
162{
163 const emu_presentation_spec_t spec = {
164 .panel_width = view_w,
165 .panel_height = view_h,
166 .rotate_deg = args->rotate_deg,
167 .active = args->want_view || (args->ppm_path != nullptr) || args->want_click ||
168 (args->record_dir != nullptr),
169 };
170 const emu_presentation_result_t result =
174 workspace);
175 if (result.status != k_emu_presentation_ok) {
176 (void)priv_emu_io_errf("ra8_emulator: presentation workspace failed (%u): "
177 "surface=%zu scratch-required=%zu scratch-supplied=%zu os=%d\n",
178 (unsigned int)result.status,
182 result.os_error);
183 return false;
184 }
185 return true;
186}
187
209RA8_INTERNAL static int internal_main_open_engine(uc_engine** uc_out,
211{
212 uc_engine* uc = nullptr;
213 if (uc_open(UC_ARCH_ARM, (uc_mode)(UC_MODE_THUMB | UC_MODE_MCLASS), &uc) != UC_ERR_OK) {
214 (void)priv_emu_io_errf("uc_open failed\n");
215 return 1;
216 }
217 (void)uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_M33); /* closest to the M85. */
218 if (emu_memmap_attach(memory, uc).status != k_emu_memmap_ok) {
219 (void)uc_close(uc);
220 return 1;
221 }
222 /* Seed hardwired MPU_TYPE.DREGION (=8) so ra8_mpu_configure validates; the
223 * PPB is plain RAM here, so it would otherwise read 0 and panic
224 * mpu_partition_simple. */
225 wr32(uc, (uint64_t)k_mpu_type, (uint32_t)k_mpu_type_seed);
226 *uc_out = uc;
227 return 0;
228}
229
249RA8_INTERNAL static void internal_main_arm_touch_seq(const char* touch_seq_str)
250{
251 if (touch_seq_str == nullptr) {
252 return;
253 }
254 enum : uint32_t {
255 k_touch_seq_parse_max = 32U,
256 };
258 const char* p = touch_seq_str;
259 uint32_t pushed = 0U;
260 for (uint32_t n = 0U; (n < (uint32_t)k_touch_seq_parse_max) && (*p != '\0'); n++) {
261 char* end = nullptr;
262 const long x = strtol(p, &end, (int)k_strtol_base10);
263 if ((end == p) || (*end != ':')) {
264 break;
265 }
266 p = end + 1;
267 const long y = strtol(p, &end, (int)k_strtol_base10);
268 if (end == p) {
269 break;
270 }
271 p = end;
272 if ((x >= 0L) && (y >= 0L) && board_periph_touch_seq_push((uint16_t)x, (uint16_t)y)) {
273 pushed++;
274 }
275 if (*p == ',') {
276 p++;
277 }
278 }
279 (void)priv_emu_io_errf("ra8_emulator: --touch-seq armed %u raw point(s)\n", (unsigned)pushed);
280}
281
300{
301 if (args->button_press != 0) {
302 const uint8_t pin = (args->button_press == 2) ? (uint8_t)k_emu_sw2_pin : (uint8_t)k_emu_sw1_pin;
304 (void)priv_emu_io_errf("ra8_emulator: --button %d held (SW pin P00%u low/pressed)\n",
305 args->button_press,
306 (unsigned)pin);
307 }
308 if (args->battery_opt) {
309 uint8_t cur_soc = 0U;
310 board_periph_battery_get(&cur_soc, nullptr);
311 const uint8_t soc = (args->battery_soc >= 0) ? (uint8_t)args->battery_soc : cur_soc;
313 (void)priv_emu_io_errf("ra8_emulator: battery %u%% %s (MAX17048 @ I2C 0x36)\n",
314 (unsigned)soc,
315 args->battery_charging ? "charging" : "discharging");
316 }
317}
318
337{
338 if (args->input_str != nullptr) {
339 uint8_t rx[k_uart_line_max];
340 const uint32_t n = decode_escapes(args->input_str, rx, (uint32_t)sizeof(rx));
342 (void)priv_emu_io_errf("ra8_emulator: queued %u byte(s) to SCI%u RX from --input\n",
343 n,
345 }
346 if (args->keys_str != nullptr) {
347 uint8_t kb[k_uart_line_max];
348 const uint32_t n = decode_escapes(args->keys_str, kb, (uint32_t)sizeof(kb));
349 for (uint32_t k = 0U; k < n; k++) {
350 board_input_push_key((char)kb[k]);
351 }
352 (void)priv_emu_io_errf("ra8_emulator: queued %u keystroke(s) via --keys (window-key path)\n",
353 n);
354 }
355 if (args->usb_in_str != nullptr) {
356 uint8_t ub[k_uart_line_max];
357 const uint32_t n = decode_escapes(args->usb_in_str, ub, (uint32_t)sizeof(ub));
359 (void)priv_emu_io_errf("ra8_emulator: queued %u byte(s) to the USB CDC bulk OUT pipe\n", n);
360 }
361}
362
381{
384 board_periph_set_device(args->emu_device); /* gates the RA8P1-only NPU block. */
385 /* --usbhs-loop: activate the on-chip USBHS host model and hand the USBFS
386 * device to its bridge so the built-in virtual host stands down
387 * (chip-internal loop). */
394}
395
417RA8_INTERNAL static int
418internal_main_load_primary(uc_engine* uc, const char* elf_path, emu_elf_source_t* elf_out)
419{
420 const emu_elf_io_result_t opened = priv_emu_elf_source_open(elf_path, elf_out);
421 if (opened.status != k_emu_elf_io_ok) {
422 (void)priv_emu_io_errf("cannot read %s\n", elf_path);
423 return 1;
424 }
425 (void)priv_emu_io_errf("ra8_emulator: loading %s (%llu bytes)\n",
426 elf_path,
427 (unsigned long long)elf_out->length);
428 (void)priv_emu_io_errf(" device : %s\n",
430 ? "RA8P1 (R7KA8P1KFLCAC) -- +Ethos-U55 NPU"
431 : "RA8D2 (R7KA8D2KFLCAC)");
432 (void)priv_emu_io_errf(" primary core : %s%s\n",
434 ? "Cortex-M33 (Armv8-M)"
435 : "Cortex-M85 (Armv8.1-M, MVE seams armed)",
436 emu_low_power() ? " [low-power: 1/4 chunk budget]" : "");
437 if (load_elf(uc, elf_out) != 0) {
438 (void)priv_emu_elf_source_close(elf_out);
439 return 1;
440 }
441 return 0;
442}
443
466RA8_INTERNAL static int internal_main_load_ns(uc_engine* uc,
467 const char* ns_elf_path,
468 emu_elf_source_t* elf,
469 emu_elf_source_t* ns_out)
470{
471 if (ns_elf_path != nullptr) {
472 const emu_elf_io_result_t opened = priv_emu_elf_source_open(ns_elf_path, ns_out);
473 if (opened.status != k_emu_elf_io_ok) {
474 (void)priv_emu_io_errf("cannot read --ns %s\n", ns_elf_path);
475 (void)priv_emu_elf_source_close(elf);
476 return 1;
477 }
478 (void)priv_emu_io_errf("ra8_emulator: loading NS image %s (%llu bytes)\n",
479 ns_elf_path,
480 (unsigned long long)ns_out->length);
481 if (load_elf(uc, ns_out) != 0) {
482 (void)priv_emu_elf_source_close(ns_out);
483 (void)priv_emu_elf_source_close(elf);
484 return 1;
485 }
486 /* Track the NS image's vector base (0x32100000 RAM-resident, 0x90000000 XIP
487 * from OSPI) so the BLXNS world switch reads MSP/reset from the right
488 * place. */
489 const uint32_t ns_vbase = elf_vector_base(ns_out);
490 if (ns_vbase != 0U) {
492 }
493 (void)priv_emu_io_errf("ra8_emulator: NS vector base @ 0x%08X\n", emu_tz_ns_vector_base());
494 }
495 return 0;
496}
497
521 const emu_elf_source_t* ns_elf,
522 const emu_args_t* args,
523 uint32_t* dump_sym_addrs,
524 uint32_t* stop_sym_addr)
525{
526 for (uint32_t d = 0U; d < args->dump_sym_n; d++) {
527 dump_sym_addrs[d] = elf_sym_addr(elf, args->dump_sym_names[d], nullptr);
528 if ((dump_sym_addrs[d] == 0U) && (ns_elf->fd >= 0)) {
529 dump_sym_addrs[d] = elf_sym_addr(ns_elf, args->dump_sym_names[d], nullptr);
530 }
531 if (dump_sym_addrs[d] == 0U) {
532 (void)priv_emu_io_errf("ra8_emulator: --dump-sym %s not found in symbol table\n",
533 args->dump_sym_names[d]);
534 }
535 }
536 *stop_sym_addr = 0U;
537 if (args->stop_sym_name != nullptr) {
538 *stop_sym_addr = elf_sym_addr(elf, args->stop_sym_name, nullptr);
539 if ((*stop_sym_addr == 0U) && (ns_elf->fd >= 0)) {
540 *stop_sym_addr = elf_sym_addr(ns_elf, args->stop_sym_name, nullptr);
541 }
542 if (*stop_sym_addr == 0U) {
543 (void)priv_emu_io_errf("ra8_emulator: --stop-sym %s not found in symbol table\n",
544 args->stop_sym_name);
545 }
546 }
547}
548
566RA8_INTERNAL static uint32_t internal_main_reset_vector(uc_engine* uc)
567{
568 uint32_t sp = 0U;
569 uint32_t pc = 0U;
570 /* MRAM[0] */
571 (void)emu_mem_read(uc, emu_memmap_mram_base() + 0U, &sp, 4);
572 /* MRAM[4] (Thumb: bit0=1) */
573 (void)emu_mem_read(uc, emu_memmap_mram_base() + 4U, &pc, 4);
574 pc |= 1U; /* M-profile is always Thumb (EPSR.T must be 1). */
575 uint32_t xpsr = (uint32_t)k_xpsr_t_bit; /* xPSR.T */
576 (void)uc_reg_write(uc, UC_ARM_REG_SP, &sp);
577 (void)uc_reg_write(uc, UC_ARM_REG_PC, &pc);
578 (void)uc_reg_write(uc, UC_ARM_REG_XPSR, &xpsr);
579 (void)priv_emu_io_errf("ra8_emulator: reset SP=0x%08X PC=0x%08X -- running "
580 "(<= %u x %u insns, %u s wall)\n",
581 sp,
582 pc,
583 (unsigned)k_run_max_chunks,
584 (unsigned)k_run_chunk_insns,
585 (unsigned)k_run_wall_s);
586 return pc;
587}
588
608 const emu_elf_source_t* elf)
609{
612 /* Seed the ITM ready bits + echo stimulus-port writes so ra8_log prints
613 * [itm]. */
615 /* TrustZone S->NS boot seams (SAU_TYPE seed + hand-emulated BLXNS), armed
616 * only when the firmware links the secure boot. */
617 emu_tz_install(uc, elf);
619 emu_mpu_install(uc);
620}
621
645 const emu_elf_source_t* elf,
646 const emu_args_t* args,
648{
649 bool usbh_seamed = false;
650 if (!args->usbhs_loop) {
651 usbh_seamed = usbh_seam_install(uc, elf);
652 }
653 /* Register-level USBHS host model: only an UNSEAMED, non-loop firmware
654 * engages it, so the C-level seam / loop-only register block do not both
655 * answer. */
656 board_usb_host_set_allowed(!usbh_seamed && !args->usbhs_loop);
657 sym_trace_install(uc, elf, args->trace_sym_names, args->trace_sym_n);
658 /* M85-only long-shift (LSLL/LSRL/ASRL) + MVE (Helium) seams: off under
659 * --primary-core m33 (pure Armv8-M), inert but honest. CSEL rides the
660 * invalid- instruction hook and stays armed (also inert for an M33 image). */
661 if (emu_primary_core() == k_core_m85) {
663 }
664 div0_seam_install(elf); /* UDIV/SDIV sites, patched only under DIV_0_TRP. */
665 fast_sd_seam_install(uc, elf); /* --fast-sd whole-block serve; else inert. */
666 prof_load(elf); /* RA8_EMU_PROFILE FUNC symbols + code hook. */
668 emu_cpu1_init(elf, memory); /* dual-core cpu1 engine; no-op for single-core. */
669}
670
702 uc_engine* uc,
703 emu_elf_source_t* elf,
704 uint32_t pc,
705 uint32_t vtor_base,
706 uint16_t view_w,
707 uint16_t view_h,
708 const char* win_title,
709 const uint32_t* dump_sym_addrs,
710 uint32_t stop_sym_addr,
711 emu_presentation_workspace_t* presentation,
713{
714 return (emu_run_cfg_t){
715 .uc = uc,
716 .elf = elf,
717 .initial_pc = pc,
718 .vtor_base = vtor_base,
719 .want_trace = args->want_trace,
720 .want_view = args->want_view,
721 .want_click = args->want_click,
722 .click_x = args->click_x,
723 .click_y = args->click_y,
724 .ppm_path = args->ppm_path,
725 .record_dir = args->record_dir,
726 .record_secs = args->record_secs,
727 .rotate_deg = args->rotate_deg,
728 .reboot_count = args->reboot_count,
729 .save_sd_path = args->save_sd_path,
730 .stop_sym_addr = stop_sym_addr,
731 .stop_sym_thresh = args->stop_sym_thresh,
732 .dump_sym_names = args->dump_sym_names,
733 .dump_sym_addrs = dump_sym_addrs,
734 .dump_sym_n = args->dump_sym_n,
735 .view_w = view_w,
736 .view_h = view_h,
737 .win_title = win_title,
738 .presentation = presentation,
739 .memory = memory,
740 };
741}
742
768 emu_presentation_workspace_t* presentation,
769 uc_engine* uc,
770 emu_elf_source_t* elf,
771 emu_elf_source_t* ns_elf,
772 uint16_t view_w,
773 uint16_t view_h,
774 const char* win_title)
775{
776 uint32_t dump_sym_addrs[k_dump_sym_max] = {};
777 uint32_t stop_sym_addr = 0U;
778 internal_main_resolve_symbols(elf, ns_elf, args, dump_sym_addrs, &stop_sym_addr);
779 if (ns_elf->fd >= 0) {
780 (void)priv_emu_elf_source_close(ns_elf);
781 }
782 emu_tz_patch_cmse(uc, elf);
783
784 const uint32_t pc = internal_main_reset_vector(uc);
785 const uint32_t vtor_base = (uint32_t)emu_memmap_mram_base();
787 internal_main_install_run_seams(uc, elf, args, memory);
788
789 const emu_run_cfg_t run_cfg = internal_main_build_run_cfg(args,
790 uc,
791 elf,
792 pc,
793 vtor_base,
794 view_w,
795 view_h,
796 win_title,
797 dump_sym_addrs,
798 stop_sym_addr,
799 presentation,
800 memory);
801 return emu_run_and_report(&run_cfg);
802}
803
825 const emu_args_t* args,
827 emu_presentation_workspace_t* presentation,
828 emu_elf_source_t* elf,
829 emu_elf_source_t* ns_elf)
830{
831 if (internal_main_load_primary(uc, args->elf_path, elf) != 0) {
832 (void)emu_memmap_detach(memory, uc);
833 (void)uc_close(uc);
834 (void)emu_memmap_close(memory);
835 (void)emu_presentation_close(presentation);
836 return 1;
837 }
838 if (internal_main_load_ns(uc, args->ns_elf_path, elf, ns_elf) != 0) {
839 (void)priv_emu_elf_source_close(elf);
840 (void)emu_memmap_detach(memory, uc);
841 (void)uc_close(uc);
842 (void)emu_memmap_close(memory);
843 (void)emu_presentation_close(presentation);
844 return 1;
845 }
846 return 0;
847}
848
849int main(int argc, char** argv)
850{
851 priv_emu_io_configure(STDOUT_FILENO, STDERR_FILENO, nullptr);
852 emu_args_t args = {};
853 if (!emu_args_parse(argc, argv, &args)) {
854 return 2;
855 }
856 uint16_t view_w = args.view_w;
857 uint16_t view_h = args.view_h;
858 const char* const win_title = internal_main_apply_panel(&args, &view_w, &view_h);
859 emu_presentation_workspace_t presentation = {.fd = -1};
860 if (!internal_main_open_presentation(&args, view_w, view_h, &presentation)) {
861 return 2;
862 }
863 emu_memmap_workspace_t memory = {};
864 if (!internal_main_open_memory(&memory)) {
865 (void)emu_presentation_close(&presentation);
866 return 2;
867 }
868
869 uc_engine* uc = nullptr;
870 if (internal_main_open_engine(&uc, &memory) != 0) {
871 (void)emu_memmap_close(&memory);
872 (void)emu_presentation_close(&presentation);
873 return 1;
874 }
876
877 emu_elf_source_t elf = {.fd = -1};
878 emu_elf_source_t ns_elf = {.fd = -1};
879 if (internal_main_load_images(uc, &args, &memory, &presentation, &elf, &ns_elf) != 0) {
880 return 1;
881 }
882
883 return internal_main_run_loaded(&args,
884 &memory,
885 &presentation,
886 uc,
887 &elf,
888 &ns_elf,
889 view_w,
890 view_h,
891 win_title);
892}
void main(void)
Secure fallback main entry point.
Definition main.c:37
Multi-channel console log store backing the board view's tabbed console.
Host-side keystroke FIFO: window / CLI key source -> UART RX sink.
void board_input_push_key(char ch)
Push one keystroke byte into the input FIFO.
Definition board_input.c:28
Virtual network peer for ra8_emulator – talks TCP/IP to the firmware.
void board_net_init(bool trace)
Reset the virtual network peer to its initial state.
Definition board_net.c:786
Composite board-view renderer: panel framebuffer + a status sidebar.
Register-accurate peripheral-model framework for the board emulator.
void board_periph_init(bool trace)
One-time reset of all peripheral-model state.
board_device_t board_periph_device(void)
Report which RA8 device the peripheral model is emulating.
void board_periph_sci_feed_rx(uint8_t channel, const uint8_t *data, uint32_t len)
Queue host->firmware bytes for a channel's receive path.
void board_periph_battery_get(uint8_t *out_soc, bool *out_charging)
Read back the emulated battery state (for the status overlay).
bool board_periph_touch_seq_push(uint16_t x, uint16_t y)
Queue one raw touch point onto the modelled GT911 injection FIFO.
void board_periph_set_usbhs_loop(bool on)
Enable the chip-internal USBHS-host self-loop model (–usbhs-loop).
uint8_t board_periph_sci_console_channel(void)
The SCI channel the EK-RA8D2 console (J-Link OB VCOM) uses.
void board_periph_sci_set_tx_sink(void(*sink)(uint8_t channel, uint8_t byte))
Wire a host sink that receives every byte the firmware transmits.
void board_periph_touch_seq_reset(void)
Clear the modelled GT911 injected-touch sequence FIFO.
void board_periph_battery_set(uint8_t soc_pct, bool charging)
Set the emulated battery state surfaced by the MAX17048 fuel gauge.
void board_periph_gpio_set_input(uint8_t port, uint8_t pin, bool level)
Drive a GPIO pin's input level from outside the firmware.
void board_periph_set_device(board_device_t device)
Select which RA8 device the peripheral model emulates.
@ k_board_device_ra8p1
Renesas RA8P1: adds the Ethos-U55 NPU.
IT8951 e-paper SPI-device model for ra8_emulator (attached to SPI_B).
Cellular AT-modem device model for ra8_emulator (attached to SCI7 UART).
SD-card-over-SPI device model for ra8_emulator (attached to SPI_B).
USBFS controller model + a virtual USB host for the board emulator.
void board_usb_feed_bulk_in(const uint8_t *data, uint32_t len)
Queue host->device bulk bytes for the CDC data OUT pipe (echo test).
Definition board_usb.c:196
void board_usb_set_external_host(bool present)
Declare (or withdraw) a real-firmware USB host driving the device.
USBHS HOST-mode controller model (self-loop peer of the USBFS device).
void board_usb_host_set_allowed(bool allowed)
Grant (or deny) the register-level loop for this firmware.
Minimal self-contained macOS window for the board emulator.
ra8_emulator command-line parsing (usage text + option decoding)
bool emu_args_parse(int argc, char **argv, emu_args_t *out)
Parse the ra8_emulator command line into out (or print usage).
Definition emu_args.c:485
Emulator text-console surfaces: UART echo, ITM/SWO echo, escapes.
uint32_t decode_escapes(const char *in, uint8_t *out, uint32_t cap)
Decode a C-style escaped –input string into a raw byte buffer.
@ k_uart_line_max
Pretty-print line buffer for the [uart] prefix.
Definition emu_console.h:92
void emu_console_install(uc_engine *uc)
Seed ITM "ready" bits and arm the stimulus-port echo hook.
void console_tx_sink(uint8_t channel, uint8_t byte)
SCI TX sink: print each transmitted byte (prefixed line + raw mirror).
Second-core (cpu1, Cortex-M33) engine: release watch, boot, stepping.
void emu_cpu1_init(const emu_elf_source_t *elf, emu_memmap_workspace_t *memory)
Create the second emulator engine for cpu1, if the image carries one.
Definition emu_cpu1.c:178
ELF32 image services for the board emulator (load / symbols / vectors).
uint32_t elf_sym_addr(const emu_elf_source_t *elf, const char *name, uint32_t *size_out)
Resolve a function symbol's entry address from the ELF .symtab.
int load_elf(uc_engine *uc, const emu_elf_source_t *elf)
Load ELF32 PT_LOAD segments into emulated memory at their LMA.
Definition emu_elf.c:248
uint32_t elf_vector_base(const emu_elf_source_t *elf)
Vector-table base of an ELF: lowest executable PT_LOAD VMA.
Definition emu_elf.c:320
@ k_emu_elf_io_ok
The complete operation succeeded.
Definition emu_elf.h:75
Private raw-descriptor ELF source operations.
emu_elf_io_result_t priv_emu_elf_source_open(const char *path, emu_elf_source_t *source)
Open one regular ELF source without reading or allocating its bytes.
emu_elf_io_result_t priv_emu_elf_source_close(emu_elf_source_t *source)
Close and invalidate one independently owned ELF source.
Shared Unicorn engine access utilities for the board emulator.
static void wr32(uc_engine *uc, uint64_t addr, uint32_t v)
Write a 32-bit little-endian word to emulated memory.
Definition emu_engine.h:91
Cortex-M exception model constants and interfaces for ra8_emulator.
@ k_xpsr_t_bit
xPSR.T (Thumb) – must stay set.
Definition emu_exc.h:93
@ k_mpu_type_seed
8 data regions (matches the M85 MPU).
Definition emu_exc.h:45
@ k_mpu_type
MPU_TYPE (DREGION in bits 15:8).
Definition emu_exc.h:44
void emu_exc_install_scb_nvic(uc_engine *uc)
Arm the SCB control-word and NVIC ISER/ICER write watchers.
void emu_exc_install_core(uc_engine *uc)
Arm the core exception hooks (unmapped / INTR / ICSR watch).
Definition emu_exc.c:898
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
void priv_emu_io_configure(int out_fd, int err_fd, const emu_io_ops_t *ops)
Inject process output descriptors and optional raw transfer hooks.
Shared aliased-memory backing and Unicorn memory-map bindings.
emu_memmap_result_t emu_memmap_open(emu_memmap_workspace_t *workspace)
Create three independent, lazily-committed host aperture mappings.
Definition emu_memmap.c:439
struct emu_memmap_workspace emu_memmap_workspace_t
Independent aperture backing with at most two engine bindings.
@ k_emu_memmap_ok
Operation completed exactly.
Definition emu_memmap.h:63
emu_memmap_result_t emu_memmap_attach(emu_memmap_workspace_t *workspace, uc_engine *uc)
Map one Unicorn engine onto the shared aperture backing.
Definition emu_memmap.c:463
bool emu_memmap_detach(emu_memmap_workspace_t *workspace, uc_engine *uc)
Remove one engine binding before closing that Unicorn engine.
Definition emu_memmap.c:486
bool emu_memmap_close(emu_memmap_workspace_t *workspace)
Release every host aperture mapping after all engines detached.
Definition emu_memmap.c:500
uint64_t emu_memmap_mram_base(void)
Return the MRAM boot-vector base.
Definition emu_memmap.c:523
uc_err emu_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t count)
Read guest memory through the central access seam.
Sparse MMIO model of the Renesas peripheral space.
Armv8-M MPU enforcement model for ra8_emulator.
void emu_mpu_install(uc_engine *uc)
Arm the MPU register watchers (RLAR capture + CTRL edge hooks).
Definition emu_mpu.c:295
@ k_emu_presentation_ok
Operation completed exactly.
bool emu_presentation_close(emu_presentation_workspace_t *workspace)
Close one owned presentation descriptor and invalidate the workspace.
@ k_emu_presentation_max_scratch_bytes
Exact maximum caller scratch: source plus rotated 64x64 RGB565 tiles.
emu_presentation_result_t emu_presentation_open(const emu_presentation_spec_t *spec, void *scratch, size_t supplied_scratch_bytes, emu_presentation_workspace_t *workspace)
Create and bind one unlinked raw-fd presentation workspace.
Firmware profiler (RA8_EMU_PROFILE): sampling, hooks, reports.
void emu_prof_install(uc_engine *uc)
Arm the per-instruction profiling hook (insn mode only).
Definition emu_prof.c:940
void prof_load(const emu_elf_source_t *elf)
Collect + sort FUNC symbols (RA8_EMU_PROFILE only) for PC bucketing.
Definition emu_prof.c:160
The chunked emulation run loop, report and exit-code mapping.
int emu_run_and_report(const emu_run_cfg_t *cfg)
Run the firmware to a stop condition, print the report, map the exit code.
Definition emu_run.c:852
@ k_run_wall_s
Wall-clock safety bound (seconds).
Definition emu_run.h:62
@ k_run_chunk_insns
Instructions per emulation chunk.
Definition emu_run.h:38
@ k_run_max_chunks
Chunk budget.
Definition emu_run.h:42
@ k_dump_sym_max
Max –dump-sym globals per run.
Definition emu_run.h:97
Armv8.1-M instruction-emulation seams (M85 ops on Unicorn's M33).
void div0_seam_install(const emu_elf_source_t *elf)
Scan the image for UDIV/SDIV sites so the div-0 trap can arm later.
void emu_insn_seams_install(uc_engine *uc)
Arm the invalid-instruction dispatcher on the engine.
void long_shift_seam_install(uc_engine *uc, const emu_elf_source_t *elf)
Scan the loaded image and install a hook at every immediate long-shift.
void fast_sd_seam_install(uc_engine *uc, const emu_elf_source_t *elf)
Install the --fast-sd block-read hook if opted-in and the symbol exists.
Function-entry seam glue + the –trace-sym instrument.
void sym_trace_install(uc_engine *uc, const emu_elf_source_t *elf, const char *const *names, uint32_t count)
Install a --trace-sym entry hook for every requested symbol present.
Definition emu_trace.c:98
TrustZone Secure/Non-Secure seams for ra8_emulator.
uint32_t emu_tz_ns_vector_base(void)
The tracked NS vector-table fallback base.
Definition emu_tz.c:228
void emu_tz_install(uc_engine *uc, const emu_elf_source_t *elf)
Arm the TrustZone S->NS boot seams (SAU_TYPE seed + BLXNS hook).
Definition emu_tz.c:152
void emu_tz_set_ns_vector_base(uint32_t base)
Track the NS image's actual vector base (–ns load path).
Definition emu_tz.c:222
void emu_tz_patch_cmse(uc_engine *uc, const emu_elf_source_t *elf)
Patch cmse_check_address_range to BX LR (flat-domain model).
Definition emu_tz.c:194
Virtual USB host-mode devices behind the ra8_usb_host_* / hmsc seams.
bool usbh_seam_install(uc_engine *uc, const emu_elf_source_t *elf)
Install the virtual USB host-mode device seam if the host stack is linked.
Board-view presentation: frames, composition, input routing, panels.
@ k_emu_sw1_pin
SW1 -> P009.
Definition emu_view.h:37
@ k_emu_sw2_pin
SW2 -> P008.
Definition emu_view.h:38
@ k_emu_sw_port
Both user switches sit on PORT0.
Definition emu_view.h:36
bool emu_low_power(void)
Whether the M33 4:1-slower low-power clock model is active.
Definition emu_view.c:645
@ k_strtol_base10
Base-10 radix for strtol parses.
Definition emu_view.h:85
bool load_panel(const char *path, board_panel_t *out)
Load a panel descriptor (name / width / height) from a TOML-ish file.
Definition emu_view.c:550
@ k_core_m33
Cortex-M33 primary: the M85-only instruction seams stay off.
Definition emu_view.h:65
@ k_core_m85
Cortex-M85 primary (default): MVE/long-shift seams armed.
Definition emu_view.h:64
board_primary_core_t emu_primary_core(void)
The primary core the firmware targets (label + seam gating).
Definition emu_view.c:633
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
ra8_board_eth_pin_t pin
Pin.
static ra8_epaper_panel_t s_panel
Single-instance panel context.
Definition ra8_epaper.c:194
Display descriptor loaded from a flat key=value panel file.
Definition emu_view.h:92
Every value the ra8_emulator CLI parse produces for the setup phase.
Definition emu_args.h:51
uint32_t stop_sym_thresh
–stop-sym stop threshold.
Definition emu_args.h:66
int click_x
–click column (-1 = unset).
Definition emu_args.h:74
const char * elf_path
Firmware ELF path (argv[1]).
Definition emu_args.h:52
const char * touch_seq_str
–touch-seq raw-point FIFO string.
Definition emu_args.h:61
int click_y
–click row (-1 = unset).
Definition emu_args.h:75
const char * stop_sym_name
–stop-sym watch global (NULL = off).
Definition emu_args.h:65
uint32_t trace_sym_n
Count of –trace-sym entries.
Definition emu_args.h:68
uint16_t view_w
Panel width in pixels.
Definition emu_args.h:81
uint32_t dump_sym_n
Count of –dump-sym entries.
Definition emu_args.h:64
const char * usb_in_str
–usb-in CDC bulk OUT string.
Definition emu_args.h:62
int battery_soc
–battery pct (-1 = model default).
Definition emu_args.h:78
bool usbhs_loop
–usbhs-loop chip-internal self-loop.
Definition emu_args.h:84
bool want_view
–view live window.
Definition emu_args.h:53
const char * panel_path
–panel descriptor path (NULL = none).
Definition emu_args.h:58
const char * trace_sym_names[k_trace_sym_max]
–trace-sym functions to log.
Definition emu_args.h:67
int button_press
–button: 1=SW1, 2=SW2, 0=none.
Definition emu_args.h:76
bool battery_opt
Any battery flag given.
Definition emu_args.h:80
const char * ns_elf_path
–ns second (NS) image path.
Definition emu_args.h:70
bool want_trace
–trace transition logging.
Definition emu_args.h:73
const char * save_sd_path
–save-sd dump path (NULL = off).
Definition emu_args.h:69
int reboot_count
–reboot N warm reboots.
Definition emu_args.h:77
uint16_t view_h
Panel height in pixels.
Definition emu_args.h:82
const char * dump_sym_names[k_dump_sym_max]
–dump-sym globals to read.
Definition emu_args.h:63
bool battery_charging
–charge given.
Definition emu_args.h:79
const char * record_dir
–record directory (NULL = off).
Definition emu_args.h:55
board_device_t emu_device
–device selected part (RA8D2 default).
Definition emu_args.h:83
bool size_set
–size given (wins over –panel).
Definition emu_args.h:71
const char * keys_str
–keys window-key path string.
Definition emu_args.h:60
const char * ppm_path
–ppm output path (NULL = off).
Definition emu_args.h:54
bool want_click
–click armed with valid coordinates.
Definition emu_args.h:72
uint32_t record_secs
–record-secs bound (0 = unbounded).
Definition emu_args.h:56
uint32_t rotate_deg
–rotate display rotation (0 default).
Definition emu_args.h:57
const char * input_str
–input console RX string.
Definition emu_args.h:59
Exact result for source open and bounded view acquisition.
Definition emu_elf.h:83
emu_elf_io_status_t status
Semantic completion status.
Definition emu_elf.h:84
One independently owned immutable raw-descriptor ELF source.
Definition emu_elf.h:91
int fd
Owned regular-file descriptor, or -1 when closed.
Definition emu_elf.h:92
uint64_t length
Stat-derived parsing bound.
Definition emu_elf.h:93
Exact requirements and operation outcome.
Definition emu_memmap.h:70
int os_error
Captured errno for host mapping.
Definition emu_memmap.h:73
uint64_t logical_backing_bytes
Sum of the three aperture lengths.
Definition emu_memmap.h:72
emu_memmap_status_t status
Semantic completion status.
Definition emu_memmap.h:71
Exact result of a requirements or workspace operation.
size_t required_scratch_bytes
Exact caller scratch.
emu_presentation_status_t status
Semantic result.
size_t required_surface_bytes
Exact raw-fd length.
int os_error
Captured errno for I/O.
size_t supplied_scratch_bytes
Caller capacity.
Inputs controlling exact presentation requirements.
One independent owned surface plus non-owning bounded scratch.
Everything setup hands the run loop: engine, image, CLI products.
Definition emu_run.h:122
static RA8_INTERNAL void internal_main_bringup_peripherals(const emu_args_t *args)
Bring up the peripheral models and apply pre-boot input state.
Definition main.c:380
static RA8_INTERNAL int internal_main_load_images(uc_engine *uc, const emu_args_t *args, emu_memmap_workspace_t *memory, emu_presentation_workspace_t *presentation, emu_elf_source_t *elf, emu_elf_source_t *ns_elf)
Load the primary and optional non-secure images into the engine.
Definition main.c:824
static RA8_INTERNAL int internal_main_open_engine(uc_engine **uc_out, emu_memmap_workspace_t *memory)
Open the Unicorn engine, set the memory map, seed hardwired SCS regs.
Definition main.c:209
static RA8_INTERNAL uint32_t internal_main_reset_vector(uc_engine *uc)
Read the reset vector, set the initial CPU registers, print the banner.
Definition main.c:566
static RA8_INTERNAL bool internal_main_open_presentation(const emu_args_t *args, uint16_t view_w, uint16_t view_h, emu_presentation_workspace_t *workspace)
Create the exact fd-backed surface before engine/output mutation.
Definition main.c:158
static RA8_INTERNAL emu_run_cfg_t internal_main_build_run_cfg(const emu_args_t *args, uc_engine *uc, emu_elf_source_t *elf, uint32_t pc, uint32_t vtor_base, uint16_t view_w, uint16_t view_h, const char *win_title, const uint32_t *dump_sym_addrs, uint32_t stop_sym_addr, emu_presentation_workspace_t *presentation, emu_memmap_workspace_t *memory)
Build the run configuration handed to emu_run_and_report().
Definition main.c:701
static RA8_INTERNAL bool internal_main_open_memory(emu_memmap_workspace_t *memory)
Open the shared aliased-memory backing before engine mutation.
Definition main.c:96
static RA8_INTERNAL int internal_main_run_loaded(const emu_args_t *args, emu_memmap_workspace_t *memory, emu_presentation_workspace_t *presentation, uc_engine *uc, emu_elf_source_t *elf, emu_elf_source_t *ns_elf, uint16_t view_w, uint16_t view_h, const char *win_title)
Resolve loaded firmware state, install seams, and run the emulator.
Definition main.c:766
static uint8_t s_main_presentation_scratch[k_emu_presentation_max_scratch_bytes]
Explicit bounded presentation scratch owned by the process root.
Definition main.c:81
static RA8_INTERNAL const char * internal_main_apply_panel(const emu_args_t *args, uint16_t *view_w, uint16_t *view_h)
Apply a –panel descriptor to the window size and title.
Definition main.c:130
static RA8_INTERNAL void internal_main_install_core_seams(uc_engine *uc, const emu_elf_source_t *elf)
Install the core execution, exception, console, TrustZone + MPU seams.
Definition main.c:607
static RA8_INTERNAL void internal_main_apply_button_battery(const emu_args_t *args)
Apply –button and –battery / –charge before the firmware boots.
Definition main.c:299
static RA8_INTERNAL void internal_main_install_run_seams(uc_engine *uc, const emu_elf_source_t *elf, const emu_args_t *args, emu_memmap_workspace_t *memory)
Install the USB, symbol-trace, ISA-emulation and profiler seams.
Definition main.c:644
static RA8_INTERNAL int internal_main_load_ns(uc_engine *uc, const char *ns_elf_path, emu_elf_source_t *elf, emu_elf_source_t *ns_out)
Read + load the optional –ns second (Non-Secure) image.
Definition main.c:466
static RA8_INTERNAL int internal_main_load_primary(uc_engine *uc, const char *elf_path, emu_elf_source_t *elf_out)
Read + load the primary firmware ELF and print the load banner.
Definition main.c:418
static RA8_INTERNAL void internal_main_arm_touch_seq(const char *touch_seq_str)
Arm the modelled GT911 injection FIFO from a –touch-seq string.
Definition main.c:249
static RA8_INTERNAL void internal_main_feed_inputs(const emu_args_t *args)
Queue the –input / –keys / –usb-in injected byte streams.
Definition main.c:336
static RA8_INTERNAL void internal_main_resolve_symbols(const emu_elf_source_t *elf, const emu_elf_source_t *ns_elf, const emu_args_t *args, uint32_t *dump_sym_addrs, uint32_t *stop_sym_addr)
Resolve the –dump-sym globals and the –stop-sym watch address.
Definition main.c:520