cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

core.c (6299B)


      1/*
      2 * SD card bus interface code.
      3 *
      4 * Copyright (c) 2015 Linaro Limited
      5 *
      6 * Author:
      7 *  Peter Maydell <peter.maydell@linaro.org>
      8 *
      9 * This program is free software; you can redistribute it and/or modify it
     10 * under the terms and conditions of the GNU General Public License,
     11 * version 2 or later, as published by the Free Software Foundation.
     12 *
     13 * This program is distributed in the hope it will be useful, but WITHOUT
     14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     16 * more details.
     17 *
     18 * You should have received a copy of the GNU General Public License along with
     19 * this program.  If not, see <http://www.gnu.org/licenses/>.
     20 */
     21
     22#include "qemu/osdep.h"
     23#include "hw/qdev-core.h"
     24#include "hw/sd/sd.h"
     25#include "qemu/module.h"
     26#include "qapi/error.h"
     27#include "trace.h"
     28
     29static inline const char *sdbus_name(SDBus *sdbus)
     30{
     31    return sdbus->qbus.name;
     32}
     33
     34static SDState *get_card(SDBus *sdbus)
     35{
     36    /* We only ever have one child on the bus so just return it */
     37    BusChild *kid = QTAILQ_FIRST(&sdbus->qbus.children);
     38
     39    if (!kid) {
     40        return NULL;
     41    }
     42    return SD_CARD(kid->child);
     43}
     44
     45uint8_t sdbus_get_dat_lines(SDBus *sdbus)
     46{
     47    SDState *slave = get_card(sdbus);
     48    uint8_t dat_lines = 0b1111; /* 4 bit bus width */
     49
     50    if (slave) {
     51        SDCardClass *sc = SD_CARD_GET_CLASS(slave);
     52
     53        if (sc->get_dat_lines) {
     54            dat_lines = sc->get_dat_lines(slave);
     55        }
     56    }
     57    trace_sdbus_get_dat_lines(sdbus_name(sdbus), dat_lines);
     58
     59    return dat_lines;
     60}
     61
     62bool sdbus_get_cmd_line(SDBus *sdbus)
     63{
     64    SDState *slave = get_card(sdbus);
     65    bool cmd_line = true;
     66
     67    if (slave) {
     68        SDCardClass *sc = SD_CARD_GET_CLASS(slave);
     69
     70        if (sc->get_cmd_line) {
     71            cmd_line = sc->get_cmd_line(slave);
     72        }
     73    }
     74    trace_sdbus_get_cmd_line(sdbus_name(sdbus), cmd_line);
     75
     76    return cmd_line;
     77}
     78
     79void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
     80{
     81    SDState *card = get_card(sdbus);
     82
     83    trace_sdbus_set_voltage(sdbus_name(sdbus), millivolts);
     84    if (card) {
     85        SDCardClass *sc = SD_CARD_GET_CLASS(card);
     86
     87        assert(sc->set_voltage);
     88        sc->set_voltage(card, millivolts);
     89    }
     90}
     91
     92int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
     93{
     94    SDState *card = get_card(sdbus);
     95
     96    trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg);
     97    if (card) {
     98        SDCardClass *sc = SD_CARD_GET_CLASS(card);
     99
    100        return sc->do_command(card, req, response);
    101    }
    102
    103    return 0;
    104}
    105
    106void sdbus_write_byte(SDBus *sdbus, uint8_t value)
    107{
    108    SDState *card = get_card(sdbus);
    109
    110    trace_sdbus_write(sdbus_name(sdbus), value);
    111    if (card) {
    112        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    113
    114        sc->write_byte(card, value);
    115    }
    116}
    117
    118void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length)
    119{
    120    SDState *card = get_card(sdbus);
    121    const uint8_t *data = buf;
    122
    123    if (card) {
    124        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    125
    126        for (size_t i = 0; i < length; i++) {
    127            trace_sdbus_write(sdbus_name(sdbus), data[i]);
    128            sc->write_byte(card, data[i]);
    129        }
    130    }
    131}
    132
    133uint8_t sdbus_read_byte(SDBus *sdbus)
    134{
    135    SDState *card = get_card(sdbus);
    136    uint8_t value = 0;
    137
    138    if (card) {
    139        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    140
    141        value = sc->read_byte(card);
    142    }
    143    trace_sdbus_read(sdbus_name(sdbus), value);
    144
    145    return value;
    146}
    147
    148void sdbus_read_data(SDBus *sdbus, void *buf, size_t length)
    149{
    150    SDState *card = get_card(sdbus);
    151    uint8_t *data = buf;
    152
    153    if (card) {
    154        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    155
    156        for (size_t i = 0; i < length; i++) {
    157            data[i] = sc->read_byte(card);
    158            trace_sdbus_read(sdbus_name(sdbus), data[i]);
    159        }
    160    }
    161}
    162
    163bool sdbus_receive_ready(SDBus *sdbus)
    164{
    165    SDState *card = get_card(sdbus);
    166
    167    if (card) {
    168        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    169
    170        return sc->receive_ready(card);
    171    }
    172
    173    return false;
    174}
    175
    176bool sdbus_data_ready(SDBus *sdbus)
    177{
    178    SDState *card = get_card(sdbus);
    179
    180    if (card) {
    181        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    182
    183        return sc->data_ready(card);
    184    }
    185
    186    return false;
    187}
    188
    189bool sdbus_get_inserted(SDBus *sdbus)
    190{
    191    SDState *card = get_card(sdbus);
    192
    193    if (card) {
    194        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    195
    196        return sc->get_inserted(card);
    197    }
    198
    199    return false;
    200}
    201
    202bool sdbus_get_readonly(SDBus *sdbus)
    203{
    204    SDState *card = get_card(sdbus);
    205
    206    if (card) {
    207        SDCardClass *sc = SD_CARD_GET_CLASS(card);
    208
    209        return sc->get_readonly(card);
    210    }
    211
    212    return false;
    213}
    214
    215void sdbus_set_inserted(SDBus *sdbus, bool inserted)
    216{
    217    SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
    218    BusState *qbus = BUS(sdbus);
    219
    220    if (sbc->set_inserted) {
    221        sbc->set_inserted(qbus->parent, inserted);
    222    }
    223}
    224
    225void sdbus_set_readonly(SDBus *sdbus, bool readonly)
    226{
    227    SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
    228    BusState *qbus = BUS(sdbus);
    229
    230    if (sbc->set_readonly) {
    231        sbc->set_readonly(qbus->parent, readonly);
    232    }
    233}
    234
    235void sdbus_reparent_card(SDBus *from, SDBus *to)
    236{
    237    SDState *card = get_card(from);
    238    SDCardClass *sc;
    239    bool readonly;
    240
    241    /* We directly reparent the card object rather than implementing this
    242     * as a hotpluggable connection because we don't want to expose SD cards
    243     * to users as being hotpluggable, and we can get away with it in this
    244     * limited use case. This could perhaps be implemented more cleanly in
    245     * future by adding support to the hotplug infrastructure for "device
    246     * can be hotplugged only via code, not by user".
    247     */
    248
    249    if (!card) {
    250        return;
    251    }
    252
    253    sc = SD_CARD_GET_CLASS(card);
    254    readonly = sc->get_readonly(card);
    255
    256    sdbus_set_inserted(from, false);
    257    qdev_set_parent_bus(DEVICE(card), &to->qbus, &error_abort);
    258    sdbus_set_inserted(to, true);
    259    sdbus_set_readonly(to, readonly);
    260}
    261
    262static const TypeInfo sd_bus_info = {
    263    .name = TYPE_SD_BUS,
    264    .parent = TYPE_BUS,
    265    .instance_size = sizeof(SDBus),
    266    .class_size = sizeof(SDBusClass),
    267};
    268
    269static void sd_bus_register_types(void)
    270{
    271    type_register_static(&sd_bus_info);
    272}
    273
    274type_init(sd_bus_register_types)