fw_cfg.c (4139B)
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 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}