Skip to content

Instantly share code, notes, and snippets.

@bbaranoff
Last active January 5, 2026 13:52
Show Gist options
  • Select an option

  • Save bbaranoff/1d3420074c8207ff919e5c6ce83b3fe1 to your computer and use it in GitHub Desktop.

Select an option

Save bbaranoff/1d3420074c8207ff919e5c6ce83b3fe1 to your computer and use it in GitHub Desktop.
Adding Calypso machine to qemu
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/log.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/misc/unimp.h"
#include "hw/char/serial.h"
#include "hw/block/flash.h"
#include "sysemu/sysemu.h"
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
#include "target/arm/cpu.h"
#include "elf.h"
#define TYPE_CALYPSO_MIN_MACHINE MACHINE_TYPE_NAME("calypso-min")
OBJECT_DECLARE_SIMPLE_TYPE(CalypsoMinState, CALYPSO_MIN_MACHINE)
#define CALYPSO_FLASH_BASE 0x02000000u
#define CALYPSO_FLASH_SIZE (4 * MiB)
#define FLASH_SECTOR_SIZE (64 * KiB)
#define CALYPSO_RAM_BASE 0x00800000u
#define CALYPSO_RAM_ALIAS0_BASE 0x00000000u
#define CALYPSO_RAM_ALIAS0_SIZE (128 * KiB)
#define CALYPSO_UART_BASE 0xFFFF5800u
#define CALYPSO_SPI_BASE 0xFFFE3000u
#define CALYPSO_SPI_SIZE 0x00000100u
#define SPI_OFF_STATUS 0x06
#define SPI_OFF_DATA 0x0A
#define ST_TX_READY (1u << 0)
#define ST_RX_READY (1u << 1)
#define CALYPSO_UART_SIZE 0x00000100u
#define UART_OFF_TXRX 0x00
#define UART_OFF_STATUS 0x11
#define UART_ST_TX_READY 0x60 /* valeur “OK” pour éviter polling infini */
#define CALYPSO_SYSFB_BASE 0xFFFFFB00u
#define CALYPSO_SYSFB_SIZE 0x00000100u
#define CALYPSO_SYSFD_BASE 0xFFFFFD00u
#define CALYPSO_SYSFD_SIZE 0x00000100u
#define CALYPSO_48XX_BASE 0xFFFE4800u
#define CALYPSO_48XX_SIZE 0x00000100u
#define CALYPSO_28XX_BASE 0xFFFE2800u
#define CALYPSO_28XX_SIZE 0x00000100u
#define CALYPSO_18XX_BASE 0xFFFE1800u
#define CALYPSO_18XX_SIZE 0x00000100u
#define CALYPSO_68XX_BASE 0xFFFE6800u
#define CALYPSO_68XX_SIZE 0x00000100u
#define CALYPSO_FAXX_BASE 0xFFFFFA00u
#define CALYPSO_FAXX_SIZE 0x00000100u
#define CALYPSO_50XX_BASE 0xFFFF5000u
#define CALYPSO_50XX_SIZE 0x00000100u
#define CALYPSO_FCXX_BASE 0xFFFFFC00u
#define CALYPSO_FCXX_SIZE 0x00000100u
#define CALYPSO_TMR1_BASE 0xFFFE3800u
#define CALYPSO_TMR1_SIZE 0x00000100u /* prends large, le firmware touche au moins +0x00 */
#define CALYPSO_98XX_BASE 0xFFFF9800u
#define CALYPSO_98XX_SIZE 0x00000100u
#define CALYPSO_F9XX_BASE 0xFFFFF900u
#define CALYPSO_F9XX_SIZE 0x00000100u
#define CALYPSO_F0XX_BASE 0xFFFEF000u
#define CALYPSO_F0XX_SIZE 0x00000100u
#define CALYPSO_VECTORS_HI_BASE 0xFFFF0000u
#define CALYPSO_VECTORS_HI_SIZE 0x00010000u
#define CALYPSO_FFXX_BASE 0xFFFFFF00u
#define CALYPSO_FFXX_SIZE 0x00000100u
#define CALYPSO_80XX_BASE 0xFFFE8000u
#define CALYPSO_80XX_SIZE 0x00000100u
typedef struct CalypsoMinState {
MachineState parent_obj;
ARMCPU *cpu;
MemoryRegion ram;
MemoryRegion ram_alias0;
MemoryRegion stub_mmio; /* Pour utiliser la structure ops */
MemoryRegion spi_mmio;
uint16_t spi_status;
uint16_t spi_rx;
MemoryRegion uart_mmio;
MemoryRegion uart_alias0;
uint8_t uart_last;
MemoryRegion sysfb_mmio;
MemoryRegion sysfd_mmio;
MemoryRegion mmio_48xx;
uint16_t sysfb_regs[0x80]; /* 0x100 bytes / 2 */
uint16_t sysfd_regs[0x80];
uint16_t regs_48xx[0x80];
MemoryRegion mmio_28xx;
uint8_t regs_28xx[CALYPSO_28XX_SIZE];
MemoryRegion mmio_18xx;
uint8_t regs_18xx[CALYPSO_18XX_SIZE];
MemoryRegion mmio_68xx;
uint8_t regs_68xx[CALYPSO_68XX_SIZE];
MemoryRegion mmio_faxx;
uint16_t regs_faxx[0x80];
MemoryRegion mmio_faxx_alias0;
MemoryRegion mmio_50xx;
uint8_t regs_50xx[CALYPSO_50XX_SIZE];
MemoryRegion mmio_fcxx;
MemoryRegion mmio_fcxx_alias0;
uint16_t regs_fcxx[0x80];
/* Timer @ 0xFFFE3800 */
MemoryRegion tmr_mmio;
uint16_t tmr_cnt;
MemoryRegion mmio_98xx;
uint16_t regs_98xx[0x80];
MemoryRegion mmio_f9xx;
MemoryRegion mmio_f9xx_alias0100;
uint16_t regs_f9xx[0x80];
MemoryRegion mmio_f0xx;
uint16_t regs_f0xx[0x80];
MemoryRegion ram_alias_hi;
MemoryRegion ffxx_mmio;
uint8_t regs_ffxx[CALYPSO_FFXX_SIZE];
MemoryRegion mmio_80xx;
uint8_t regs_80xx[CALYPSO_80XX_SIZE];
} CalypsoMinState;
static uint64_t calypso_stub_read(void *opaque, hwaddr off, unsigned size) {
return (off == 0x06) ? 0x0003 : 0;
}
static void calypso_stub_write(void *opaque, hwaddr off, uint64_t val, unsigned size) {
/* Stub write */
}
static const MemoryRegionOps calypso_stub_ops = {
.read = calypso_stub_read,
.write = calypso_stub_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t calypso_spi_read(void *opaque, hwaddr off, unsigned size)
{
CalypsoMinState *s = (CalypsoMinState *)opaque;
if (size == 2 && off == SPI_OFF_STATUS) {
return s->spi_status;
}
if (size == 2 && off == SPI_OFF_DATA) {
return s->spi_rx;
}
return 0;
}
static void calypso_spi_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
CalypsoMinState *s = (CalypsoMinState *)opaque;
if (size == 2 && off == SPI_OFF_DATA) {
/* répond quelque chose et signale "ready" */
s->spi_rx = 0xFFFF;
s->spi_status = (ST_TX_READY | ST_RX_READY);
}
}
static uint64_t calypso_uart_read(void *opaque, hwaddr off, unsigned size)
{
CalypsoMinState *s = (CalypsoMinState *)opaque;
if (size != 1) {
return 0;
}
if (off == UART_OFF_STATUS) {
return UART_ST_TX_READY;
}
if (off == UART_OFF_TXRX) {
return s->uart_last;
}
return 0;
}
static void calypso_uart_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
CalypsoMinState *s = (CalypsoMinState *)opaque;
if (size != 1) {
return;
}
if (off == UART_OFF_TXRX) {
s->uart_last = (uint8_t)val;
/* log minimal */
qemu_log_mask(LOG_GUEST_ERROR, "[calypso-uart] '%c' (0x%02x)\n",
(val >= 32 && val < 127) ? (char)val : '.', (unsigned)val);
}
}
static const MemoryRegionOps calypso_uart_ops = {
.read = calypso_uart_read,
.write = calypso_uart_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t calypso_reg16_read(void *opaque, hwaddr off, unsigned size)
{
uint16_t *regs = (uint16_t *)opaque;
if (size != 2) {
return 0;
}
off &= 0xFE; /* aligne 16-bit */
uint32_t idx = (uint32_t)(off >> 1);
return regs[idx];
}
static void calypso_reg16_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
uint16_t *regs = (uint16_t *)opaque;
if (size != 2) {
return;
}
off &= 0xFE;
uint32_t idx = (uint32_t)(off >> 1);
regs[idx] = (uint16_t)val;
}
/* Variante “always ready” pour casser les polls */
static uint64_t calypso_ready16_read(void *opaque, hwaddr off, unsigned size)
{
uint16_t *regs = (uint16_t *)opaque;
if (size != 2) {
return 0;
}
off &= 0xFE;
uint32_t idx = (uint32_t)(off >> 1);
/* Force un bit “ready” (0xFFFF = prêt pour beaucoup de drivers crades) */
if (off == 0x0A) { /* ton log lit 0x...480A */
return 0xFFFF;
}
return regs[idx];
}
static const MemoryRegionOps calypso_reg16_ops = {
.read = calypso_reg16_read,
.write = calypso_reg16_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static const MemoryRegionOps calypso_ready16_ops = {
.read = calypso_ready16_read,
.write = calypso_reg16_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t calypso_reg8_read(void *opaque, hwaddr off, unsigned size)
{
uint8_t *regs = (uint8_t *)opaque;
if (size != 1) {
return 0;
}
/* Pour casser le polling: offsets vus dans ton log */
if (off == 0x04 || off == 0x09) {
return 0xFF;
}
return regs[off & 0xFF];
if (off == 0x03) {
/* “power key pressed” + “no pending irq” style: renvoie un truc non-bloquant */
return 0x01;
}
}
static void calypso_reg8_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
uint8_t *regs = (uint8_t *)opaque;
if (size != 1) {
return;
}
regs[off & 0xFF] = (uint8_t)val;
}
static uint64_t calypso_80xx_read(void *opaque, hwaddr off, unsigned size)
{
CalypsoMinState *s = opaque;
if (size != 1) {
return 0;
}
return s->regs_80xx[off & 0xFF];
}
static inline void calypso_log_mmio(const char *op, hwaddr addr,
unsigned size, uint64_t val, bool has_val)
{
if (has_val) {
qemu_log_mask(LOG_GUEST_ERROR,
"[calypso-mmio] %s addr=0x%08" HWADDR_PRIx " size=%u val=0x%08" PRIx64 "\n",
op, addr, size, val);
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"[calypso-mmio] %s addr=0x%08" HWADDR_PRIx " size=%u\n",
op, addr, size);
}
}
static void calypso_80xx_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
CalypsoMinState *s = opaque;
if (size != 1) {
return;
}
s->regs_80xx[off & 0xFF] = (uint8_t)val;
calypso_log_mmio("80XX-WRITE", CALYPSO_80XX_BASE + off, size, val, true);
}
static const MemoryRegionOps calypso_80xx_ops = {
.read = calypso_80xx_read,
.write = calypso_80xx_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static const MemoryRegionOps calypso_reg8_ops = {
.read = calypso_reg8_read,
.write = calypso_reg8_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t calypso_reg8_16_read(void *opaque, hwaddr off, unsigned size)
{
uint8_t *r = (uint8_t *)opaque;
off &= 0xFF;
if (size == 1) {
/* casse les polls éventuels */
if (off == 0x00) return 0xFF;
return r[off];
}
if (size == 2) {
uint16_t lo = r[off];
uint16_t hi = r[(off + 1) & 0xFF];
return (hi << 8) | lo; /* little-endian */
}
return 0;
}
static void calypso_reg8_16_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
uint8_t *r = (uint8_t *)opaque;
off &= 0xFF;
if (size == 1) {
r[off] = (uint8_t)val;
return;
}
if (size == 2) {
r[off] = (uint8_t)(val & 0xFF);
r[(off + 1) & 0xFF] = (uint8_t)((val >> 8) & 0xFF);
return;
}
}
static uint64_t calypso_tmr_read(void *opaque, hwaddr off, unsigned size)
{
CalypsoMinState *s = (CalypsoMinState *)opaque;
if (size == 1) {
/* renvoie qqchose de stable pour éviter le blocage */
if ((off & 0xFF) == 0x02) {
return (uint8_t)(s->tmr_cnt++ & 0xFF);
}
return 0;
}
if (size == 2) {
if ((off & 0xFF) == 0x02) {
return s->tmr_cnt++;
}
return 0;
}
return 0;
}
static void calypso_tmr_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
(void)opaque; (void)val;
/* accepter size 1 / 2 */
calypso_log_mmio("TMR-WRITE", CALYPSO_TMR1_BASE + off, size, val, true);
}
static const MemoryRegionOps calypso_reg8_16_ops = {
.read = calypso_reg8_16_read,
.write = calypso_reg8_16_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static const MemoryRegionOps calypso_tmr_ops = {
.read = calypso_tmr_read,
.write = calypso_tmr_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t calypso_ffxx_read(void *opaque, hwaddr off, unsigned size)
{
CalypsoMinState *s = opaque;
if (size != 1) {
return 0;
}
/* Valeur par défaut "safe" */
uint8_t v = s->regs_ffxx[off & 0xFF];
/* Option anti-blocage : si ça poll un status, on pourra ajuster ici */
return v;
}
static void calypso_ffxx_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
{
CalypsoMinState *s = opaque;
if (size != 1) {
return;
}
s->regs_ffxx[off & 0xFF] = (uint8_t)val;
calypso_log_mmio("FFXX-WRITE", CALYPSO_FFXX_BASE + off, size, val, true);
}
static const MemoryRegionOps calypso_ffxx_ops = {
.read = calypso_ffxx_read,
.write = calypso_ffxx_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void calypso_min_init(MachineState *ms)
{
CalypsoMinState *s = CALYPSO_MIN_MACHINE(ms);
MemoryRegion *sysmem = get_system_memory();
s->cpu = ARM_CPU(cpu_create(ms->cpu_type ? ms->cpu_type : ARM_CPU_TYPE_NAME("arm946")));
/* 1. RAM principale */
memory_region_init_ram(&s->ram, NULL, "calypso.ram", ms->ram_size, &error_fatal);
memory_region_add_subregion(sysmem, CALYPSO_RAM_BASE, &s->ram);
/* 2. Alias RAM @ 0x0 (Priorité 1) - Garantit l'affichage */
memory_region_init_alias(&s->ram_alias0, NULL, "calypso.ram.alias0",
&s->ram, 0, CALYPSO_RAM_ALIAS0_SIZE);
memory_region_add_subregion_overlap(sysmem, CALYPSO_RAM_ALIAS0_BASE, &s->ram_alias0, 1);
s->spi_status = (ST_TX_READY | ST_RX_READY);
s->spi_rx = 0xFFFF;
/* Alias vecteurs HIGH @ 0xFFFF0000 (certains firmwares/CPU le veulent) */
memory_region_init_alias(&s->ram_alias_hi, NULL, "calypso.ram.aliashi",
&s->ram, 0, CALYPSO_VECTORS_HI_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), CALYPSO_VECTORS_HI_BASE,
&s->ram_alias_hi, -1);
static const MemoryRegionOps calypso_spi_ops = {
.read = calypso_spi_read,
.write = calypso_spi_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
memset(s->regs_ffxx, 0x00, sizeof(s->regs_ffxx));
memory_region_init_io(&s->ffxx_mmio, NULL, &calypso_ffxx_ops, s,
"calypso.ffxx", CALYPSO_FFXX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_FFXX_BASE, &s->ffxx_mmio);
/* UART stub @ 0xFFFF5800 */
memory_region_init_io(&s->uart_mmio, NULL, &calypso_uart_ops, s,
"calypso.uart", CALYPSO_UART_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_UART_BASE, &s->uart_mmio);
/* Alias UART @ 0x00000000 pour couvrir les reads à 0x11 */
memory_region_init_alias(&s->uart_alias0, NULL, "calypso.uart.alias0",
&s->uart_mmio, 0, CALYPSO_UART_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), 0x00000000u,
&s->uart_alias0, -2);
memory_region_init_io(&s->spi_mmio, NULL, &calypso_spi_ops, s, "calypso.spi", CALYPSO_SPI_SIZE);
memory_region_add_subregion(sysmem, CALYPSO_SPI_BASE, &s->spi_mmio);
/* 3. NOR Flash @ 0x02000000 (Miroir pour éviter le conflit avec la RAM) */
DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi01_register(CALYPSO_FLASH_BASE, "calypso.flash", CALYPSO_FLASH_SIZE,
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
FLASH_SECTOR_SIZE, 4,
0x0089, 0x8871, 0x0089, 0x8871, 0);
/* 4. Utilisation des ops pour éviter l'erreur de compilation */
memory_region_init_io(&s->stub_mmio, NULL, &calypso_stub_ops, s, "calypso.stub", 0x100);
memory_region_add_subregion(sysmem, 0xFFFE4000, &s->stub_mmio);
/* 5. UART */
if (serial_hd(0)) {
serial_mm_init(sysmem, CALYPSO_UART_BASE, 0, NULL, 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
}
/* 0xFFFFFB00 block */
memory_region_init_io(&s->sysfb_mmio, NULL, &calypso_reg16_ops,
s->sysfb_regs, "calypso.sysfb", CALYPSO_SYSFB_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_SYSFB_BASE, &s->sysfb_mmio);
/* 0xFFFFFD00 block */
memory_region_init_io(&s->sysfd_mmio, NULL, &calypso_reg16_ops,
s->sysfd_regs, "calypso.sysfd", CALYPSO_SYSFD_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_SYSFD_BASE, &s->sysfd_mmio);
/* 0xFFFE4800 block: status “ready” à +0x0A */
memory_region_init_io(&s->mmio_48xx, NULL, &calypso_ready16_ops,
s->regs_48xx, "calypso.48xx", CALYPSO_48XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_48XX_BASE, &s->mmio_48xx);
memory_region_init_io(&s->mmio_28xx, NULL, &calypso_reg8_ops,
s->regs_28xx, "calypso.28xx", CALYPSO_28XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_28XX_BASE, &s->mmio_28xx);
memory_region_init_io(&s->mmio_18xx, NULL, &calypso_reg8_ops,
s->regs_18xx, "calypso.18xx", CALYPSO_18XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_18XX_BASE, &s->mmio_18xx);
memory_region_init_io(&s->mmio_68xx, NULL, &calypso_reg8_16_ops,
s->regs_68xx, "calypso.68xx", CALYPSO_68XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_68XX_BASE, &s->mmio_68xx);
memory_region_init_io(&s->mmio_faxx, NULL, &calypso_reg16_ops,
s->regs_faxx, "calypso.faxx", CALYPSO_FAXX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_FAXX_BASE, &s->mmio_faxx);
memory_region_init_alias(&s->mmio_faxx_alias0, NULL, "calypso.faxx.alias0",
&s->mmio_faxx, 0, CALYPSO_FAXX_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), 0x00000000u,
&s->mmio_faxx_alias0, -3);
memory_region_init_io(&s->mmio_50xx, NULL, &calypso_reg8_ops,
s->regs_50xx, "calypso.50xx", CALYPSO_50XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_50XX_BASE, &s->mmio_50xx);
memory_region_init_io(&s->mmio_fcxx, NULL, &calypso_reg16_ops,
s->regs_fcxx, "calypso.fcxx", CALYPSO_FCXX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_FCXX_BASE, &s->mmio_fcxx);
/* Alias bas pour capter 0x00000002 */
memory_region_init_alias(&s->mmio_fcxx_alias0, NULL, "calypso.fcxx.alias0",
&s->mmio_fcxx, 0, CALYPSO_FCXX_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), 0x00000000u,
&s->mmio_fcxx_alias0, -4);
/* Stub Timer (Priorité 1) */
s->tmr_cnt = 0;
memory_region_init_io(&s->tmr_mmio, NULL, &calypso_tmr_ops, s,
"calypso.tmr1", CALYPSO_TMR1_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), CALYPSO_TMR1_BASE,
&s->tmr_mmio, 1);
memory_region_init_io(&s->mmio_98xx, NULL, &calypso_reg16_ops,
s->regs_98xx, "calypso.98xx", CALYPSO_98XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_98XX_BASE, &s->mmio_98xx);
memory_region_init_io(&s->mmio_f9xx, NULL, &calypso_reg16_ops,
s->regs_f9xx, "calypso.f9xx", CALYPSO_F9XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_F9XX_BASE, &s->mmio_f9xx);
/* Alias bas à 0x00000100 pour capter 0x100/0x102/0x104 */
memory_region_init_alias(&s->mmio_f9xx_alias0100, NULL, "calypso.f9xx.alias0100",
&s->mmio_f9xx, 0, 0x100);
memory_region_add_subregion_overlap(get_system_memory(), 0x00000100u,
&s->mmio_f9xx_alias0100, -5);
memory_region_init_io(&s->mmio_f0xx, NULL, &calypso_reg16_ops,
s->regs_f0xx, "calypso.f0xx", CALYPSO_F0XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_F0XX_BASE, &s->mmio_f0xx);
memset(s->regs_80xx, 0x00, sizeof(s->regs_80xx));
memory_region_init_io(&s->mmio_80xx, NULL, &calypso_80xx_ops, s,
"calypso.80xx", CALYPSO_80XX_SIZE);
memory_region_add_subregion(get_system_memory(), CALYPSO_80XX_BASE, &s->mmio_80xx);
/* 6. Chargement ELF et Patch de la variable 'the_flash' */
if (ms->kernel_filename) {
uint64_t entry = 0;
if (load_elf(ms->kernel_filename, NULL, NULL, &entry, NULL, NULL, NULL, NULL, 0, EM_ARM, 1, 0) >= 0) {
/* Patch de la variable 'the_flash' (0x008147e8) pour pointer sur 0x02000000 */
uint32_t flash_addr = tswap32(CALYPSO_FLASH_BASE);
cpu_physical_memory_write(0x008147e8, &flash_addr, 4);
cpu_set_pc(CPU(s->cpu), entry);
}
}
}
static void calypso_min_class_init(ObjectClass *oc, void *data) {
MachineClass *mc = MACHINE_CLASS(oc);
mc->init = calypso_min_init;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm946");
mc->ignore_memory_transaction_failures = true;
}
static const TypeInfo calypso_min_typeinfo = {
.name = TYPE_CALYPSO_MIN_MACHINE, .parent = TYPE_MACHINE,
.instance_size = sizeof(CalypsoMinState), .class_init = calypso_min_class_init,
};
static void calypso_min_register_types(void) { type_register_static(&calypso_min_typeinfo); }
type_init(calypso_min_register_types);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment