xref: /openbmc/qemu/hw/misc/aspeed_sbc.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
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"
1454ee5641SJoel Stanley #include "hw/qdev-properties.h"
15e1acf581SJoel Stanley #include "hw/misc/aspeed_sbc.h"
16e1acf581SJoel Stanley #include "qapi/error.h"
17e1acf581SJoel Stanley #include "migration/vmstate.h"
18e1acf581SJoel Stanley 
19e1acf581SJoel Stanley #define R_PROT          (0x000 / 4)
20e1acf581SJoel Stanley #define R_STATUS        (0x014 / 4)
21c2651cf4SJoel Stanley #define R_QSR           (0x040 / 4)
22e1acf581SJoel Stanley 
2354ee5641SJoel Stanley /* R_STATUS */
2454ee5641SJoel Stanley #define ABR_EN                  BIT(14) /* Mirrors SCU510[11] */
2554ee5641SJoel Stanley #define ABR_IMAGE_SOURCE        BIT(13)
2654ee5641SJoel Stanley #define SPI_ABR_IMAGE_SOURCE    BIT(12)
2754ee5641SJoel Stanley #define SB_CRYPTO_KEY_EXP_DONE  BIT(11)
2854ee5641SJoel Stanley #define SB_CRYPTO_BUSY          BIT(10)
2954ee5641SJoel Stanley #define OTP_WP_EN               BIT(9)
3054ee5641SJoel Stanley #define OTP_ADDR_WP_EN          BIT(8)
3154ee5641SJoel Stanley #define LOW_SEC_KEY_EN          BIT(7)
3254ee5641SJoel Stanley #define SECURE_BOOT_EN          BIT(6)
3354ee5641SJoel Stanley #define UART_BOOT_EN            BIT(5)
3454ee5641SJoel Stanley /* bit 4 reserved*/
3554ee5641SJoel Stanley #define OTP_CHARGE_PUMP_READY   BIT(3)
3654ee5641SJoel Stanley #define OTP_IDLE                BIT(2)
3754ee5641SJoel Stanley #define OTP_MEM_IDLE            BIT(1)
3854ee5641SJoel Stanley #define OTP_COMPARE_STATUS      BIT(0)
3954ee5641SJoel Stanley 
4054ee5641SJoel Stanley /* QSR */
4154ee5641SJoel Stanley #define QSR_RSA_MASK           (0x3 << 12)
4254ee5641SJoel Stanley #define QSR_HASH_MASK          (0x3 << 10)
4354ee5641SJoel Stanley 
aspeed_sbc_read(void * opaque,hwaddr addr,unsigned int size)44e1acf581SJoel Stanley static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size)
45e1acf581SJoel Stanley {
46e1acf581SJoel Stanley     AspeedSBCState *s = ASPEED_SBC(opaque);
47e1acf581SJoel Stanley 
48e1acf581SJoel Stanley     addr >>= 2;
49e1acf581SJoel Stanley 
50e1acf581SJoel Stanley     if (addr >= ASPEED_SBC_NR_REGS) {
51e1acf581SJoel Stanley         qemu_log_mask(LOG_GUEST_ERROR,
52e1acf581SJoel Stanley                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
53e1acf581SJoel Stanley                       __func__, addr << 2);
54e1acf581SJoel Stanley         return 0;
55e1acf581SJoel Stanley     }
56e1acf581SJoel Stanley 
57e1acf581SJoel Stanley     return s->regs[addr];
58e1acf581SJoel Stanley }
59e1acf581SJoel Stanley 
aspeed_sbc_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)60e1acf581SJoel Stanley static void aspeed_sbc_write(void *opaque, hwaddr addr, uint64_t data,
61e1acf581SJoel Stanley                               unsigned int size)
62e1acf581SJoel Stanley {
63e1acf581SJoel Stanley     AspeedSBCState *s = ASPEED_SBC(opaque);
64e1acf581SJoel Stanley 
65e1acf581SJoel Stanley     addr >>= 2;
66e1acf581SJoel Stanley 
67e1acf581SJoel Stanley     if (addr >= ASPEED_SBC_NR_REGS) {
68e1acf581SJoel Stanley         qemu_log_mask(LOG_GUEST_ERROR,
69e1acf581SJoel Stanley                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
70e1acf581SJoel Stanley                       __func__, addr << 2);
71e1acf581SJoel Stanley         return;
72e1acf581SJoel Stanley     }
73e1acf581SJoel Stanley 
74e1acf581SJoel Stanley     switch (addr) {
75e1acf581SJoel Stanley     case R_STATUS:
76c2651cf4SJoel Stanley     case R_QSR:
77e1acf581SJoel Stanley         qemu_log_mask(LOG_GUEST_ERROR,
78e1acf581SJoel Stanley                       "%s: write to read only register 0x%" HWADDR_PRIx "\n",
79e1acf581SJoel Stanley                       __func__, addr << 2);
80e1acf581SJoel Stanley         return;
81e1acf581SJoel Stanley     default:
82e1acf581SJoel Stanley         break;
83e1acf581SJoel Stanley     }
84e1acf581SJoel Stanley 
85e1acf581SJoel Stanley     s->regs[addr] = data;
86e1acf581SJoel Stanley }
87e1acf581SJoel Stanley 
88e1acf581SJoel Stanley static const MemoryRegionOps aspeed_sbc_ops = {
89e1acf581SJoel Stanley     .read = aspeed_sbc_read,
90e1acf581SJoel Stanley     .write = aspeed_sbc_write,
91e1acf581SJoel Stanley     .endianness = DEVICE_LITTLE_ENDIAN,
92e1acf581SJoel Stanley     .valid = {
93e1acf581SJoel Stanley         .min_access_size = 1,
94e1acf581SJoel Stanley         .max_access_size = 4,
95e1acf581SJoel Stanley     },
96e1acf581SJoel Stanley };
97e1acf581SJoel Stanley 
aspeed_sbc_reset(DeviceState * dev)98e1acf581SJoel Stanley static void aspeed_sbc_reset(DeviceState *dev)
99e1acf581SJoel Stanley {
100e1acf581SJoel Stanley     struct AspeedSBCState *s = ASPEED_SBC(dev);
101e1acf581SJoel Stanley 
102e1acf581SJoel Stanley     memset(s->regs, 0, sizeof(s->regs));
103e1acf581SJoel Stanley 
104c2651cf4SJoel Stanley     /* Set secure boot enabled with RSA4096_SHA256 and enable eMMC ABR */
10554ee5641SJoel Stanley     s->regs[R_STATUS] = OTP_IDLE | OTP_MEM_IDLE;
10654ee5641SJoel Stanley 
10754ee5641SJoel Stanley     if (s->emmc_abr) {
10854ee5641SJoel Stanley         s->regs[R_STATUS] &= ABR_EN;
10954ee5641SJoel Stanley     }
11054ee5641SJoel Stanley 
11154ee5641SJoel Stanley     if (s->signing_settings) {
11254ee5641SJoel Stanley         s->regs[R_STATUS] &= SECURE_BOOT_EN;
11354ee5641SJoel Stanley     }
11454ee5641SJoel Stanley 
11554ee5641SJoel Stanley     s->regs[R_QSR] = s->signing_settings;
116e1acf581SJoel Stanley }
117e1acf581SJoel Stanley 
aspeed_sbc_realize(DeviceState * dev,Error ** errp)118e1acf581SJoel Stanley static void aspeed_sbc_realize(DeviceState *dev, Error **errp)
119e1acf581SJoel Stanley {
120e1acf581SJoel Stanley     AspeedSBCState *s = ASPEED_SBC(dev);
121e1acf581SJoel Stanley     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
122e1acf581SJoel Stanley 
123e1acf581SJoel Stanley     memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sbc_ops, s,
124e1acf581SJoel Stanley             TYPE_ASPEED_SBC, 0x1000);
125e1acf581SJoel Stanley 
126e1acf581SJoel Stanley     sysbus_init_mmio(sbd, &s->iomem);
127e1acf581SJoel Stanley }
128e1acf581SJoel Stanley 
129e1acf581SJoel Stanley static const VMStateDescription vmstate_aspeed_sbc = {
130e1acf581SJoel Stanley     .name = TYPE_ASPEED_SBC,
131e1acf581SJoel Stanley     .version_id = 1,
132e1acf581SJoel Stanley     .minimum_version_id = 1,
133e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
134e1acf581SJoel Stanley         VMSTATE_UINT32_ARRAY(regs, AspeedSBCState, ASPEED_SBC_NR_REGS),
135e1acf581SJoel Stanley         VMSTATE_END_OF_LIST(),
136e1acf581SJoel Stanley     }
137e1acf581SJoel Stanley };
138e1acf581SJoel Stanley 
13954ee5641SJoel Stanley static Property aspeed_sbc_properties[] = {
14054ee5641SJoel Stanley     DEFINE_PROP_BOOL("emmc-abr", AspeedSBCState, emmc_abr, 0),
14154ee5641SJoel Stanley     DEFINE_PROP_UINT32("signing-settings", AspeedSBCState, signing_settings, 0),
14254ee5641SJoel Stanley     DEFINE_PROP_END_OF_LIST(),
14354ee5641SJoel Stanley };
14454ee5641SJoel Stanley 
aspeed_sbc_class_init(ObjectClass * klass,void * data)145e1acf581SJoel Stanley static void aspeed_sbc_class_init(ObjectClass *klass, void *data)
146e1acf581SJoel Stanley {
147e1acf581SJoel Stanley     DeviceClass *dc = DEVICE_CLASS(klass);
148e1acf581SJoel Stanley 
149e1acf581SJoel Stanley     dc->realize = aspeed_sbc_realize;
150*e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, aspeed_sbc_reset);
151e1acf581SJoel Stanley     dc->vmsd = &vmstate_aspeed_sbc;
15254ee5641SJoel Stanley     device_class_set_props(dc, aspeed_sbc_properties);
153e1acf581SJoel Stanley }
154e1acf581SJoel Stanley 
155e1acf581SJoel Stanley static const TypeInfo aspeed_sbc_info = {
156e1acf581SJoel Stanley     .name = TYPE_ASPEED_SBC,
157e1acf581SJoel Stanley     .parent = TYPE_SYS_BUS_DEVICE,
158e1acf581SJoel Stanley     .instance_size = sizeof(AspeedSBCState),
159e1acf581SJoel Stanley     .class_init = aspeed_sbc_class_init,
160e1acf581SJoel Stanley     .class_size = sizeof(AspeedSBCClass)
161e1acf581SJoel Stanley };
162e1acf581SJoel Stanley 
aspeed_ast2600_sbc_class_init(ObjectClass * klass,void * data)163e1acf581SJoel Stanley static void aspeed_ast2600_sbc_class_init(ObjectClass *klass, void *data)
164e1acf581SJoel Stanley {
165e1acf581SJoel Stanley     DeviceClass *dc = DEVICE_CLASS(klass);
166e1acf581SJoel Stanley 
167e1acf581SJoel Stanley     dc->desc = "AST2600 Secure Boot Controller";
168e1acf581SJoel Stanley }
169e1acf581SJoel Stanley 
170e1acf581SJoel Stanley static const TypeInfo aspeed_ast2600_sbc_info = {
171e1acf581SJoel Stanley     .name = TYPE_ASPEED_AST2600_SBC,
172e1acf581SJoel Stanley     .parent = TYPE_ASPEED_SBC,
173e1acf581SJoel Stanley     .class_init = aspeed_ast2600_sbc_class_init,
174e1acf581SJoel Stanley };
175e1acf581SJoel Stanley 
aspeed_sbc_register_types(void)176e1acf581SJoel Stanley static void aspeed_sbc_register_types(void)
177e1acf581SJoel Stanley {
178e1acf581SJoel Stanley     type_register_static(&aspeed_ast2600_sbc_info);
179e1acf581SJoel Stanley     type_register_static(&aspeed_sbc_info);
180e1acf581SJoel Stanley }
181e1acf581SJoel Stanley 
182e1acf581SJoel Stanley type_init(aspeed_sbc_register_types);
183