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.
10 #include "qemu/osdep.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)
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
33 error_report_err(err
);
39 static uint64_t bcm2835_rng_read(void *opaque
, hwaddr offset
,
42 BCM2835RngState
*s
= (BCM2835RngState
*)opaque
;
48 case 0x0: /* rng_ctrl */
51 case 0x4: /* rng_status */
52 res
= s
->rng_status
| (1 << 24);
54 case 0x8: /* rng_data */
55 res
= get_random_bytes();
59 qemu_log_mask(LOG_GUEST_ERROR
,
60 "bcm2835_rng_read: Bad offset %x\n",
69 static void bcm2835_rng_write(void *opaque
, hwaddr offset
,
70 uint64_t value
, unsigned size
)
72 BCM2835RngState
*s
= (BCM2835RngState
*)opaque
;
77 case 0x0: /* rng_ctrl */
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 */
87 qemu_log_mask(LOG_GUEST_ERROR
,
88 "bcm2835_rng_write: Bad offset %x\n",
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
,
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
);
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
)