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