qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

fw_cfg.c (4142B)


      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 "fw_cfg.h"
     17 #include "../libqtest.h"
     18 #include "qemu/bswap.h"
     19 #include "hw/nvram/fw_cfg.h"
     20 
     21 void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
     22 {
     23     fw_cfg->select(fw_cfg, key);
     24 }
     25 
     26 void qfw_cfg_read_data(QFWCFG *fw_cfg, void *data, size_t len)
     27 {
     28     fw_cfg->read(fw_cfg, data, len);
     29 }
     30 
     31 void 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 
     37 uint16_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 
     44 uint32_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 
     51 uint64_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 
     58 static 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  */
     75 size_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 
    107 static 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 
    117 QFWCFG *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 
    129 void mm_fw_cfg_uninit(QFWCFG *fw_cfg)
    130 {
    131     g_free(fw_cfg);
    132 }
    133 
    134 static void io_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
    135 {
    136     qtest_outw(fw_cfg->qts, fw_cfg->base, key);
    137 }
    138 
    139 static 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 
    149 QFWCFG *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 
    161 void io_fw_cfg_uninit(QFWCFG *fw_cfg)
    162 {
    163     g_free(fw_cfg);
    164 }