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