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 "qemu/guest-random.h"
13 #include "qemu/module.h"
14 #include "hw/misc/bcm2835_rng.h"
15 #include "migration/vmstate.h"
17 static uint32_t get_random_bytes(void)
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 qemu_guest_getrandom_nofail(&res
, sizeof(res
));
37 static uint64_t bcm2835_rng_read(void *opaque
, hwaddr offset
,
40 BCM2835RngState
*s
= (BCM2835RngState
*)opaque
;
46 case 0x0: /* rng_ctrl */
49 case 0x4: /* rng_status */
50 res
= s
->rng_status
| (1 << 24);
52 case 0x8: /* rng_data */
53 res
= get_random_bytes();
57 qemu_log_mask(LOG_GUEST_ERROR
,
58 "bcm2835_rng_read: Bad offset %x\n",
67 static void bcm2835_rng_write(void *opaque
, hwaddr offset
,
68 uint64_t value
, unsigned size
)
70 BCM2835RngState
*s
= (BCM2835RngState
*)opaque
;
75 case 0x0: /* rng_ctrl */
78 case 0x4: /* rng_status */
79 /* we shouldn't let the guest write to bits [31..20] */
80 s
->rng_status
&= ~0xFFFFF; /* clear 20 lower bits */
81 s
->rng_status
|= value
& 0xFFFFF; /* set them to new value */
85 qemu_log_mask(LOG_GUEST_ERROR
,
86 "bcm2835_rng_write: Bad offset %x\n",
92 static const MemoryRegionOps bcm2835_rng_ops
= {
93 .read
= bcm2835_rng_read
,
94 .write
= bcm2835_rng_write
,
95 .endianness
= DEVICE_NATIVE_ENDIAN
,
98 static const VMStateDescription vmstate_bcm2835_rng
= {
99 .name
= TYPE_BCM2835_RNG
,
101 .minimum_version_id
= 1,
102 .fields
= (VMStateField
[]) {
103 VMSTATE_UINT32(rng_ctrl
, BCM2835RngState
),
104 VMSTATE_UINT32(rng_status
, BCM2835RngState
),
105 VMSTATE_END_OF_LIST()
109 static void bcm2835_rng_init(Object
*obj
)
111 BCM2835RngState
*s
= BCM2835_RNG(obj
);
113 memory_region_init_io(&s
->iomem
, obj
, &bcm2835_rng_ops
, s
,
114 TYPE_BCM2835_RNG
, 0x10);
115 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->iomem
);
118 static void bcm2835_rng_reset(DeviceState
*dev
)
120 BCM2835RngState
*s
= BCM2835_RNG(dev
);
126 static void bcm2835_rng_class_init(ObjectClass
*klass
, void *data
)
128 DeviceClass
*dc
= DEVICE_CLASS(klass
);
130 dc
->reset
= bcm2835_rng_reset
;
131 dc
->vmsd
= &vmstate_bcm2835_rng
;
134 static const TypeInfo bcm2835_rng_info
= {
135 .name
= TYPE_BCM2835_RNG
,
136 .parent
= TYPE_SYS_BUS_DEVICE
,
137 .instance_size
= sizeof(BCM2835RngState
),
138 .class_init
= bcm2835_rng_class_init
,
139 .instance_init
= bcm2835_rng_init
,
142 static void bcm2835_rng_register_types(void)
144 type_register_static(&bcm2835_rng_info
);
147 type_init(bcm2835_rng_register_types
)