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 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 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 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 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 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 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