1 /* 2 * PowerMac NVRAM emulation 3 * 4 * Copyright (c) 2005-2007 Fabrice Bellard 5 * Copyright (c) 2007 Jocelyn Mayer 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "qemu/osdep.h" 27 #include "hw/nvram/chrp_nvram.h" 28 #include "hw/ppc/mac.h" 29 #include "hw/qdev-properties.h" 30 #include "migration/vmstate.h" 31 #include "qemu/cutils.h" 32 #include "qemu/module.h" 33 #include "trace.h" 34 #include <zlib.h> 35 36 #define DEF_SYSTEM_SIZE 0xc10 37 38 /* macio style NVRAM device */ 39 static void macio_nvram_writeb(void *opaque, hwaddr addr, 40 uint64_t value, unsigned size) 41 { 42 MacIONVRAMState *s = opaque; 43 44 addr = (addr >> s->it_shift) & (s->size - 1); 45 trace_macio_nvram_write(addr, value); 46 s->data[addr] = value; 47 } 48 49 static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, 50 unsigned size) 51 { 52 MacIONVRAMState *s = opaque; 53 uint32_t value; 54 55 addr = (addr >> s->it_shift) & (s->size - 1); 56 value = s->data[addr]; 57 trace_macio_nvram_read(addr, value); 58 59 return value; 60 } 61 62 static const MemoryRegionOps macio_nvram_ops = { 63 .read = macio_nvram_readb, 64 .write = macio_nvram_writeb, 65 .valid.min_access_size = 1, 66 .valid.max_access_size = 4, 67 .impl.min_access_size = 1, 68 .impl.max_access_size = 1, 69 .endianness = DEVICE_BIG_ENDIAN, 70 }; 71 72 static const VMStateDescription vmstate_macio_nvram = { 73 .name = "macio_nvram", 74 .version_id = 1, 75 .minimum_version_id = 1, 76 .fields = (VMStateField[]) { 77 VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, size), 78 VMSTATE_END_OF_LIST() 79 } 80 }; 81 82 83 static void macio_nvram_reset(DeviceState *dev) 84 { 85 } 86 87 static void macio_nvram_realizefn(DeviceState *dev, Error **errp) 88 { 89 SysBusDevice *d = SYS_BUS_DEVICE(dev); 90 MacIONVRAMState *s = MACIO_NVRAM(dev); 91 92 s->data = g_malloc0(s->size); 93 94 memory_region_init_io(&s->mem, OBJECT(s), &macio_nvram_ops, s, 95 "macio-nvram", s->size << s->it_shift); 96 sysbus_init_mmio(d, &s->mem); 97 } 98 99 static void macio_nvram_unrealizefn(DeviceState *dev) 100 { 101 MacIONVRAMState *s = MACIO_NVRAM(dev); 102 103 g_free(s->data); 104 } 105 106 static Property macio_nvram_properties[] = { 107 DEFINE_PROP_UINT32("size", MacIONVRAMState, size, 0), 108 DEFINE_PROP_UINT32("it_shift", MacIONVRAMState, it_shift, 0), 109 DEFINE_PROP_END_OF_LIST() 110 }; 111 112 static void macio_nvram_class_init(ObjectClass *oc, void *data) 113 { 114 DeviceClass *dc = DEVICE_CLASS(oc); 115 116 dc->realize = macio_nvram_realizefn; 117 dc->unrealize = macio_nvram_unrealizefn; 118 dc->reset = macio_nvram_reset; 119 dc->vmsd = &vmstate_macio_nvram; 120 device_class_set_props(dc, macio_nvram_properties); 121 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 122 } 123 124 static const TypeInfo macio_nvram_type_info = { 125 .name = TYPE_MACIO_NVRAM, 126 .parent = TYPE_SYS_BUS_DEVICE, 127 .instance_size = sizeof(MacIONVRAMState), 128 .class_init = macio_nvram_class_init, 129 }; 130 131 static void macio_nvram_register_types(void) 132 { 133 type_register_static(&macio_nvram_type_info); 134 } 135 136 /* Set up a system OpenBIOS NVRAM partition */ 137 static void pmac_format_nvram_partition_of(MacIONVRAMState *nvr, int off, 138 int len) 139 { 140 int sysp_end; 141 142 /* OpenBIOS nvram variables partition */ 143 sysp_end = chrp_nvram_create_system_partition(&nvr->data[off], 144 DEF_SYSTEM_SIZE, len) + off; 145 146 /* Free space partition */ 147 chrp_nvram_create_free_partition(&nvr->data[sysp_end], len - sysp_end); 148 } 149 150 #define OSX_NVRAM_SIGNATURE (0x5A) 151 152 /* Set up a Mac OS X NVRAM partition */ 153 static void pmac_format_nvram_partition_osx(MacIONVRAMState *nvr, int off, 154 int len) 155 { 156 uint32_t start = off; 157 ChrpNvramPartHdr *part_header; 158 unsigned char *data = &nvr->data[start]; 159 160 /* empty partition */ 161 part_header = (ChrpNvramPartHdr *)data; 162 part_header->signature = OSX_NVRAM_SIGNATURE; 163 pstrcpy(part_header->name, sizeof(part_header->name), "wwwwwwwwwwww"); 164 165 chrp_nvram_finish_partition(part_header, len); 166 167 /* Generation */ 168 stl_be_p(&data[20], 2); 169 170 /* Adler32 checksum */ 171 stl_be_p(&data[16], adler32(0, &data[20], len - 20)); 172 } 173 174 /* Set up NVRAM with OF and OSX partitions */ 175 void pmac_format_nvram_partition(MacIONVRAMState *nvr, int len) 176 { 177 /* 178 * Mac OS X expects side "B" of the flash at the second half of NVRAM, 179 * so we use half of the chip for OF and the other half for a free OSX 180 * partition. 181 */ 182 pmac_format_nvram_partition_of(nvr, 0, len / 2); 183 pmac_format_nvram_partition_osx(nvr, len / 2, len / 2); 184 } 185 type_init(macio_nvram_register_types) 186