xref: /qemu/hw/misc/aspeed_sbc.c (revision c2651cf45dd3ac5674bc720d2303668f0905507d)
1e1acf581SJoel Stanley /*
2e1acf581SJoel Stanley  * ASPEED Secure Boot Controller
3e1acf581SJoel Stanley  *
4e1acf581SJoel Stanley  * Copyright (C) 2021-2022 IBM Corp.
5e1acf581SJoel Stanley  *
6e1acf581SJoel Stanley  * Joel Stanley <joel@jms.id.au>
7e1acf581SJoel Stanley  *
8e1acf581SJoel Stanley  * SPDX-License-Identifier: GPL-2.0-or-later
9e1acf581SJoel Stanley  */
10e1acf581SJoel Stanley 
11e1acf581SJoel Stanley #include "qemu/osdep.h"
12e1acf581SJoel Stanley #include "qemu/log.h"
13e1acf581SJoel Stanley #include "qemu/error-report.h"
14e1acf581SJoel Stanley #include "hw/misc/aspeed_sbc.h"
15e1acf581SJoel Stanley #include "qapi/error.h"
16e1acf581SJoel Stanley #include "migration/vmstate.h"
17e1acf581SJoel Stanley 
18e1acf581SJoel Stanley #define R_PROT          (0x000 / 4)
19e1acf581SJoel Stanley #define R_STATUS        (0x014 / 4)
20*c2651cf4SJoel Stanley #define R_QSR           (0x040 / 4)
21e1acf581SJoel Stanley 
22e1acf581SJoel Stanley static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size)
23e1acf581SJoel Stanley {
24e1acf581SJoel Stanley     AspeedSBCState *s = ASPEED_SBC(opaque);
25e1acf581SJoel Stanley 
26e1acf581SJoel Stanley     addr >>= 2;
27e1acf581SJoel Stanley 
28e1acf581SJoel Stanley     if (addr >= ASPEED_SBC_NR_REGS) {
29e1acf581SJoel Stanley         qemu_log_mask(LOG_GUEST_ERROR,
30e1acf581SJoel Stanley                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
31e1acf581SJoel Stanley                       __func__, addr << 2);
32e1acf581SJoel Stanley         return 0;
33e1acf581SJoel Stanley     }
34e1acf581SJoel Stanley 
35e1acf581SJoel Stanley     return s->regs[addr];
36e1acf581SJoel Stanley }
37e1acf581SJoel Stanley 
38e1acf581SJoel Stanley static void aspeed_sbc_write(void *opaque, hwaddr addr, uint64_t data,
39e1acf581SJoel Stanley                               unsigned int size)
40e1acf581SJoel Stanley {
41e1acf581SJoel Stanley     AspeedSBCState *s = ASPEED_SBC(opaque);
42e1acf581SJoel Stanley 
43e1acf581SJoel Stanley     addr >>= 2;
44e1acf581SJoel Stanley 
45e1acf581SJoel Stanley     if (addr >= ASPEED_SBC_NR_REGS) {
46e1acf581SJoel Stanley         qemu_log_mask(LOG_GUEST_ERROR,
47e1acf581SJoel Stanley                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
48e1acf581SJoel Stanley                       __func__, addr << 2);
49e1acf581SJoel Stanley         return;
50e1acf581SJoel Stanley     }
51e1acf581SJoel Stanley 
52e1acf581SJoel Stanley     switch (addr) {
53e1acf581SJoel Stanley     case R_STATUS:
54*c2651cf4SJoel Stanley     case R_QSR:
55e1acf581SJoel Stanley         qemu_log_mask(LOG_GUEST_ERROR,
56e1acf581SJoel Stanley                       "%s: write to read only register 0x%" HWADDR_PRIx "\n",
57e1acf581SJoel Stanley                       __func__, addr << 2);
58e1acf581SJoel Stanley         return;
59e1acf581SJoel Stanley     default:
60e1acf581SJoel Stanley         break;
61e1acf581SJoel Stanley     }
62e1acf581SJoel Stanley 
63e1acf581SJoel Stanley     s->regs[addr] = data;
64e1acf581SJoel Stanley }
65e1acf581SJoel Stanley 
66e1acf581SJoel Stanley static const MemoryRegionOps aspeed_sbc_ops = {
67e1acf581SJoel Stanley     .read = aspeed_sbc_read,
68e1acf581SJoel Stanley     .write = aspeed_sbc_write,
69e1acf581SJoel Stanley     .endianness = DEVICE_LITTLE_ENDIAN,
70e1acf581SJoel Stanley     .valid = {
71e1acf581SJoel Stanley         .min_access_size = 1,
72e1acf581SJoel Stanley         .max_access_size = 4,
73e1acf581SJoel Stanley     },
74e1acf581SJoel Stanley };
75e1acf581SJoel Stanley 
76e1acf581SJoel Stanley static void aspeed_sbc_reset(DeviceState *dev)
77e1acf581SJoel Stanley {
78e1acf581SJoel Stanley     struct AspeedSBCState *s = ASPEED_SBC(dev);
79e1acf581SJoel Stanley 
80e1acf581SJoel Stanley     memset(s->regs, 0, sizeof(s->regs));
81e1acf581SJoel Stanley 
82*c2651cf4SJoel Stanley     /* Set secure boot enabled with RSA4096_SHA256 and enable eMMC ABR */
83*c2651cf4SJoel Stanley     s->regs[R_STATUS] = 0x000044C6;
84*c2651cf4SJoel Stanley     s->regs[R_QSR] = 0x07C07C89;
85e1acf581SJoel Stanley }
86e1acf581SJoel Stanley 
87e1acf581SJoel Stanley static void aspeed_sbc_realize(DeviceState *dev, Error **errp)
88e1acf581SJoel Stanley {
89e1acf581SJoel Stanley     AspeedSBCState *s = ASPEED_SBC(dev);
90e1acf581SJoel Stanley     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
91e1acf581SJoel Stanley 
92e1acf581SJoel Stanley     memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sbc_ops, s,
93e1acf581SJoel Stanley             TYPE_ASPEED_SBC, 0x1000);
94e1acf581SJoel Stanley 
95e1acf581SJoel Stanley     sysbus_init_mmio(sbd, &s->iomem);
96e1acf581SJoel Stanley }
97e1acf581SJoel Stanley 
98e1acf581SJoel Stanley static const VMStateDescription vmstate_aspeed_sbc = {
99e1acf581SJoel Stanley     .name = TYPE_ASPEED_SBC,
100e1acf581SJoel Stanley     .version_id = 1,
101e1acf581SJoel Stanley     .minimum_version_id = 1,
102e1acf581SJoel Stanley     .fields = (VMStateField[]) {
103e1acf581SJoel Stanley         VMSTATE_UINT32_ARRAY(regs, AspeedSBCState, ASPEED_SBC_NR_REGS),
104e1acf581SJoel Stanley         VMSTATE_END_OF_LIST(),
105e1acf581SJoel Stanley     }
106e1acf581SJoel Stanley };
107e1acf581SJoel Stanley 
108e1acf581SJoel Stanley static void aspeed_sbc_class_init(ObjectClass *klass, void *data)
109e1acf581SJoel Stanley {
110e1acf581SJoel Stanley     DeviceClass *dc = DEVICE_CLASS(klass);
111e1acf581SJoel Stanley 
112e1acf581SJoel Stanley     dc->realize = aspeed_sbc_realize;
113e1acf581SJoel Stanley     dc->reset = aspeed_sbc_reset;
114e1acf581SJoel Stanley     dc->vmsd = &vmstate_aspeed_sbc;
115e1acf581SJoel Stanley }
116e1acf581SJoel Stanley 
117e1acf581SJoel Stanley static const TypeInfo aspeed_sbc_info = {
118e1acf581SJoel Stanley     .name = TYPE_ASPEED_SBC,
119e1acf581SJoel Stanley     .parent = TYPE_SYS_BUS_DEVICE,
120e1acf581SJoel Stanley     .instance_size = sizeof(AspeedSBCState),
121e1acf581SJoel Stanley     .class_init = aspeed_sbc_class_init,
122e1acf581SJoel Stanley     .class_size = sizeof(AspeedSBCClass)
123e1acf581SJoel Stanley };
124e1acf581SJoel Stanley 
125e1acf581SJoel Stanley static void aspeed_ast2600_sbc_class_init(ObjectClass *klass, void *data)
126e1acf581SJoel Stanley {
127e1acf581SJoel Stanley     DeviceClass *dc = DEVICE_CLASS(klass);
128e1acf581SJoel Stanley 
129e1acf581SJoel Stanley     dc->desc = "AST2600 Secure Boot Controller";
130e1acf581SJoel Stanley }
131e1acf581SJoel Stanley 
132e1acf581SJoel Stanley static const TypeInfo aspeed_ast2600_sbc_info = {
133e1acf581SJoel Stanley     .name = TYPE_ASPEED_AST2600_SBC,
134e1acf581SJoel Stanley     .parent = TYPE_ASPEED_SBC,
135e1acf581SJoel Stanley     .class_init = aspeed_ast2600_sbc_class_init,
136e1acf581SJoel Stanley };
137e1acf581SJoel Stanley 
138e1acf581SJoel Stanley static void aspeed_sbc_register_types(void)
139e1acf581SJoel Stanley {
140e1acf581SJoel Stanley     type_register_static(&aspeed_ast2600_sbc_info);
141e1acf581SJoel Stanley     type_register_static(&aspeed_sbc_info);
142e1acf581SJoel Stanley }
143e1acf581SJoel Stanley 
144e1acf581SJoel Stanley type_init(aspeed_sbc_register_types);
145