Statistics
| Branch: | Revision:

root / hw / nvram / mac_nvram.c @ ec0503b4

History | View | Annotate | Download (5.7 kB)

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
#include "hw/hw.h"
26
#include "hw/nvram/openbios_firmware_abi.h"
27
#include "sysemu/sysemu.h"
28
#include "hw/ppc/mac.h"
29

    
30
/* debug NVR */
31
//#define DEBUG_NVR
32

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

    
40
#define DEF_SYSTEM_SIZE 0xc10
41

    
42
/* Direct access to NVRAM */
43
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr)
44
{
45
    uint32_t ret;
46

    
47
    if (addr < s->size) {
48
        ret = s->data[addr];
49
    } else {
50
        ret = -1;
51
    }
52
    NVR_DPRINTF("read addr %04" PRIx32 " val %" PRIx8 "\n", addr, ret);
53

    
54
    return ret;
55
}
56

    
57
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val)
58
{
59
    NVR_DPRINTF("write addr %04" PRIx32 " val %" PRIx8 "\n", addr, val);
60
    if (addr < s->size) {
61
        s->data[addr] = val;
62
    }
63
}
64

    
65
/* macio style NVRAM device */
66
static void macio_nvram_writeb(void *opaque, hwaddr addr,
67
                               uint64_t value, unsigned size)
68
{
69
    MacIONVRAMState *s = opaque;
70

    
71
    addr = (addr >> s->it_shift) & (s->size - 1);
72
    s->data[addr] = value;
73
    NVR_DPRINTF("writeb addr %04" PHYS_PRIx " val %" PRIx64 "\n", addr, value);
74
}
75

    
76
static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
77
                                  unsigned size)
78
{
79
    MacIONVRAMState *s = opaque;
80
    uint32_t value;
81

    
82
    addr = (addr >> s->it_shift) & (s->size - 1);
83
    value = s->data[addr];
84
    NVR_DPRINTF("readb addr %04x val %x\n", (int)addr, value);
85

    
86
    return value;
87
}
88

    
89
static const MemoryRegionOps macio_nvram_ops = {
90
    .read = macio_nvram_readb,
91
    .write = macio_nvram_writeb,
92
    .endianness = DEVICE_BIG_ENDIAN,
93
};
94

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

    
106

    
107
static void macio_nvram_reset(DeviceState *dev)
108
{
109
}
110

    
111
static void macio_nvram_realizefn(DeviceState *dev, Error **errp)
112
{
113
    SysBusDevice *d = SYS_BUS_DEVICE(dev);
114
    MacIONVRAMState *s = MACIO_NVRAM(dev);
115

    
116
    s->data = g_malloc0(s->size);
117

    
118
    memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram",
119
                          s->size << s->it_shift);
120
    sysbus_init_mmio(d, &s->mem);
121
}
122

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

    
127
    g_free(s->data);
128
}
129

    
130
static Property macio_nvram_properties[] = {
131
    DEFINE_PROP_UINT32("size", MacIONVRAMState, size, 0),
132
    DEFINE_PROP_UINT32("it_shift", MacIONVRAMState, it_shift, 0),
133
    DEFINE_PROP_END_OF_LIST()
134
};
135

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

    
140
    dc->realize = macio_nvram_realizefn;
141
    dc->unrealize = macio_nvram_unrealizefn;
142
    dc->reset = macio_nvram_reset;
143
    dc->vmsd = &vmstate_macio_nvram;
144
    dc->props = macio_nvram_properties;
145
}
146

    
147
static const TypeInfo macio_nvram_type_info = {
148
    .name = TYPE_MACIO_NVRAM,
149
    .parent = TYPE_SYS_BUS_DEVICE,
150
    .instance_size = sizeof(MacIONVRAMState),
151
    .class_init = macio_nvram_class_init,
152
};
153

    
154
static void macio_nvram_register_types(void)
155
{
156
    type_register_static(&macio_nvram_type_info);
157
}
158

    
159
/* Set up a system OpenBIOS NVRAM partition */
160
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
161
{
162
    unsigned int i;
163
    uint32_t start = 0, end;
164
    struct OpenBIOS_nvpart_v1 *part_header;
165

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

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

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

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

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

    
192
    end = len;
193
    OpenBIOS_finish_partition(part_header, end - start);
194
}
195

    
196
type_init(macio_nvram_register_types)