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" 14*54ee5641SJoel 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 23*54ee5641SJoel Stanley /* R_STATUS */ 24*54ee5641SJoel Stanley #define ABR_EN BIT(14) /* Mirrors SCU510[11] */ 25*54ee5641SJoel Stanley #define ABR_IMAGE_SOURCE BIT(13) 26*54ee5641SJoel Stanley #define SPI_ABR_IMAGE_SOURCE BIT(12) 27*54ee5641SJoel Stanley #define SB_CRYPTO_KEY_EXP_DONE BIT(11) 28*54ee5641SJoel Stanley #define SB_CRYPTO_BUSY BIT(10) 29*54ee5641SJoel Stanley #define OTP_WP_EN BIT(9) 30*54ee5641SJoel Stanley #define OTP_ADDR_WP_EN BIT(8) 31*54ee5641SJoel Stanley #define LOW_SEC_KEY_EN BIT(7) 32*54ee5641SJoel Stanley #define SECURE_BOOT_EN BIT(6) 33*54ee5641SJoel Stanley #define UART_BOOT_EN BIT(5) 34*54ee5641SJoel Stanley /* bit 4 reserved*/ 35*54ee5641SJoel Stanley #define OTP_CHARGE_PUMP_READY BIT(3) 36*54ee5641SJoel Stanley #define OTP_IDLE BIT(2) 37*54ee5641SJoel Stanley #define OTP_MEM_IDLE BIT(1) 38*54ee5641SJoel Stanley #define OTP_COMPARE_STATUS BIT(0) 39*54ee5641SJoel Stanley 40*54ee5641SJoel Stanley /* QSR */ 41*54ee5641SJoel Stanley #define QSR_RSA_MASK (0x3 << 12) 42*54ee5641SJoel Stanley #define QSR_HASH_MASK (0x3 << 10) 43*54ee5641SJoel Stanley 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 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 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 */ 105*54ee5641SJoel Stanley s->regs[R_STATUS] = OTP_IDLE | OTP_MEM_IDLE; 106*54ee5641SJoel Stanley 107*54ee5641SJoel Stanley if (s->emmc_abr) { 108*54ee5641SJoel Stanley s->regs[R_STATUS] &= ABR_EN; 109*54ee5641SJoel Stanley } 110*54ee5641SJoel Stanley 111*54ee5641SJoel Stanley if (s->signing_settings) { 112*54ee5641SJoel Stanley s->regs[R_STATUS] &= SECURE_BOOT_EN; 113*54ee5641SJoel Stanley } 114*54ee5641SJoel Stanley 115*54ee5641SJoel Stanley s->regs[R_QSR] = s->signing_settings; 116e1acf581SJoel Stanley } 117e1acf581SJoel Stanley 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, 133e1acf581SJoel Stanley .fields = (VMStateField[]) { 134e1acf581SJoel Stanley VMSTATE_UINT32_ARRAY(regs, AspeedSBCState, ASPEED_SBC_NR_REGS), 135e1acf581SJoel Stanley VMSTATE_END_OF_LIST(), 136e1acf581SJoel Stanley } 137e1acf581SJoel Stanley }; 138e1acf581SJoel Stanley 139*54ee5641SJoel Stanley static Property aspeed_sbc_properties[] = { 140*54ee5641SJoel Stanley DEFINE_PROP_BOOL("emmc-abr", AspeedSBCState, emmc_abr, 0), 141*54ee5641SJoel Stanley DEFINE_PROP_UINT32("signing-settings", AspeedSBCState, signing_settings, 0), 142*54ee5641SJoel Stanley DEFINE_PROP_END_OF_LIST(), 143*54ee5641SJoel Stanley }; 144*54ee5641SJoel Stanley 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; 150e1acf581SJoel Stanley dc->reset = aspeed_sbc_reset; 151e1acf581SJoel Stanley dc->vmsd = &vmstate_aspeed_sbc; 152*54ee5641SJoel 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 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 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