xref: /qemu/hw/vmapple/cfg.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
133b54462SAlexander Graf /*
233b54462SAlexander Graf  * VMApple Configuration Region
333b54462SAlexander Graf  *
433b54462SAlexander Graf  * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
533b54462SAlexander Graf  *
633b54462SAlexander Graf  * SPDX-License-Identifier: GPL-2.0-or-later
733b54462SAlexander Graf  *
833b54462SAlexander Graf  * This work is licensed under the terms of the GNU GPL, version 2 or later.
933b54462SAlexander Graf  * See the COPYING file in the top-level directory.
1033b54462SAlexander Graf  */
1133b54462SAlexander Graf 
1233b54462SAlexander Graf #include "qemu/osdep.h"
1333b54462SAlexander Graf #include "hw/vmapple/vmapple.h"
1433b54462SAlexander Graf #include "hw/sysbus.h"
1533b54462SAlexander Graf #include "qemu/log.h"
1633b54462SAlexander Graf #include "qemu/module.h"
1733b54462SAlexander Graf #include "qapi/error.h"
1833b54462SAlexander Graf #include "net/net.h"
1933b54462SAlexander Graf 
2033b54462SAlexander Graf OBJECT_DECLARE_SIMPLE_TYPE(VMAppleCfgState, VMAPPLE_CFG)
2133b54462SAlexander Graf 
2233b54462SAlexander Graf #define VMAPPLE_CFG_SIZE 0x00010000
2333b54462SAlexander Graf 
2433b54462SAlexander Graf typedef struct VMAppleCfg {
2533b54462SAlexander Graf     uint32_t version;         /* 0x000 */
2633b54462SAlexander Graf     uint32_t nr_cpus;         /* 0x004 */
2733b54462SAlexander Graf     uint32_t unk1;            /* 0x008 */
2833b54462SAlexander Graf     uint32_t unk2;            /* 0x00c */
2933b54462SAlexander Graf     uint32_t unk3;            /* 0x010 */
3033b54462SAlexander Graf     uint32_t unk4;            /* 0x014 */
3133b54462SAlexander Graf     uint64_t ecid;            /* 0x018 */
3233b54462SAlexander Graf     uint64_t ram_size;        /* 0x020 */
3333b54462SAlexander Graf     uint32_t run_installer1;  /* 0x028 */
3433b54462SAlexander Graf     uint32_t unk5;            /* 0x02c */
3533b54462SAlexander Graf     uint32_t unk6;            /* 0x030 */
3633b54462SAlexander Graf     uint32_t run_installer2;  /* 0x034 */
3733b54462SAlexander Graf     uint32_t rnd;             /* 0x038 */
3833b54462SAlexander Graf     uint32_t unk7;            /* 0x03c */
3933b54462SAlexander Graf     MACAddr mac_en0;          /* 0x040 */
4033b54462SAlexander Graf     uint8_t pad1[2];
4133b54462SAlexander Graf     MACAddr mac_en1;          /* 0x048 */
4233b54462SAlexander Graf     uint8_t pad2[2];
4333b54462SAlexander Graf     MACAddr mac_wifi0;        /* 0x050 */
4433b54462SAlexander Graf     uint8_t pad3[2];
4533b54462SAlexander Graf     MACAddr mac_bt0;          /* 0x058 */
4633b54462SAlexander Graf     uint8_t pad4[2];
4733b54462SAlexander Graf     uint8_t reserved[0xa0];   /* 0x060 */
4833b54462SAlexander Graf     uint32_t cpu_ids[0x80];   /* 0x100 */
4933b54462SAlexander Graf     uint8_t scratch[0x200];   /* 0x180 */
5033b54462SAlexander Graf     char serial[32];          /* 0x380 */
5133b54462SAlexander Graf     char unk8[32];            /* 0x3a0 */
5233b54462SAlexander Graf     char model[32];           /* 0x3c0 */
5333b54462SAlexander Graf     uint8_t unk9[32];         /* 0x3e0 */
5433b54462SAlexander Graf     uint32_t unk10;           /* 0x400 */
5533b54462SAlexander Graf     char soc_name[32];        /* 0x404 */
5633b54462SAlexander Graf } VMAppleCfg;
5733b54462SAlexander Graf 
5833b54462SAlexander Graf struct VMAppleCfgState {
5933b54462SAlexander Graf     SysBusDevice parent_obj;
6033b54462SAlexander Graf     VMAppleCfg cfg;
6133b54462SAlexander Graf 
6233b54462SAlexander Graf     MemoryRegion mem;
6333b54462SAlexander Graf     char *serial;
6433b54462SAlexander Graf     char *model;
6533b54462SAlexander Graf     char *soc_name;
6633b54462SAlexander Graf };
6733b54462SAlexander Graf 
vmapple_cfg_reset(Object * obj,ResetType type)6833b54462SAlexander Graf static void vmapple_cfg_reset(Object *obj, ResetType type)
6933b54462SAlexander Graf {
7033b54462SAlexander Graf     VMAppleCfgState *s = VMAPPLE_CFG(obj);
7133b54462SAlexander Graf     VMAppleCfg *cfg;
7233b54462SAlexander Graf 
7333b54462SAlexander Graf     cfg = memory_region_get_ram_ptr(&s->mem);
7433b54462SAlexander Graf     memset(cfg, 0, VMAPPLE_CFG_SIZE);
7533b54462SAlexander Graf     *cfg = s->cfg;
7633b54462SAlexander Graf }
7733b54462SAlexander Graf 
set_fixlen_property_or_error(char * restrict dst,const char * restrict src,size_t dst_size,Error ** errp,const char * property_name)7833b54462SAlexander Graf static bool set_fixlen_property_or_error(char *restrict dst,
7933b54462SAlexander Graf                                          const char *restrict src,
8033b54462SAlexander Graf                                          size_t dst_size, Error **errp,
8133b54462SAlexander Graf                                          const char *property_name)
8233b54462SAlexander Graf {
8333b54462SAlexander Graf     ERRP_GUARD();
8433b54462SAlexander Graf     size_t len;
8533b54462SAlexander Graf 
8633b54462SAlexander Graf     len = g_strlcpy(dst, src, dst_size);
8733b54462SAlexander Graf     if (len < dst_size) { /* len does not count nul terminator */
8833b54462SAlexander Graf         return true;
8933b54462SAlexander Graf     }
9033b54462SAlexander Graf 
9133b54462SAlexander Graf     error_setg(errp, "Provided value too long for property '%s'", property_name);
9233b54462SAlexander Graf     error_append_hint(errp, "length (%zu) exceeds maximum of %zu\n",
9333b54462SAlexander Graf                       len, dst_size - 1);
9433b54462SAlexander Graf     return false;
9533b54462SAlexander Graf }
9633b54462SAlexander Graf 
9733b54462SAlexander Graf #define set_fixlen_property_or_return(dst_array, src, errp, property_name) \
9833b54462SAlexander Graf     do { \
9933b54462SAlexander Graf         if (!set_fixlen_property_or_error((dst_array), (src), \
10033b54462SAlexander Graf                                           ARRAY_SIZE(dst_array), \
10133b54462SAlexander Graf                                           (errp), (property_name))) { \
10233b54462SAlexander Graf             return; \
10333b54462SAlexander Graf         } \
10433b54462SAlexander Graf     } while (0)
10533b54462SAlexander Graf 
vmapple_cfg_realize(DeviceState * dev,Error ** errp)10633b54462SAlexander Graf static void vmapple_cfg_realize(DeviceState *dev, Error **errp)
10733b54462SAlexander Graf {
10833b54462SAlexander Graf     VMAppleCfgState *s = VMAPPLE_CFG(dev);
10933b54462SAlexander Graf     uint32_t i;
11033b54462SAlexander Graf 
11133b54462SAlexander Graf     if (!s->serial) {
11233b54462SAlexander Graf         s->serial = g_strdup("1234");
11333b54462SAlexander Graf     }
11433b54462SAlexander Graf     if (!s->model) {
11533b54462SAlexander Graf         s->model = g_strdup("VM0001");
11633b54462SAlexander Graf     }
11733b54462SAlexander Graf     if (!s->soc_name) {
11833b54462SAlexander Graf         s->soc_name = g_strdup("Apple M1 (Virtual)");
11933b54462SAlexander Graf     }
12033b54462SAlexander Graf 
12133b54462SAlexander Graf     set_fixlen_property_or_return(s->cfg.serial, s->serial, errp, "serial");
12233b54462SAlexander Graf     set_fixlen_property_or_return(s->cfg.model, s->model, errp, "model");
12333b54462SAlexander Graf     set_fixlen_property_or_return(s->cfg.soc_name, s->soc_name, errp, "soc_name");
12433b54462SAlexander Graf     set_fixlen_property_or_return(s->cfg.unk8, "D/A", errp, "unk8");
12533b54462SAlexander Graf     s->cfg.version = 2;
12633b54462SAlexander Graf     s->cfg.unk1 = 1;
12733b54462SAlexander Graf     s->cfg.unk2 = 1;
12833b54462SAlexander Graf     s->cfg.unk3 = 0x20;
12933b54462SAlexander Graf     s->cfg.unk4 = 0;
13033b54462SAlexander Graf     s->cfg.unk5 = 1;
13133b54462SAlexander Graf     s->cfg.unk6 = 1;
13233b54462SAlexander Graf     s->cfg.unk7 = 0;
13333b54462SAlexander Graf     s->cfg.unk10 = 1;
13433b54462SAlexander Graf 
13533b54462SAlexander Graf     if (s->cfg.nr_cpus > ARRAY_SIZE(s->cfg.cpu_ids)) {
13633b54462SAlexander Graf         error_setg(errp,
13733b54462SAlexander Graf                    "Failed to create %u CPUs, vmapple machine supports %zu max",
13833b54462SAlexander Graf                    s->cfg.nr_cpus, ARRAY_SIZE(s->cfg.cpu_ids));
13933b54462SAlexander Graf         return;
14033b54462SAlexander Graf     }
14133b54462SAlexander Graf     for (i = 0; i < s->cfg.nr_cpus; i++) {
14233b54462SAlexander Graf         s->cfg.cpu_ids[i] = i;
14333b54462SAlexander Graf     }
14433b54462SAlexander Graf }
14533b54462SAlexander Graf 
vmapple_cfg_init(Object * obj)14633b54462SAlexander Graf static void vmapple_cfg_init(Object *obj)
14733b54462SAlexander Graf {
14833b54462SAlexander Graf     VMAppleCfgState *s = VMAPPLE_CFG(obj);
14933b54462SAlexander Graf 
15033b54462SAlexander Graf     memory_region_init_ram(&s->mem, obj, "VMApple Config", VMAPPLE_CFG_SIZE,
15133b54462SAlexander Graf                            &error_fatal);
15233b54462SAlexander Graf     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mem);
15333b54462SAlexander Graf }
15433b54462SAlexander Graf 
15533b54462SAlexander Graf static const Property vmapple_cfg_properties[] = {
15633b54462SAlexander Graf     DEFINE_PROP_UINT32("nr-cpus", VMAppleCfgState, cfg.nr_cpus, 1),
15733b54462SAlexander Graf     DEFINE_PROP_UINT64("ecid", VMAppleCfgState, cfg.ecid, 0),
15833b54462SAlexander Graf     DEFINE_PROP_UINT64("ram-size", VMAppleCfgState, cfg.ram_size, 0),
15933b54462SAlexander Graf     DEFINE_PROP_UINT32("run_installer1", VMAppleCfgState, cfg.run_installer1, 0),
16033b54462SAlexander Graf     DEFINE_PROP_UINT32("run_installer2", VMAppleCfgState, cfg.run_installer2, 0),
16133b54462SAlexander Graf     DEFINE_PROP_UINT32("rnd", VMAppleCfgState, cfg.rnd, 0),
16233b54462SAlexander Graf     DEFINE_PROP_MACADDR("mac-en0", VMAppleCfgState, cfg.mac_en0),
16333b54462SAlexander Graf     DEFINE_PROP_MACADDR("mac-en1", VMAppleCfgState, cfg.mac_en1),
16433b54462SAlexander Graf     DEFINE_PROP_MACADDR("mac-wifi0", VMAppleCfgState, cfg.mac_wifi0),
16533b54462SAlexander Graf     DEFINE_PROP_MACADDR("mac-bt0", VMAppleCfgState, cfg.mac_bt0),
16633b54462SAlexander Graf     DEFINE_PROP_STRING("serial", VMAppleCfgState, serial),
16733b54462SAlexander Graf     DEFINE_PROP_STRING("model", VMAppleCfgState, model),
16833b54462SAlexander Graf     DEFINE_PROP_STRING("soc_name", VMAppleCfgState, soc_name),
16933b54462SAlexander Graf };
17033b54462SAlexander Graf 
vmapple_cfg_class_init(ObjectClass * klass,const void * data)171*12d1a768SPhilippe Mathieu-Daudé static void vmapple_cfg_class_init(ObjectClass *klass, const void *data)
17233b54462SAlexander Graf {
17333b54462SAlexander Graf     DeviceClass *dc = DEVICE_CLASS(klass);
17433b54462SAlexander Graf     ResettableClass *rc = RESETTABLE_CLASS(klass);
17533b54462SAlexander Graf 
17633b54462SAlexander Graf     dc->realize = vmapple_cfg_realize;
17733b54462SAlexander Graf     dc->desc = "VMApple Configuration Region";
17833b54462SAlexander Graf     device_class_set_props(dc, vmapple_cfg_properties);
17933b54462SAlexander Graf     rc->phases.hold = vmapple_cfg_reset;
18033b54462SAlexander Graf }
18133b54462SAlexander Graf 
18233b54462SAlexander Graf static const TypeInfo vmapple_cfg_info = {
18333b54462SAlexander Graf     .name          = TYPE_VMAPPLE_CFG,
18433b54462SAlexander Graf     .parent        = TYPE_SYS_BUS_DEVICE,
18533b54462SAlexander Graf     .instance_size = sizeof(VMAppleCfgState),
18633b54462SAlexander Graf     .instance_init = vmapple_cfg_init,
18733b54462SAlexander Graf     .class_init    = vmapple_cfg_class_init,
18833b54462SAlexander Graf };
18933b54462SAlexander Graf 
vmapple_cfg_register_types(void)19033b54462SAlexander Graf static void vmapple_cfg_register_types(void)
19133b54462SAlexander Graf {
19233b54462SAlexander Graf     type_register_static(&vmapple_cfg_info);
19333b54462SAlexander Graf }
19433b54462SAlexander Graf 
19533b54462SAlexander Graf type_init(vmapple_cfg_register_types)
196