qemu/hw/misc/csu_aes.c
<<
>>
Prefs
   1/*
   2 * QEMU model of ZynqMP CSU AES-GCM block
   3 *
   4 * Copyright (c) 2013 Xilinx Inc
   5 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   6 *
   7 * This code is licensed under the GNU GPL.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "hw/sysbus.h"
  12#include "qemu/log.h"
  13#include "qapi/error.h"
  14
  15#include "hw/hw.h"
  16#include "hw/stream.h"
  17#include "qemu/bitops.h"
  18#include "sysemu/dma.h"
  19#include "migration/vmstate.h"
  20#include "hw/qdev-properties.h"
  21#include "hw/register.h"
  22#include "hw/zynqmp_aes_key.h"
  23#include "hw/fdt_generic_util.h"
  24
  25#include "hw/misc/xlnx-aes.h"
  26
  27#ifndef ZYNQMP_CSU_AES_ERR_DEBUG
  28#define ZYNQMP_CSU_AES_ERR_DEBUG 0
  29#endif
  30
  31#define TYPE_ZYNQMP_CSU_AES "zynqmp,csu-aes"
  32#define TYPE_ZYNQMP_CSU_DEVKEY_SINK "zynqmp.csu-aes.devkey-sink"
  33
  34#define ZYNQMP_CSU_AES(obj) \
  35     OBJECT_CHECK(ZynqMPCSUAES, (obj), TYPE_ZYNQMP_CSU_AES)
  36
  37#define ZYNQMP_CSU_KEY_SINK(obj) \
  38     OBJECT_CHECK(CSUKeySink, (obj), TYPE_ZYNQMP_CSU_DEVKEY_SINK)
  39
  40REG32(AES_STATUS, 0x00)
  41    FIELD(AES_STATUS, OKR_ZEROED, 11, 1)
  42    FIELD(AES_STATUS, BOOT_ZEROED, 10, 1)
  43    FIELD(AES_STATUS, KUP_ZEROED, 9, 1)
  44    FIELD(AES_STATUS, AES_KEY_ZEROED, 8, 1)
  45    FIELD(AES_STATUS, BLACK_KEY_DONE, 5, 1)
  46    FIELD(AES_STATUS, KEY_INIT_DONE, 4, 1)
  47    FIELD(AES_STATUS, GCM_TAG_PASS, 3, 1)
  48    FIELD(AES_STATUS, DONE, 2, 1)
  49    FIELD(AES_STATUS, READY, 1, 1)
  50    FIELD(AES_STATUS, BUSY, 0, 1)
  51REG32(AES_KEY_SRC, 0x04)
  52    FIELD(AES_KEY_SRC, KEY_SRC, 0, 4)
  53
  54#define AES_KEYSRC_KUP        0
  55#define AES_KEYSRC_DEV        1
  56
  57REG32(AES_KEY_LOAD, 0x08)
  58    FIELD(AES_KEY_LOAD, KEY_LOAD, 0, 1)
  59REG32(AES_START_MSG, 0x0c)
  60    FIELD(AES_START_MSG, START_MSG, 0, 1)
  61REG32(AES_RESET, 0x10)
  62    FIELD(AES_RESET, RESET, 0, 1)
  63REG32(AES_KEY_CLEAR, 0x14)
  64    FIELD(AES_KEY_CLEAR, AES_KUP_ZERO, 1, 1)
  65    FIELD(AES_KEY_CLEAR, AES_KEY_ZERO, 0, 1)
  66REG32(AES_CFG, 0x18)
  67    FIELD(AES_CFG, ENCRYPT_DECRYPT_N, 0, 1)
  68REG32(AES_KUP_WR, 0x1c)
  69    FIELD(AES_KUP_WR, IV_WRITE, 1, 1)
  70    FIELD(AES_KUP_WR, KUP_WRITE, 0, 1)
  71REG32(AES_KUP_0, 0x020)
  72REG32(AES_KUP_1, 0x24)
  73REG32(AES_KUP_2, 0x28)
  74REG32(AES_KUP_3, 0x2c)
  75REG32(AES_KUP_4, 0x30)
  76REG32(AES_KUP_5, 0x34)
  77REG32(AES_KUP_6, 0x38)
  78REG32(AES_KUP_7, 0x3c)
  79REG32(AES_IV_0, 0x40)
  80REG32(AES_IV_1, 0x44)
  81REG32(AES_IV_2, 0x48)
  82REG32(AES_IV_3, 0x4c)
  83
  84#define R_MAX                      (R_AES_IV_3 + 1)
  85
  86static const RegisterAccessInfo aes_regs_info[] = {
  87    {   .name = "AES_STATUS",  .addr = A_AES_STATUS,
  88        .reset = 0xf00,
  89        .rsvd = 0xc0,
  90        .ro = 0xfff,
  91    },{ .name = "AES_KEY_SRC",  .addr = A_AES_KEY_SRC,
  92    },{ .name = "AES_KEY_LOAD",  .addr = A_AES_KEY_LOAD,
  93    },{ .name = "AES_START_MSG",  .addr = A_AES_START_MSG,
  94    },{ .name = "AES_RESET",  .addr = A_AES_RESET,
  95    },{ .name = "AES_KEY_CLEAR",  .addr = A_AES_KEY_CLEAR,
  96    },{ .name = "AES_CFG",  .addr = A_AES_CFG,
  97    },{ .name = "AES_KUP_WR",  .addr = A_AES_KUP_WR,
  98    },{ .name = "AES_KUP_0",  .addr = A_AES_KUP_0,
  99    },{ .name = "AES_KUP_1",  .addr = A_AES_KUP_1,
 100    },{ .name = "AES_KUP_2",  .addr = A_AES_KUP_2,
 101    },{ .name = "AES_KUP_3",  .addr = A_AES_KUP_3,
 102    },{ .name = "AES_KUP_4",  .addr = A_AES_KUP_4,
 103    },{ .name = "AES_KUP_5",  .addr = A_AES_KUP_5,
 104    },{ .name = "AES_KUP_6",  .addr = A_AES_KUP_6,
 105    },{ .name = "AES_KUP_7",  .addr = A_AES_KUP_7,
 106    },{ .name = "AES_IV_0",  .addr = A_AES_IV_0,
 107        .ro = 0xffffffff,
 108    },{ .name = "AES_IV_1",  .addr = A_AES_IV_1,
 109        .ro = 0xffffffff,
 110    },{ .name = "AES_IV_2",  .addr = A_AES_IV_2,
 111        .ro = 0xffffffff,
 112    },{ .name = "AES_IV_3",  .addr = A_AES_IV_3,
 113        .ro = 0xffffffff,
 114    }
 115};
 116
 117typedef struct ZynqMPCSUAES ZynqMPCSUAES;
 118
 119typedef struct CSUKeySink {
 120    Object parent;
 121    ZynqMPCSUAES *tmr;
 122
 123    union {
 124        uint8_t key[256 / 8];
 125        uint32_t k32[256 / 32];
 126    };
 127} CSUKeySink;
 128
 129/* This implements a model of the wrapper logic around the Helion unit.  */
 130struct ZynqMPCSUAES {
 131    SysBusDevice busdev;
 132    MemoryRegion iomem;
 133    StreamSink *tx_dev;
 134    char *family_key_id;
 135    char *puf_key_id;
 136
 137    XlnxAES *aes;
 138    qemu_irq aes_rst;
 139    bool in_reset;
 140    bool aes_done;
 141    bool aes_busy;
 142
 143    bool key_loaded;
 144    uint32_t regs[R_MAX];
 145    RegisterInfo regs_info[R_MAX];
 146
 147    union {
 148        struct {
 149            bool kup_write;
 150            bool boot_write;
 151            bool okr_write;
 152            bool iv_write;
 153            bool key_decrypt;
 154        };
 155        bool bl[5];
 156    } inputs;
 157
 158    CSUKeySink bbram_key;
 159    CSUKeySink boot_key;
 160    CSUKeySink efuse_key;
 161    CSUKeySink family_key;
 162    CSUKeySink okr_key;
 163    CSUKeySink puf_key;
 164    CSUKeySink *dev_key;
 165
 166    struct {
 167        uint32_t key[256 / 32];
 168        uint32_t iv[128 / 32];
 169    } feedback;
 170
 171    StreamCanPushNotifyFn notify;
 172    void *notify_opaque;
 173    /* Debug only */
 174    const char *prefix;
 175};
 176
 177/* Xilinx wrapper logic.
 178 *
 179 * Disable AAD.
 180 * Cap encryption lengths to 256bit.
 181 */
 182static int xlx_aes_push_data(ZynqMPCSUAES *s,
 183                             uint8_t *data8x, int len,
 184                             bool last_word , int lw_len,
 185                             uint8_t *outbuf, int *outlen)
 186{
 187    /* ZynqMP does not support AAD */
 188    return xlnx_aes_push_data(s->aes, data8x, len, false, last_word, lw_len,
 189                              outbuf, outlen);
 190}
 191
 192static uint32_t shift_in_u32(uint32_t *a, unsigned int size, uint32_t data)
 193{
 194    unsigned int i;
 195    uint32_t r = a[0];
 196
 197    for (i = 1; i < size; i++) {
 198        a[i - 1] = a[i];
 199    }
 200    a[i - 1] = data;
 201
 202    return r;
 203}
 204
 205static void update_devkey_sink(CSUKeySink *ks, void *key)
 206{
 207    memcpy(ks->key, key, sizeof(ks->key));
 208}
 209
 210static void xlx_aes_feedback(ZynqMPCSUAES *s, unsigned char *buf, int len)
 211{
 212    bool key_feedback;
 213    bool kup_key_feedback;
 214    bool iv_feedback;
 215    int i;
 216
 217    iv_feedback = s->inputs.iv_write;
 218    iv_feedback |= s->regs[R_AES_KUP_WR] & R_AES_KUP_WR_IV_WRITE_MASK;
 219
 220    kup_key_feedback = s->inputs.kup_write;
 221    kup_key_feedback |= s->regs[R_AES_KUP_WR] & R_AES_KUP_WR_KUP_WRITE_MASK;
 222
 223    key_feedback = kup_key_feedback;
 224    key_feedback |= s->inputs.okr_write | s->inputs.boot_write;
 225
 226    assert((len & 3) == 0);
 227
 228    for (i = 0; i < len; i += 4) {
 229        uint32_t data;
 230        memcpy(&data, buf + i, 4);
 231
 232        if (iv_feedback) {
 233            data = shift_in_u32(s->feedback.iv, ARRAY_SIZE(s->feedback.iv),
 234                               data);
 235        }
 236        if (key_feedback) {
 237            shift_in_u32(s->feedback.key, ARRAY_SIZE(s->feedback.key), data);
 238        }
 239    }
 240
 241    /* feedback the AES output into Key and IV storage.  */
 242    if (iv_feedback) {
 243        for (i = 0; i < ARRAY_SIZE(s->feedback.iv); i++) {
 244            s->regs[R_AES_IV_0 + i] = s->feedback.iv[i];
 245        }
 246    }
 247    if (s->inputs.kup_write | kup_key_feedback) {
 248        for (i = 0; i < ARRAY_SIZE(s->feedback.key); i++) {
 249            s->regs[R_AES_KUP_0 + i] = s->feedback.key[i];
 250        }
 251    }
 252
 253    if (s->inputs.boot_write) {
 254        update_devkey_sink(&s->boot_key, s->feedback.key);
 255    }
 256    if (s->inputs.okr_write) {
 257        update_devkey_sink(&s->okr_key, s->feedback.key);
 258    }
 259}
 260
 261static void bswap32_buf8(uint8_t *buf, int len)
 262{
 263    int i;
 264
 265    assert((len & 3) == 0);
 266    for (i = 0; i < len; i += 4) {
 267        uint8_t v[4];
 268
 269        v[0] = buf[i];
 270        v[1] = buf[i + 1];
 271        v[2] = buf[i + 2];
 272        v[3] = buf[i + 3];
 273        buf[i] = v[3];
 274        buf[i + 1] = v[2];
 275        buf[i + 2] = v[1];
 276        buf[i + 3] = v[0];
 277    }
 278}
 279
 280static size_t xlx_aes_stream_push(StreamSink *obj, uint8_t *buf, size_t len,
 281                                  bool eop)
 282{
 283    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(obj);
 284    unsigned char outbuf[8 * 1024 + 16];
 285    int outlen = 0;
 286    bool feedback;
 287    size_t ret;
 288
 289    /* When encrypting, we need to be prepared to receive the 16 byte tag.  */
 290    if (len > (sizeof(outbuf) - 16)) {
 291        len = sizeof(outbuf) - 16;
 292        eop = false;
 293    }
 294
 295    bswap32_buf8(buf, len);
 296    ret = xlx_aes_push_data(s, buf, len, eop, 4, outbuf, &outlen);
 297    bswap32_buf8(outbuf, outlen);
 298
 299    /* No flow-control on the output.  */
 300    feedback = s->inputs.iv_write | s->inputs.kup_write;
 301    feedback |= s->inputs.boot_write | s->inputs.okr_write;
 302    feedback |= s->regs[R_AES_KUP_WR]
 303                & (R_AES_KUP_WR_IV_WRITE_MASK | R_AES_KUP_WR_KUP_WRITE_MASK);
 304    if (feedback) {
 305        xlx_aes_feedback(s, outbuf, outlen);
 306        memset(outbuf, 0, outlen);
 307    }
 308    stream_push(s->tx_dev, outbuf, outlen, eop);
 309    return ret;
 310}
 311
 312static bool xlx_aes_stream_can_push(StreamSink *obj,
 313                                    StreamCanPushNotifyFn notify,
 314                                    void *notify_opaque)
 315{
 316    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(obj);
 317    return s->aes->inp_ready;
 318}
 319
 320static void xlx_aes_write_key(ZynqMPCSUAES *s, unsigned int pos, uint32_t val)
 321{
 322    if (s->inputs.key_decrypt) {
 323        xlx_aes_stream_push(STREAM_SINK(s), (void *) &val, sizeof val, 0);
 324    } else {
 325        xlnx_aes_write_key(s->aes, pos, val);
 326    }
 327}
 328
 329static void xlx_aes_load_key(ZynqMPCSUAES *s, int len)
 330{
 331    static uint32_t const zero_key[256 / 32] = { 0};
 332    const uint32_t *k32;
 333
 334    unsigned int src, i;
 335    src = (s->regs[R_AES_KEY_SRC] & R_AES_KEY_SRC_KEY_SRC_MASK)
 336           >> R_AES_KEY_SRC_KEY_SRC_SHIFT;
 337
 338    switch (src) {
 339    case AES_KEYSRC_KUP:
 340        k32 = &s->regs[R_AES_KUP_0];
 341        break;
 342    case AES_KEYSRC_DEV:
 343        k32 = s->dev_key ? s->dev_key->k32 : zero_key;
 344        break;
 345    default:
 346        hw_error("%s: Unsupported AES Key source %d\n", s->prefix, src);
 347        k32 = zero_key;
 348    }
 349
 350    for (i = 0; i < 8; i++) {
 351        xlx_aes_write_key(s, i, k32[i]);
 352    }
 353
 354    if (!s->inputs.key_decrypt) {
 355        xlnx_aes_load_key(s->aes, len);
 356    }
 357    s->key_loaded = true;
 358}
 359
 360static uint64_t xlx_aes_read(void *opaque, hwaddr addr, unsigned size)
 361{
 362    RegisterInfoArray *reg_array = opaque;
 363    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(reg_array->r[0]->opaque);
 364    uint32_t v;
 365
 366    v = register_read_memory(opaque, addr, size);
 367
 368    addr >>= 2;
 369    assert(addr < R_MAX);
 370    switch (addr) {
 371    case R_AES_KUP_0...R_AES_KUP_7:
 372        v = 0;
 373        break;
 374    case R_AES_STATUS:
 375        v = 0;
 376        v |= R_AES_STATUS_BOOT_ZEROED_MASK;
 377        v |= R_AES_STATUS_OKR_ZEROED_MASK;
 378        v |= R_AES_STATUS_KUP_ZEROED_MASK;
 379        v |= s->key_loaded ? R_AES_STATUS_KEY_INIT_DONE_MASK : 0;
 380        v |= s->aes->key_zeroed ? R_AES_STATUS_AES_KEY_ZEROED_MASK : 0;
 381        v |= s->aes->tag_ok ? R_AES_STATUS_GCM_TAG_PASS_MASK : 0;
 382        v |= s->aes->inp_ready ? R_AES_STATUS_READY_MASK : 0;
 383        v |= s->aes_busy ? R_AES_STATUS_BUSY_MASK : 0;
 384        v |= s->aes_done ? R_AES_STATUS_DONE_MASK : 0;
 385        break;
 386    default:
 387        break;
 388    }
 389    return v;
 390}
 391
 392static void xlx_aes_reset(DeviceState *dev)
 393{
 394    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(dev);
 395    int i;
 396
 397    s->in_reset = true;
 398    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 399        register_reset(&s->regs_info[i]);
 400    }
 401
 402    qemu_irq_pulse(s->aes_rst);
 403    s->key_loaded = false;
 404
 405    s->in_reset = false;
 406}
 407
 408static void xlx_aes_write(void *opaque, hwaddr addr, uint64_t value,
 409                      unsigned size)
 410{
 411    RegisterInfoArray *reg_array = opaque;
 412    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(reg_array->r[0]->opaque);
 413
 414    register_write_memory(opaque, addr, value, size);
 415
 416    addr >>= 2;
 417    switch (addr) {
 418    case R_AES_KEY_LOAD:
 419        if (value) {
 420            xlx_aes_load_key(s, 256);
 421        }
 422        break;
 423    case R_AES_START_MSG:
 424        if (value) {
 425            xlnx_aes_start_message(s->aes,
 426                         s->regs[R_AES_CFG] & R_AES_CFG_ENCRYPT_DECRYPT_N_MASK);
 427        }
 428        break;
 429    case R_AES_RESET:
 430        if (value && !s->in_reset) {
 431            xlx_aes_reset((void *)s);
 432        }
 433        break;
 434    case R_AES_KEY_CLEAR:
 435        if (value & R_AES_KEY_CLEAR_AES_KEY_ZERO_MASK) {
 436            xlnx_aes_key_zero(s->aes);
 437            s->regs[R_AES_KEY_CLEAR] &= ~R_AES_KEY_CLEAR_AES_KEY_ZERO_MASK;
 438            s->key_loaded = false;
 439        }
 440        if (value & R_AES_KEY_CLEAR_AES_KUP_ZERO_MASK) {
 441            s->regs[R_AES_KEY_CLEAR] &= ~R_AES_KEY_CLEAR_AES_KUP_ZERO_MASK;
 442            memset(&s->regs[R_AES_KUP_0], 0, 8 * 4);
 443        }
 444        break;
 445    default:
 446        break;
 447    }
 448}
 449
 450static const MemoryRegionOps aes_ops = {
 451    .read = xlx_aes_read,
 452    .write = xlx_aes_write,
 453    .endianness = DEVICE_LITTLE_ENDIAN,
 454};
 455
 456static void gpio_key_write_ctrl(void *opaque, int n, int level)
 457{
 458    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(opaque);
 459    assert(n < ARRAY_SIZE(s->inputs.bl));
 460
 461    s->inputs.bl[n] = level;
 462}
 463
 464static void aes_busy_update(void *opaque, int n, int level)
 465{
 466    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(opaque);
 467
 468    s->aes_busy = level;
 469}
 470
 471static void aes_done_update(void *opaque, int n, int level)
 472{
 473    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(opaque);
 474
 475    s->aes_done = level;
 476}
 477
 478static void aes_realize(DeviceState *dev, Error **errp)
 479{
 480    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(dev);
 481
 482    s->prefix = g_strdup_printf("%s:", object_get_canonical_path(OBJECT(s)));
 483    s->aes->prefix = s->prefix;
 484    qdev_init_gpio_in_named(dev, aes_busy_update, "busy", 1);
 485    qdev_init_gpio_in_named(dev, aes_done_update, "done", 1);
 486    qdev_init_gpio_out_named(dev, &s->aes_rst, "reset", 1);
 487    qdev_init_gpio_in_named(dev, gpio_key_write_ctrl, "key-wr", 5);
 488
 489    /* Set device keys to user-provided values */
 490    xlnx_aes_k256_get_provided(OBJECT(s), "family-key-id",
 491                               NULL, s->family_key.key, NULL);
 492}
 493
 494static void csu_devkey_sink_init(ZynqMPCSUAES *s,
 495                                 const char *name, CSUKeySink *ks)
 496{
 497    char *ch_name;
 498
 499    ch_name = g_strdup_printf("zynqmp-aes-key-sink-%s-target", name);
 500    object_initialize(ks, sizeof(*ks), TYPE_ZYNQMP_CSU_DEVKEY_SINK);
 501    object_property_add_child(OBJECT(s), ch_name, (Object *)ks);
 502    free(ch_name);
 503
 504    /* Back link, non-qom for the moment.  */
 505    ks->tmr = s;
 506}
 507
 508static void aes_init(Object *obj)
 509{
 510    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(obj);
 511    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 512    RegisterInfoArray *reg_array;
 513
 514    /* Sources of device key, as shown in Xilinx UG1085, v1.9, Fig.12-2 */
 515    csu_devkey_sink_init(s, "bbram", &s->bbram_key);
 516    csu_devkey_sink_init(s, "boot", &s->boot_key);
 517    csu_devkey_sink_init(s, "efuses", &s->efuse_key);
 518    csu_devkey_sink_init(s, "family", &s->family_key);
 519    csu_devkey_sink_init(s, "operational", &s->okr_key);
 520    csu_devkey_sink_init(s, "puf", &s->puf_key);
 521
 522    if (s->family_key_id == NULL) {
 523        s->family_key_id = g_strdup("xlnx-aes-family-key");
 524    }
 525    if (s->puf_key_id == NULL) {
 526        s->puf_key_id = g_strdup("xlnx-aes-puf-key");
 527    }
 528
 529    /* A reference to one of above, to emulate the mux shown in Fig.12-2 */
 530    s->dev_key = NULL;
 531
 532    memory_region_init(&s->iomem, obj, TYPE_ZYNQMP_CSU_AES, R_MAX * 4);
 533    reg_array =
 534        register_init_block32(DEVICE(obj), aes_regs_info,
 535                              ARRAY_SIZE(aes_regs_info),
 536                              s->regs_info, s->regs,
 537                              &aes_ops,
 538                              ZYNQMP_CSU_AES_ERR_DEBUG,
 539                              R_MAX * 4);
 540    memory_region_add_subregion(&s->iomem,
 541                                0x0,
 542                                &reg_array->mem);
 543    sysbus_init_mmio(sbd, &s->iomem);
 544}
 545
 546static const VMStateDescription vmstate_aes = {
 547    .name = "zynqmp_csu_aes",
 548    .version_id = 1,
 549    .minimum_version_id = 1,
 550    .minimum_version_id_old = 1,
 551    .fields = (VMStateField[]) {
 552        VMSTATE_UINT32_ARRAY(regs, ZynqMPCSUAES, R_MAX),
 553        VMSTATE_END_OF_LIST(),
 554    }
 555};
 556
 557static Property aes_properties[] = {
 558    DEFINE_PROP_LINK("stream-connected-aes",
 559                     ZynqMPCSUAES, tx_dev,
 560                     TYPE_STREAM_SINK, StreamSink *),
 561    DEFINE_PROP_LINK("aes-core",
 562                     ZynqMPCSUAES, aes,
 563                     TYPE_XLNX_AES, XlnxAES *),
 564
 565    DEFINE_PROP_STRING("family-key-id", ZynqMPCSUAES, family_key_id),
 566    DEFINE_PROP_STRING("puf-key-id", ZynqMPCSUAES, puf_key_id),
 567
 568    DEFINE_PROP_END_OF_LIST(),
 569};
 570
 571static const FDTGenericGPIOSet aes_gpios[] = {
 572    {
 573      .names = &fdt_generic_gpio_name_set_gpio,
 574      .gpios = (FDTGenericGPIOConnection[]) {
 575        { .name = "key-wr", .fdt_index = 0, .range = 5 },
 576        { .name = "reset", .fdt_index = 5, .range = 1},
 577        { },
 578      },
 579    },
 580    { },
 581};
 582
 583static void aes_select_device_key(ZynqMPAESKeySink *obj, uint8_t *key, size_t len)
 584{
 585    ZynqMPCSUAES *s = ZYNQMP_CSU_AES(obj);
 586
 587    /*
 588     * Class-specific:
 589     * The key-material is 1-character key-sink label, not key values
 590     */
 591    assert(key);
 592    assert(len == 1);
 593
 594    switch (key[0]) {
 595    case 'M':
 596    case 'm':
 597        s->dev_key = &s->bbram_key;
 598        break;
 599    case 'E':
 600    case 'e':
 601        s->dev_key = &s->efuse_key;
 602        break;
 603    case 'B':
 604    case 'b':
 605        s->dev_key = &s->boot_key;
 606        break;
 607    case 'O':
 608    case 'o':
 609        s->dev_key = &s->okr_key;
 610        break;
 611    case 'F':
 612    case 'f':
 613        s->dev_key = &s->family_key;
 614        break;
 615    case 'P':
 616    case 'p':
 617        s->dev_key = &s->puf_key;
 618        break;
 619    default:
 620        s->dev_key = NULL;
 621    }
 622
 623    return;
 624}
 625
 626static void aes_class_init(ObjectClass *klass, void *data)
 627{
 628    DeviceClass *dc = DEVICE_CLASS(klass);
 629    StreamSinkClass *ssc = STREAM_SINK_CLASS(klass);
 630    ZynqMPAESKeySinkClass *ksc = ZYNQMP_AES_KEY_SINK_CLASS(klass);
 631    FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
 632
 633
 634    dc->reset = xlx_aes_reset;
 635    dc->realize = aes_realize;
 636    dc->vmsd = &vmstate_aes;
 637    device_class_set_props(dc, aes_properties);
 638
 639    ssc->push = xlx_aes_stream_push;
 640    ssc->can_push = xlx_aes_stream_can_push;
 641
 642    ksc->update = aes_select_device_key;
 643    fggc->controller_gpios = aes_gpios;
 644}
 645
 646static void csu_devkey_sink_update(ZynqMPAESKeySink *obj,
 647                                   uint8_t *key, size_t len)
 648{
 649    CSUKeySink *ks = ZYNQMP_CSU_KEY_SINK(obj);
 650
 651    assert(len == sizeof(ks->key)); /* Support only 1 size */
 652    update_devkey_sink(ks, key);
 653}
 654
 655static void csu_devkey_sink_class_init(ObjectClass *klass, void *data)
 656{
 657    ZynqMPAESKeySinkClass *c = ZYNQMP_AES_KEY_SINK_CLASS(klass);
 658    c->update = csu_devkey_sink_update;
 659}
 660
 661static const TypeInfo aes_info = {
 662    .name          = TYPE_ZYNQMP_CSU_AES,
 663    .parent        = TYPE_SYS_BUS_DEVICE,
 664    .instance_size = sizeof(ZynqMPCSUAES),
 665    .class_init    = aes_class_init,
 666    .instance_init = aes_init,
 667    .interfaces = (InterfaceInfo[]) {
 668        { TYPE_STREAM_SINK },
 669        { TYPE_ZYNQMP_AES_KEY_SINK },
 670        { TYPE_FDT_GENERIC_GPIO },
 671        { }
 672    }
 673};
 674
 675static const TypeInfo csu_devkey_sink_info = {
 676    .name          = TYPE_ZYNQMP_CSU_DEVKEY_SINK,
 677    .parent        = TYPE_OBJECT,
 678    .instance_size = sizeof(CSUKeySink),
 679    .class_init    = csu_devkey_sink_class_init,
 680    .interfaces    = (InterfaceInfo[]) {
 681        { TYPE_ZYNQMP_AES_KEY_SINK },
 682        { }
 683    }
 684};
 685
 686static void aes_register_types(void)
 687{
 688    type_register_static(&aes_info);
 689    type_register_static(&csu_devkey_sink_info);
 690}
 691
 692type_init(aes_register_types)
 693