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