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