io: cope with websock 'Connection' header having multiple values
[qemu/ar7.git] / hw / misc / bcm2835_rng.c
blob4d62143b24c2269052019deb59a19f38d16a7c33
1 /*
2 * BCM2835 Random Number Generator emulation
4 * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
10 #include "qemu/osdep.h"
11 #include "qemu/log.h"
12 #include "qapi/error.h"
13 #include "crypto/random.h"
14 #include "hw/misc/bcm2835_rng.h"
16 static uint32_t get_random_bytes(void)
18 uint32_t res;
19 Error *err = NULL;
21 if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
22 /* On failure we don't want to return the guest a non-random
23 * value in case they're really using it for cryptographic
24 * purposes, so the best we can do is die here.
25 * This shouldn't happen unless something's broken.
26 * In theory we could implement this device's full FIFO
27 * and interrupt semantics and then just stop filling the
28 * FIFO. That's a lot of work, though, so we assume any
29 * errors are systematic problems and trust that if we didn't
30 * fail as the guest inited then we won't fail later on
31 * mid-run.
33 error_report_err(err);
34 exit(1);
36 return res;
39 static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
40 unsigned size)
42 BCM2835RngState *s = (BCM2835RngState *)opaque;
43 uint32_t res = 0;
45 assert(size == 4);
47 switch (offset) {
48 case 0x0: /* rng_ctrl */
49 res = s->rng_ctrl;
50 break;
51 case 0x4: /* rng_status */
52 res = s->rng_status | (1 << 24);
53 break;
54 case 0x8: /* rng_data */
55 res = get_random_bytes();
56 break;
58 default:
59 qemu_log_mask(LOG_GUEST_ERROR,
60 "bcm2835_rng_read: Bad offset %x\n",
61 (int)offset);
62 res = 0;
63 break;
66 return res;
69 static void bcm2835_rng_write(void *opaque, hwaddr offset,
70 uint64_t value, unsigned size)
72 BCM2835RngState *s = (BCM2835RngState *)opaque;
74 assert(size == 4);
76 switch (offset) {
77 case 0x0: /* rng_ctrl */
78 s->rng_ctrl = value;
79 break;
80 case 0x4: /* rng_status */
81 /* we shouldn't let the guest write to bits [31..20] */
82 s->rng_status &= ~0xFFFFF; /* clear 20 lower bits */
83 s->rng_status |= value & 0xFFFFF; /* set them to new value */
84 break;
86 default:
87 qemu_log_mask(LOG_GUEST_ERROR,
88 "bcm2835_rng_write: Bad offset %x\n",
89 (int)offset);
90 break;
94 static const MemoryRegionOps bcm2835_rng_ops = {
95 .read = bcm2835_rng_read,
96 .write = bcm2835_rng_write,
97 .endianness = DEVICE_NATIVE_ENDIAN,
100 static const VMStateDescription vmstate_bcm2835_rng = {
101 .name = TYPE_BCM2835_RNG,
102 .version_id = 1,
103 .minimum_version_id = 1,
104 .fields = (VMStateField[]) {
105 VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
106 VMSTATE_UINT32(rng_status, BCM2835RngState),
107 VMSTATE_END_OF_LIST()
111 static void bcm2835_rng_init(Object *obj)
113 BCM2835RngState *s = BCM2835_RNG(obj);
115 memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
116 TYPE_BCM2835_RNG, 0x10);
117 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
120 static void bcm2835_rng_reset(DeviceState *dev)
122 BCM2835RngState *s = BCM2835_RNG(dev);
124 s->rng_ctrl = 0;
125 s->rng_status = 0;
128 static void bcm2835_rng_class_init(ObjectClass *klass, void *data)
130 DeviceClass *dc = DEVICE_CLASS(klass);
132 dc->reset = bcm2835_rng_reset;
133 dc->vmsd = &vmstate_bcm2835_rng;
136 static TypeInfo bcm2835_rng_info = {
137 .name = TYPE_BCM2835_RNG,
138 .parent = TYPE_SYS_BUS_DEVICE,
139 .instance_size = sizeof(BCM2835RngState),
140 .class_init = bcm2835_rng_class_init,
141 .instance_init = bcm2835_rng_init,
144 static void bcm2835_rng_register_types(void)
146 type_register_static(&bcm2835_rng_info);
149 type_init(bcm2835_rng_register_types)