qemu/tests/libqos/fw_cfg.c
<<
>>
Prefs
   1/*
   2 * libqos fw_cfg support
   3 *
   4 * Copyright IBM, Corp. 2012-2013
   5 * Copyright (C) 2013 Red Hat Inc.
   6 *
   7 * Authors:
   8 *  Anthony Liguori   <aliguori@us.ibm.com>
   9 *  Markus Armbruster <armbru@redhat.com>
  10 *
  11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  12 * See the COPYING file in the top-level directory.
  13 */
  14
  15#include "qemu/osdep.h"
  16#include "libqos/fw_cfg.h"
  17#include "libqtest.h"
  18#include "qemu/bswap.h"
  19#include "hw/nvram/fw_cfg.h"
  20
  21void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
  22{
  23    fw_cfg->select(fw_cfg, key);
  24}
  25
  26void qfw_cfg_read_data(QFWCFG *fw_cfg, void *data, size_t len)
  27{
  28    fw_cfg->read(fw_cfg, data, len);
  29}
  30
  31void qfw_cfg_get(QFWCFG *fw_cfg, uint16_t key, void *data, size_t len)
  32{
  33    qfw_cfg_select(fw_cfg, key);
  34    qfw_cfg_read_data(fw_cfg, data, len);
  35}
  36
  37uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key)
  38{
  39    uint16_t value;
  40    qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
  41    return le16_to_cpu(value);
  42}
  43
  44uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key)
  45{
  46    uint32_t value;
  47    qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
  48    return le32_to_cpu(value);
  49}
  50
  51uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key)
  52{
  53    uint64_t value;
  54    qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
  55    return le64_to_cpu(value);
  56}
  57
  58static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
  59{
  60    qtest_writew(fw_cfg->qts, fw_cfg->base, key);
  61}
  62
  63/*
  64 * The caller need check the return value. When the return value is
  65 * nonzero, it means that some bytes have been transferred.
  66 *
  67 * If the fw_cfg file in question is smaller than the allocated & passed-in
  68 * buffer, then the buffer has been populated only in part.
  69 *
  70 * If the fw_cfg file in question is larger than the passed-in
  71 * buffer, then the return value explains how much room would have been
  72 * necessary in total. And, while the caller's buffer has been fully
  73 * populated, it has received only a starting slice of the fw_cfg file.
  74 */
  75size_t qfw_cfg_get_file(QFWCFG *fw_cfg, const char *filename,
  76                      void *data, size_t buflen)
  77{
  78    uint32_t count;
  79    uint32_t i;
  80    unsigned char *filesbuf = NULL;
  81    size_t dsize;
  82    FWCfgFile *pdir_entry;
  83    size_t filesize = 0;
  84
  85    qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, &count, sizeof(count));
  86    count = be32_to_cpu(count);
  87    dsize = sizeof(uint32_t) + count * sizeof(struct fw_cfg_file);
  88    filesbuf = g_malloc(dsize);
  89    qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, filesbuf, dsize);
  90    pdir_entry = (FWCfgFile *)(filesbuf + sizeof(uint32_t));
  91    for (i = 0; i < count; ++i, ++pdir_entry) {
  92        if (!strcmp(pdir_entry->name, filename)) {
  93            uint32_t len = be32_to_cpu(pdir_entry->size);
  94            uint16_t sel = be16_to_cpu(pdir_entry->select);
  95            filesize = len;
  96            if (len > buflen) {
  97                len = buflen;
  98            }
  99            qfw_cfg_get(fw_cfg, sel, data, len);
 100            break;
 101        }
 102    }
 103    g_free(filesbuf);
 104    return filesize;
 105}
 106
 107static void mm_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len)
 108{
 109    uint8_t *ptr = data;
 110    int i;
 111
 112    for (i = 0; i < len; i++) {
 113        ptr[i] = qtest_readb(fw_cfg->qts, fw_cfg->base + 2);
 114    }
 115}
 116
 117QFWCFG *mm_fw_cfg_init(QTestState *qts, uint64_t base)
 118{
 119    QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg));
 120
 121    fw_cfg->base = base;
 122    fw_cfg->qts = qts;
 123    fw_cfg->select = mm_fw_cfg_select;
 124    fw_cfg->read = mm_fw_cfg_read;
 125
 126    return fw_cfg;
 127}
 128
 129void mm_fw_cfg_uninit(QFWCFG *fw_cfg)
 130{
 131    g_free(fw_cfg);
 132}
 133
 134static void io_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
 135{
 136    qtest_outw(fw_cfg->qts, fw_cfg->base, key);
 137}
 138
 139static void io_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len)
 140{
 141    uint8_t *ptr = data;
 142    int i;
 143
 144    for (i = 0; i < len; i++) {
 145        ptr[i] = qtest_inb(fw_cfg->qts, fw_cfg->base + 1);
 146    }
 147}
 148
 149QFWCFG *io_fw_cfg_init(QTestState *qts, uint16_t base)
 150{
 151    QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg));
 152
 153    fw_cfg->base = base;
 154    fw_cfg->qts = qts;
 155    fw_cfg->select = io_fw_cfg_select;
 156    fw_cfg->read = io_fw_cfg_read;
 157
 158    return fw_cfg;
 159}
 160
 161void io_fw_cfg_uninit(QFWCFG *fw_cfg)
 162{
 163    g_free(fw_cfg);
 164}
 165