2 * libqos fw_cfg support
4 * Copyright IBM, Corp. 2012-2013
5 * Copyright (C) 2013 Red Hat Inc.
8 * Anthony Liguori <aliguori@us.ibm.com>
9 * Markus Armbruster <armbru@redhat.com>
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.
15 #include "qemu/osdep.h"
16 #include "libqos/fw_cfg.h"
18 #include "qemu/bswap.h"
19 #include "hw/nvram/fw_cfg.h"
21 void qfw_cfg_select(QFWCFG
*fw_cfg
, uint16_t key
)
23 fw_cfg
->select(fw_cfg
, key
);
26 void qfw_cfg_read_data(QFWCFG
*fw_cfg
, void *data
, size_t len
)
28 fw_cfg
->read(fw_cfg
, data
, len
);
31 void qfw_cfg_get(QFWCFG
*fw_cfg
, uint16_t key
, void *data
, size_t len
)
33 qfw_cfg_select(fw_cfg
, key
);
34 qfw_cfg_read_data(fw_cfg
, data
, len
);
37 uint16_t qfw_cfg_get_u16(QFWCFG
*fw_cfg
, uint16_t key
)
40 qfw_cfg_get(fw_cfg
, key
, &value
, sizeof(value
));
41 return le16_to_cpu(value
);
44 uint32_t qfw_cfg_get_u32(QFWCFG
*fw_cfg
, uint16_t key
)
47 qfw_cfg_get(fw_cfg
, key
, &value
, sizeof(value
));
48 return le32_to_cpu(value
);
51 uint64_t qfw_cfg_get_u64(QFWCFG
*fw_cfg
, uint16_t key
)
54 qfw_cfg_get(fw_cfg
, key
, &value
, sizeof(value
));
55 return le64_to_cpu(value
);
58 static void mm_fw_cfg_select(QFWCFG
*fw_cfg
, uint16_t key
)
60 qtest_writew(fw_cfg
->qts
, fw_cfg
->base
, key
);
64 * The caller need check the return value. When the return value is
65 * nonzero, it means that some bytes have been transferred.
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.
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.
75 size_t qfw_cfg_get_file(QFWCFG
*fw_cfg
, const char *filename
,
76 void *data
, size_t buflen
)
80 unsigned char *filesbuf
= NULL
;
82 FWCfgFile
*pdir_entry
;
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
);
99 qfw_cfg_get(fw_cfg
, sel
, data
, len
);
107 static void mm_fw_cfg_read(QFWCFG
*fw_cfg
, void *data
, size_t len
)
112 for (i
= 0; i
< len
; i
++) {
113 ptr
[i
] = qtest_readb(fw_cfg
->qts
, fw_cfg
->base
+ 2);
117 QFWCFG
*mm_fw_cfg_init(QTestState
*qts
, uint64_t base
)
119 QFWCFG
*fw_cfg
= g_malloc0(sizeof(*fw_cfg
));
123 fw_cfg
->select
= mm_fw_cfg_select
;
124 fw_cfg
->read
= mm_fw_cfg_read
;
129 void mm_fw_cfg_uninit(QFWCFG
*fw_cfg
)
134 static void io_fw_cfg_select(QFWCFG
*fw_cfg
, uint16_t key
)
136 qtest_outw(fw_cfg
->qts
, fw_cfg
->base
, key
);
139 static void io_fw_cfg_read(QFWCFG
*fw_cfg
, void *data
, size_t len
)
144 for (i
= 0; i
< len
; i
++) {
145 ptr
[i
] = qtest_inb(fw_cfg
->qts
, fw_cfg
->base
+ 1);
149 QFWCFG
*io_fw_cfg_init(QTestState
*qts
, uint16_t base
)
151 QFWCFG
*fw_cfg
= g_malloc0(sizeof(*fw_cfg
));
155 fw_cfg
->select
= io_fw_cfg_select
;
156 fw_cfg
->read
= io_fw_cfg_read
;
161 void io_fw_cfg_uninit(QFWCFG
*fw_cfg
)