mac_nvram.c 5.7 KB
Newer Older
J
j_mayer 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * PowerMac NVRAM emulation
 *
 * Copyright (c) 2005-2007 Fabrice Bellard
 * Copyright (c) 2007 Jocelyn Mayer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
25
#include "hw/hw.h"
P
Paolo Bonzini 已提交
26
#include "hw/sparc/firmware_abi.h"
27
#include "sysemu/sysemu.h"
28
#include "hw/ppc/mac.h"
J
j_mayer 已提交
29

B
blueswir1 已提交
30 31 32 33
/* debug NVR */
//#define DEBUG_NVR

#ifdef DEBUG_NVR
34 35
#define NVR_DPRINTF(fmt, ...)                                   \
    do { printf("NVR: " fmt , ## __VA_ARGS__); } while (0)
B
blueswir1 已提交
36
#else
37
#define NVR_DPRINTF(fmt, ...)
B
blueswir1 已提交
38 39
#endif

40 41
#define DEF_SYSTEM_SIZE 0xc10

J
j_mayer 已提交
42
/* Direct access to NVRAM */
A
Andreas Färber 已提交
43
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr)
J
j_mayer 已提交
44 45 46
{
    uint32_t ret;

A
Andreas Färber 已提交
47
    if (addr < s->size) {
J
j_mayer 已提交
48
        ret = s->data[addr];
A
Andreas Färber 已提交
49
    } else {
J
j_mayer 已提交
50
        ret = -1;
A
Andreas Färber 已提交
51 52
    }
    NVR_DPRINTF("read addr %04" PRIx32 " val %" PRIx8 "\n", addr, ret);
J
j_mayer 已提交
53 54 55 56

    return ret;
}

A
Andreas Färber 已提交
57
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val)
J
j_mayer 已提交
58
{
A
Andreas Färber 已提交
59 60
    NVR_DPRINTF("write addr %04" PRIx32 " val %" PRIx8 "\n", addr, val);
    if (addr < s->size) {
J
j_mayer 已提交
61
        s->data[addr] = val;
A
Andreas Färber 已提交
62
    }
J
j_mayer 已提交
63 64 65
}

/* macio style NVRAM device */
A
Avi Kivity 已提交
66
static void macio_nvram_writeb(void *opaque, hwaddr addr,
A
Avi Kivity 已提交
67
                               uint64_t value, unsigned size)
J
j_mayer 已提交
68 69
{
    MacIONVRAMState *s = opaque;
J
j_mayer 已提交
70

B
blueswir1 已提交
71
    addr = (addr >> s->it_shift) & (s->size - 1);
J
j_mayer 已提交
72
    s->data[addr] = value;
A
Andreas Färber 已提交
73
    NVR_DPRINTF("writeb addr %04" PHYS_PRIx " val %" PRIx64 "\n", addr, value);
J
j_mayer 已提交
74 75
}

A
Avi Kivity 已提交
76
static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
A
Avi Kivity 已提交
77
                                  unsigned size)
J
j_mayer 已提交
78 79 80 81
{
    MacIONVRAMState *s = opaque;
    uint32_t value;

B
blueswir1 已提交
82
    addr = (addr >> s->it_shift) & (s->size - 1);
J
j_mayer 已提交
83
    value = s->data[addr];
B
blueswir1 已提交
84
    NVR_DPRINTF("readb addr %04x val %x\n", (int)addr, value);
J
j_mayer 已提交
85 86 87 88

    return value;
}

A
Avi Kivity 已提交
89 90 91
static const MemoryRegionOps macio_nvram_ops = {
    .read = macio_nvram_readb,
    .write = macio_nvram_writeb,
A
Andreas Färber 已提交
92
    .endianness = DEVICE_BIG_ENDIAN,
J
j_mayer 已提交
93 94
};

J
Juan Quintela 已提交
95 96 97 98 99 100 101 102 103 104
static const VMStateDescription vmstate_macio_nvram = {
    .name = "macio_nvram",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields      = (VMStateField[]) {
        VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, 0, size),
        VMSTATE_END_OF_LIST()
    }
};
B
blueswir1 已提交
105 106


