xref: /openbmc/qemu/hw/misc/aspeed_sbc.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
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/qdev-properties.h"
15  #include "hw/misc/aspeed_sbc.h"
16  #include "qapi/error.h"
17  #include "migration/vmstate.h"
18  
19  #define R_PROT          (0x000 / 4)
20  #define R_STATUS        (0x014 / 4)
21  #define R_QSR           (0x040 / 4)
22  
23  /* R_STATUS */
24  #define ABR_EN                  BIT(14) /* Mirrors SCU510[11] */
25  #define ABR_IMAGE_SOURCE        BIT(13)
26  #define SPI_ABR_IMAGE_SOURCE    BIT(12)
27  #define SB_CRYPTO_KEY_EXP_DONE  BIT(11)
28  #define SB_CRYPTO_BUSY          BIT(10)
29  #define OTP_WP_EN               BIT(9)
30  #define OTP_ADDR_WP_EN          BIT(8)
31  #define LOW_SEC_KEY_EN          BIT(7)
32  #define SECURE_BOOT_EN          BIT(6)
33  #define UART_BOOT_EN            BIT(5)
34  /* bit 4 reserved*/
35  #define OTP_CHARGE_PUMP_READY   BIT(3)
36  #define OTP_IDLE                BIT(2)
37  #define OTP_MEM_IDLE            BIT(1)
38  #define OTP_COMPARE_STATUS      BIT(0)
39  
40  /* QSR */
41  #define QSR_RSA_MASK           (0x3 << 12)
42  #define QSR_HASH_MASK          (0x3 << 10)
43  
aspeed_sbc_read(void * opaque,hwaddr addr,unsigned int size)44  static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size)
45  {
46      AspeedSBCState *s = ASPEED_SBC(opaque);
47  
48      addr >>= 2;
49  
50      if (addr >= ASPEED_SBC_NR_REGS) {
51          qemu_log_mask(LOG_GUEST_ERROR,
52                        "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
53                        __func__, addr << 2);
54          return 0;
55      }
56  
57      return s->regs[addr];
58  }
59  
aspeed_sbc_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)60  static void aspeed_sbc_write(void *opaque, hwaddr addr, uint64_t data,
61                                unsigned int size)
62  {
63      AspeedSBCState *s = ASPEED_SBC(opaque);
64  
65      addr >>= 2;
66  
67      if (addr >= ASPEED_SBC_NR_REGS) {
68          qemu_log_mask(LOG_GUEST_ERROR,
69                        "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
70                        __func__, addr << 2);
71          return;
72      }
73  
74      switch (addr) {
75      case R_STATUS:
76      case R_QSR:
77          qemu_log_mask(LOG_GUEST_ERROR,
78                        "%s: write to read only register 0x%" HWADDR_PRIx "\n",
79                        __func__, addr << 2);
80          return;
81      default:
82          break;
83      }
84  
85      s->regs[addr] = data;
86  }
87  
88  static const MemoryRegionOps aspeed_sbc_ops = {
89      .read = aspeed_sbc_read,
90      .write = aspeed_sbc_write,
91      .endianness = DEVICE_LITTLE_ENDIAN,
92      .valid = {
93          .min_access_size = 1,
94          .max_access_size = 4,
95      },
96  };
97  
aspeed_sbc_reset(DeviceState * dev)98  static void aspeed_sbc_reset(DeviceState *dev)
99  {
100      struct AspeedSBCState *s = ASPEED_SBC(dev);
101  
102      memset(s->regs, 0, sizeof(s->regs));
103  
104      /* Set secure boot enabled with RSA4096_SHA256 and enable eMMC ABR */
105      s->regs[R_STATUS] = OTP_IDLE | OTP_MEM_IDLE;
106  
107      if (s->emmc_abr) {
108          s->regs[R_STATUS] &= ABR_EN;
109      }
110  
111      if (s->signing_settings) {
112          s->regs[R_STATUS] &= SECURE_BOOT_EN;
113      }
114  
115      s->regs[R_QSR] = s->signing_settings;
116  }
117  
aspeed_sbc_realize(DeviceState * dev,Error ** errp)118  static void aspeed_sbc_realize(DeviceState *dev, Error **errp)
119  {
120      AspeedSBCState *s = ASPEED_SBC(dev);
121      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
122  
123      memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sbc_ops, s,
124              TYPE_ASPEED_SBC, 0x1000);
125  
126      sysbus_init_mmio(sbd, &s->iomem);
127  }
128  
129  static const VMStateDescription vmstate_aspeed_sbc = {
130      .name = TYPE_ASPEED_SBC,
131      .version_id = 1,
132      .minimum_version_id = 1,
133      .fields = (const VMStateField[]) {
134          VMSTATE_UINT32_ARRAY(regs, AspeedSBCState, ASPEED_SBC_NR_REGS),
135          VMSTATE_END_OF_LIST(),
136      }
137  };
138  
139  static Property aspeed_sbc_properties[] = {
140      DEFINE_PROP_BOOL("emmc-abr", AspeedSBCState, emmc_abr, 0),
141      DEFINE_PROP_UINT32("signing-settings", AspeedSBCState, signing_settings, 0),
142      DEFINE_PROP_END_OF_LIST(),
143  };
144  
aspeed_sbc_class_init(ObjectClass * klass,void * data)145  static void aspeed_sbc_class_init(ObjectClass *klass, void *data)
146  {
147      DeviceClass *dc = DEVICE_CLASS(klass);
148  
149      dc->realize = aspeed_sbc_realize;
150      device_class_set_legacy_reset(dc, aspeed_sbc_reset);
151      dc->vmsd = &vmstate_aspeed_sbc;
152      device_class_set_props(dc, aspeed_sbc_properties);
153  }
154  
155  static const TypeInfo aspeed_sbc_info = {
156      .name = TYPE_ASPEED_SBC,
157      .parent = TYPE_SYS_BUS_DEVICE,
158      .instance_size = sizeof(AspeedSBCState),
159      .class_init = aspeed_sbc_class_init,
160      .class_size = sizeof(AspeedSBCClass)
161  };
162  
aspeed_ast2600_sbc_class_init(ObjectClass * klass,void * data)163  static void aspeed_ast2600_sbc_class_init(ObjectClass *klass, void *data)
164  {
165      DeviceClass *dc = DEVICE_CLASS(klass);
166  
167      dc->desc = "AST2600 Secure Boot Controller";
168  }
169  
170  static const TypeInfo aspeed_ast2600_sbc_info = {
171      .name = TYPE_ASPEED_AST2600_SBC,
172      .parent = TYPE_ASPEED_SBC,
173      .class_init = aspeed_ast2600_sbc_class_init,
174  };
175  
aspeed_sbc_register_types(void)176  static void aspeed_sbc_register_types(void)
177  {
178      type_register_static(&aspeed_ast2600_sbc_info);
179      type_register_static(&aspeed_sbc_info);
180  }
181  
182  type_init(aspeed_sbc_register_types);
183