1 /* 2 * ASPEED Secure Boot Controller 3 * 4 * Copyright (C) 2021-2022 IBM Corp. 5 * 6 * Joel Stanley <joel@jms.id.au> 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11 #include "qemu/osdep.h" 12 #include "qemu/log.h" 13 #include "qemu/error-report.h" 14 #include "hw/misc/aspeed_sbc.h" 15 #include "qapi/error.h" 16 #include "migration/vmstate.h" 17 18 #define R_PROT (0x000 / 4) 19 #define R_STATUS (0x014 / 4) 20 21 static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size) 22 { 23 AspeedSBCState *s = ASPEED_SBC(opaque); 24 25 addr >>= 2; 26 27 if (addr >= ASPEED_SBC_NR_REGS) { 28 qemu_log_mask(LOG_GUEST_ERROR, 29 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 30 __func__, addr << 2); 31 return 0; 32 } 33 34 return s->regs[addr]; 35 } 36 37 static void aspeed_sbc_write(void *opaque, hwaddr addr, uint64_t data, 38 unsigned int size) 39 { 40 AspeedSBCState *s = ASPEED_SBC(opaque); 41 42 addr >>= 2; 43 44 if (addr >= ASPEED_SBC_NR_REGS) { 45 qemu_log_mask(LOG_GUEST_ERROR, 46 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 47 __func__, addr << 2); 48 return; 49 } 50 51 switch (addr) { 52 case R_STATUS: 53 qemu_log_mask(LOG_GUEST_ERROR, 54 "%s: write to read only register 0x%" HWADDR_PRIx "\n", 55 __func__, addr << 2); 56 return; 57 default: 58 break; 59 } 60 61 s->regs[addr] = data; 62 } 63 64 static const MemoryRegionOps aspeed_sbc_ops = { 65 .read = aspeed_sbc_read, 66 .write = aspeed_sbc_write, 67 .endianness = DEVICE_LITTLE_ENDIAN, 68 .valid = { 69 .min_access_size = 1, 70 .max_access_size = 4, 71 }, 72 }; 73 74 static void aspeed_sbc_reset(DeviceState *dev) 75 { 76 struct AspeedSBCState *s = ASPEED_SBC(dev); 77 78 memset(s->regs, 0, sizeof(s->regs)); 79 80 /* Set secure boot enabled, and boot from emmc/spi */ 81 s->regs[R_STATUS] = 1 << 6 | 1 << 5; 82 } 83 84 static void aspeed_sbc_realize(DeviceState *dev, Error **errp) 85 { 86 AspeedSBCState *s = ASPEED_SBC(dev); 87 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 88 89 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sbc_ops, s, 90 TYPE_ASPEED_SBC, 0x1000); 91 92 sysbus_init_mmio(sbd, &s->iomem); 93 } 94 95 static const VMStateDescription vmstate_aspeed_sbc = { 96 .name = TYPE_ASPEED_SBC, 97 .version_id = 1, 98 .minimum_version_id = 1, 99 .fields = (VMStateField[]) { 100 VMSTATE_UINT32_ARRAY(regs, AspeedSBCState, ASPEED_SBC_NR_REGS), 101 VMSTATE_END_OF_LIST(), 102 } 103 }; 104 105 static void aspeed_sbc_class_init(ObjectClass *klass, void *data) 106 { 107 DeviceClass *dc = DEVICE_CLASS(klass); 108 109 dc->realize = aspeed_sbc_realize; 110 dc->reset = aspeed_sbc_reset; 111 dc->vmsd = &vmstate_aspeed_sbc; 112 } 113 114 static const TypeInfo aspeed_sbc_info = { 115 .name = TYPE_ASPEED_SBC, 116 .parent = TYPE_SYS_BUS_DEVICE, 117 .instance_size = sizeof(AspeedSBCState), 118 .class_init = aspeed_sbc_class_init, 119 .class_size = sizeof(AspeedSBCClass) 120 }; 121 122 static void aspeed_ast2600_sbc_class_init(ObjectClass *klass, void *data) 123 { 124 DeviceClass *dc = DEVICE_CLASS(klass); 125 126 dc->desc = "AST2600 Secure Boot Controller"; 127 } 128 129 static const TypeInfo aspeed_ast2600_sbc_info = { 130 .name = TYPE_ASPEED_AST2600_SBC, 131 .parent = TYPE_ASPEED_SBC, 132 .class_init = aspeed_ast2600_sbc_class_init, 133 }; 134 135 static void aspeed_sbc_register_types(void) 136 { 137 type_register_static(&aspeed_ast2600_sbc_info); 138 type_register_static(&aspeed_sbc_info); 139 } 140 141 type_init(aspeed_sbc_register_types); 142