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