A
Andreas Färber 已提交
107
static void macio_nvram_reset(DeviceState *dev)
B
blueswir1 已提交
108 109 110
{
}

A
Andreas Färber 已提交
111
static void macio_nvram_realizefn(DeviceState *dev, Error **errp)
J
j_mayer 已提交
112
{
A
Andreas Färber 已提交
113 114
    SysBusDevice *d = SYS_BUS_DEVICE(dev);
    MacIONVRAMState *s = MACIO_NVRAM(dev);
J
j_mayer 已提交
115

A
Andreas Färber 已提交
116
    s->data = g_malloc0(s->size);
A
aurel32 已提交
117

A
Avi Kivity 已提交
118
    memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram",
A
Andreas Färber 已提交
119 120 121 122 123 124 125 126 127 128
                          s->size << s->it_shift);
    sysbus_init_mmio(d, &s->mem);
}

static void macio_nvram_unrealizefn(DeviceState *dev, Error **errp)
{
    MacIONVRAMState *s = MACIO_NVRAM(dev);

    g_free(s->data);
}
J
j_mayer 已提交
129

A
Andreas Färber 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
static Property macio_nvram_properties[] = {
    DEFINE_PROP_UINT32("size", MacIONVRAMState, size, 0),
    DEFINE_PROP_UINT32("it_shift", MacIONVRAMState, it_shift, 0),
    DEFINE_PROP_END_OF_LIST()
};

static void macio_nvram_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = macio_nvram_realizefn;
    dc->unrealize = macio_nvram_unrealizefn;
    dc->reset = macio_nvram_reset;
    dc->vmsd = &vmstate_macio_nvram;
    dc->props = macio_nvram_properties;
J
j_mayer 已提交
145 146
}

A
Andreas Färber 已提交
147 148 149 150 151 152 153 154
static const TypeInfo macio_nvram_type_info = {
    .name = TYPE_MACIO_NVRAM,
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(MacIONVRAMState),
    .class_init = macio_nvram_class_init,
};

static void macio_nvram_register_types(void)
J
j_mayer 已提交
155
{
A
Andreas Färber 已提交
156
    type_register_static(&macio_nvram_type_info);
J
j_mayer 已提交
157 158
}

159
/* Set up a system OpenBIOS NVRAM partition */
J
j_mayer 已提交
160 161
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
{
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    unsigned int i;
    uint32_t start = 0, end;
    struct OpenBIOS_nvpart_v1 *part_header;

    // OpenBIOS nvram variables
    // Variable partition
    part_header = (struct OpenBIOS_nvpart_v1 *)nvr->data;
    part_header->signature = OPENBIOS_PART_SYSTEM;
    pstrcpy(part_header->name, sizeof(part_header->name), "system");

    end = start + sizeof(struct OpenBIOS_nvpart_v1);
    for (i = 0; i < nb_prom_envs; i++)
        end = OpenBIOS_set_var(nvr->data, end, prom_envs[i]);

    // End marker
    nvr->data[end++] = '\0';

    end = start + ((end - start + 15) & ~15);
180 181 182 183
    /* XXX: OpenBIOS is not able to grow up a partition. Leave some space for
       new variables. */
    if (end < DEF_SYSTEM_SIZE)
        end = DEF_SYSTEM_SIZE;
184 185 186 187 188 189 190 191 192 193
    OpenBIOS_finish_partition(part_header, end - start);

    // free partition
    start = end;
    part_header = (struct OpenBIOS_nvpart_v1 *)&nvr->data[start];
    part_header->signature = OPENBIOS_PART_FREE;
    pstrcpy(part_header->name, sizeof(part_header->name), "free");

    end = len;
    OpenBIOS_finish_partition(part_header, end - start);
J
j_mayer 已提交
194
}
A
Andreas Färber 已提交
195 196

type_init(macio_nvram_register_types)