blob: 6de70f611e046ddf41d24765825490e968130303 [file] [log] [blame]
Kevin O'Connore7cc7642009-10-04 10:05:16 -04001// Paravirtualization support.
2//
Kevin O'Connorb840ba92013-02-09 20:09:22 -05003// Copyright (C) 2013 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connore7cc7642009-10-04 10:05:16 -04004// Copyright (C) 2009 Red Hat Inc.
5//
6// Authors:
7// Gleb Natapov <gnatapov@redhat.com>
8//
9// This file may be distributed under the terms of the GNU LGPLv3 license.
10
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040011#include "byteorder.h" // be32_to_cpu
12#include "config.h" // CONFIG_QEMU
Kevin O'Connorc167e542015-09-29 09:40:46 -040013#include "e820map.h" // e820_add
Kevin O'Connor4d8510c2016-02-03 01:28:20 -050014#include "hw/pci.h" // pci_config_readw
15#include "hw/pcidevice.h" // pci_probe_devices
Gerd Hoffmannebfece82013-09-03 11:41:01 +020016#include "hw/pci_regs.h" // PCI_DEVICE_ID
Kevin O'Connor8b7861c2013-09-15 02:29:06 -040017#include "hw/rtc.h" // CMOS_*
Kevin O'Connor9dea5902013-09-14 20:23:54 -040018#include "malloc.h" // malloc_tmp
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040019#include "output.h" // dprintf
20#include "paravirt.h" // qemu_cfg_preinit
Kevin O'Connor41639f82013-09-14 19:37:36 -040021#include "romfile.h" // romfile_loadint
Kevin O'Connor836b4d82014-04-07 15:42:04 -040022#include "romfile_loader.h" // romfile_loader_execute
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040023#include "string.h" // memset
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040024#include "util.h" // pci_setup
Kevin O'Connorb9c6a962013-09-14 13:01:30 -040025#include "x86.h" // cpuid
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040026#include "xen.h" // xen_biostable_setup
Marc Marí06316c92015-10-08 17:03:26 +020027#include "stacks.h" // yield
Kevin O'Connore7cc7642009-10-04 10:05:16 -040028
Kevin O'Connorf85e4bc2013-02-19 01:33:45 -050029// Amount of continuous ram under 4Gig
30u32 RamSize;
31// Amount of continuous ram >4Gig
32u64 RamSizeOver4G;
Kevin O'Connor89a2f962013-02-18 23:36:03 -050033// Type of emulator platform.
34int PlatformRunningOn VARFSEG;
Marc Marí06316c92015-10-08 17:03:26 +020035// cfg_dma enabled
36int cfg_dma_enabled = 0;
37
38inline int qemu_cfg_dma_enabled(void)
39{
40 return cfg_dma_enabled;
41}
Kevin O'Connor89a2f962013-02-18 23:36:03 -050042
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050043/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
44 * should be used to determine that a VM is running under KVM.
45 */
46#define KVM_CPUID_SIGNATURE 0x40000000
47
Gerd Hoffmannebfece82013-09-03 11:41:01 +020048static void kvm_detect(void)
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050049{
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050050 unsigned int eax, ebx, ecx, edx;
51 char signature[13];
52
53 cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
54 memcpy(signature + 0, &ebx, 4);
55 memcpy(signature + 4, &ecx, 4);
56 memcpy(signature + 8, &edx, 4);
57 signature[12] = 0;
58
59 if (strcmp(signature, "KVMKVMKVM") == 0) {
60 dprintf(1, "Running on KVM\n");
61 PlatformRunningOn |= PF_KVM;
62 }
63}
64
Gerd Hoffmannebfece82013-09-03 11:41:01 +020065static void qemu_detect(void)
66{
67 if (!CONFIG_QEMU_HARDWARE)
68 return;
69
70 // check northbridge @ 00:00.0
71 u16 v = pci_config_readw(0, PCI_VENDOR_ID);
72 if (v == 0x0000 || v == 0xffff)
73 return;
74 u16 d = pci_config_readw(0, PCI_DEVICE_ID);
75 u16 sv = pci_config_readw(0, PCI_SUBSYSTEM_VENDOR_ID);
76 u16 sd = pci_config_readw(0, PCI_SUBSYSTEM_ID);
77
78 if (sv != 0x1af4 || /* Red Hat, Inc */
79 sd != 0x1100) /* Qemu virtual machine */
80 return;
81
82 PlatformRunningOn |= PF_QEMU;
83 switch (d) {
84 case 0x1237:
85 dprintf(1, "Running on QEMU (i440fx)\n");
86 break;
87 case 0x29c0:
88 dprintf(1, "Running on QEMU (q35)\n");
89 break;
90 default:
91 dprintf(1, "Running on QEMU (unknown nb: %04x:%04x)\n", v, d);
92 break;
93 }
94 kvm_detect();
95}
96
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050097void
Kevin O'Connora2a86e22013-02-13 19:35:12 -050098qemu_preinit(void)
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050099{
Gerd Hoffmannebfece82013-09-03 11:41:01 +0200100 qemu_detect();
101
Kevin O'Connor02313b22013-02-07 22:42:25 -0500102 if (!CONFIG_QEMU)
103 return;
104
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500105 if (runningOnXen()) {
106 xen_ramsize_preinit();
107 return;
108 }
109
Gerd Hoffmannebfece82013-09-03 11:41:01 +0200110 if (!runningOnQEMU()) {
111 dprintf(1, "Warning: No QEMU Northbridge found (isapc?)\n");
112 PlatformRunningOn |= PF_QEMU;
113 kvm_detect();
114 }
Kevin O'Connor02313b22013-02-07 22:42:25 -0500115
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500116 // On emulators, get memory size from nvram.
Kevin O'Connor8b7861c2013-09-15 02:29:06 -0400117 u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16)
118 | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24));
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500119 if (rs)
120 rs += 16 * 1024 * 1024;
121 else
Kevin O'Connor8b7861c2013-09-15 02:29:06 -0400122 rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10)
123 | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18))
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500124 + 1 * 1024 * 1024);
125 RamSize = rs;
Kevin O'Connorc167e542015-09-29 09:40:46 -0400126 e820_add(0, rs, E820_RAM);
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500127
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500128 /* reserve 256KB BIOS area at the end of 4 GB */
Kevin O'Connorc167e542015-09-29 09:40:46 -0400129 e820_add(0xfffc0000, 256*1024, E820_RESERVED);
Kevin O'Connorf85e4bc2013-02-19 01:33:45 -0500130
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200131 dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize);
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500132}
133
Haozhong Zhang20f83d52016-06-22 14:53:24 +0800134#define MSR_IA32_FEATURE_CONTROL 0x0000003a
135
136static void msr_feature_control_setup(void)
137{
138 u64 feature_control_bits = romfile_loadint("etc/msr_feature_control", 0);
139 if (feature_control_bits)
140 wrmsr_smp(MSR_IA32_FEATURE_CONTROL, feature_control_bits);
141}
142
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500143void
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500144qemu_platform_setup(void)
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500145{
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500146 if (!CONFIG_QEMU)
147 return;
148
149 if (runningOnXen()) {
150 pci_probe_devices();
151 xen_hypercall_setup();
152 xen_biostable_setup();
153 return;
154 }
155
156 // Initialize pci
157 pci_setup();
Kevin O'Connorcdbac7f2013-03-08 19:33:39 -0500158 smm_device_setup();
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500159 smm_setup();
160
Haozhong Zhang20f83d52016-06-22 14:53:24 +0800161 // Initialize mtrr, msr_feature_control and smp
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500162 mtrr_setup();
Haozhong Zhang20f83d52016-06-22 14:53:24 +0800163 msr_feature_control_setup();
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500164 smp_setup();
165
166 // Create bios tables
Igor Mammedovf7695892016-10-13 14:38:25 +0200167 if (MaxCountCPUs <= 255) {
168 pirtable_setup();
169 mptable_setup();
170 }
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500171 smbios_setup();
Kevin O'Connor836b4d82014-04-07 15:42:04 -0400172
173 if (CONFIG_FW_ROMFILE_LOAD) {
174 int loader_err;
175
176 dprintf(3, "load ACPI tables\n");
177
178 loader_err = romfile_loader_execute("etc/table-loader");
179
180 RsdpAddr = find_acpi_rsdp();
181
182 if (RsdpAddr)
183 return;
184
185 /* If present, loader should have installed an RSDP.
186 * Not installed? We might still be able to continue
187 * using the builtin RSDP.
188 */
189 if (!loader_err)
190 warn_internalerror();
191 }
192
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500193 acpi_setup();
194}
195
Kevin O'Connor4edda082013-02-09 13:21:08 -0500196
197/****************************************************************
198 * QEMU firmware config (fw_cfg) interface
199 ****************************************************************/
200
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500201// List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content
202// should be passed via the fw_cfg "file" interface.)
Kevin O'Connor4edda082013-02-09 13:21:08 -0500203#define QEMU_CFG_SIGNATURE 0x00
204#define QEMU_CFG_ID 0x01
205#define QEMU_CFG_UUID 0x02
206#define QEMU_CFG_NUMA 0x0d
207#define QEMU_CFG_BOOT_MENU 0x0e
Igor Mammedov88916972016-11-11 16:35:15 +0100208#define QEMU_CFG_NB_CPUS 0x05
Kevin O'Connor4edda082013-02-09 13:21:08 -0500209#define QEMU_CFG_MAX_CPUS 0x0f
210#define QEMU_CFG_FILE_DIR 0x19
211#define QEMU_CFG_ARCH_LOCAL 0x8000
212#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
213#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
214#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
215#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3)
216
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400217static void
218qemu_cfg_select(u16 f)
219{
220 outw(f, PORT_QEMU_CFG_CTL);
221}
222
223static void
Marc Marí06316c92015-10-08 17:03:26 +0200224qemu_cfg_dma_transfer(void *address, u32 length, u32 control)
225{
226 QemuCfgDmaAccess access;
227
228 access.address = cpu_to_be64((u64)(u32)address);
229 access.length = cpu_to_be32(length);
230 access.control = cpu_to_be32(control);
231
232 barrier();
233
234 outl(cpu_to_be32((u32)&access), PORT_QEMU_CFG_DMA_ADDR_LOW);
235
236 while(be32_to_cpu(access.control) & ~QEMU_CFG_DMA_CTL_ERROR) {
237 yield();
238 }
239}
240
241static void
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500242qemu_cfg_read(void *buf, int len)
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400243{
Marc Marí06316c92015-10-08 17:03:26 +0200244 if (len == 0) {
245 return;
246 }
247
248 if (qemu_cfg_dma_enabled()) {
249 qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_READ);
250 } else {
251 insb(PORT_QEMU_CFG_DATA, buf, len);
252 }
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400253}
254
255static void
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400256qemu_cfg_skip(int len)
257{
Marc Marí06316c92015-10-08 17:03:26 +0200258 if (len == 0) {
259 return;
260 }
261
262 if (qemu_cfg_dma_enabled()) {
263 qemu_cfg_dma_transfer(0, len, QEMU_CFG_DMA_CTL_SKIP);
264 } else {
265 while (len--)
266 inb(PORT_QEMU_CFG_DATA);
267 }
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400268}
269
270static void
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400271qemu_cfg_read_entry(void *buf, int e, int len)
272{
Marc Marí06316c92015-10-08 17:03:26 +0200273 if (qemu_cfg_dma_enabled()) {
274 u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
275 | QEMU_CFG_DMA_CTL_READ;
276 qemu_cfg_dma_transfer(buf, len, control);
277 } else {
278 qemu_cfg_select(e);
279 qemu_cfg_read(buf, len);
280 }
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400281}
282
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400283struct qemu_romfile_s {
284 struct romfile_s file;
285 int select, skip;
286};
287
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500288static int
289qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen)
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100290{
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400291 if (file->size > maxlen)
292 return -1;
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400293 struct qemu_romfile_s *qfile;
294 qfile = container_of(file, struct qemu_romfile_s, file);
Marc Marí06316c92015-10-08 17:03:26 +0200295 if (qfile->skip == 0) {
296 /* Do it in one transfer */
297 qemu_cfg_read_entry(dst, qfile->select, file->size);
298 } else {
299 qemu_cfg_select(qfile->select);
300 qemu_cfg_skip(qfile->skip);
301 qemu_cfg_read(dst, file->size);
302 }
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400303 return file->size;
304}
305
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500306static void
307qemu_romfile_add(char *name, int select, int skip, int size)
308{
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400309 struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile));
310 if (!qfile) {
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500311 warn_noalloc();
312 return;
313 }
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400314 memset(qfile, 0, sizeof(*qfile));
315 strtcpy(qfile->file.name, name, sizeof(qfile->file.name));
316 qfile->file.size = size;
317 qfile->select = select;
318 qfile->skip = skip;
319 qfile->file.copy = qemu_cfg_read_file;
320 romfile_add(&qfile->file);
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500321}
322
Igor Mammedov023b1d02016-10-13 14:38:27 +0200323u16
324qemu_get_present_cpus_count(void)
325{
Igor Mammedov88916972016-11-11 16:35:15 +0100326 u16 smp_count = 0;
327 qemu_cfg_read_entry(&smp_count, QEMU_CFG_NB_CPUS, sizeof(smp_count));
328 u16 cmos_cpu_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1;
329 if (smp_count < cmos_cpu_count) {
330 smp_count = cmos_cpu_count;
Igor Mammedov023b1d02016-10-13 14:38:27 +0200331 }
332 return smp_count;
333}
334
Kevin O'Connorfe090302013-02-09 20:00:06 -0500335struct e820_reservation {
336 u64 address;
337 u64 length;
338 u32 type;
339};
340
Kevin O'Connorde9e7052013-02-09 19:09:20 -0500341#define SMBIOS_FIELD_ENTRY 0
342#define SMBIOS_TABLE_ENTRY 1
343
344struct qemu_smbios_header {
345 u16 length;
346 u8 headertype;
347 u8 tabletype;
348 u16 fieldoffset;
349} PACKED;
350
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200351static void
352qemu_cfg_e820(void)
353{
Gerd Hoffmannce39bd42013-10-18 12:22:36 +0200354 struct e820_reservation *table;
355 int i, size;
356
Gerd Hoffmannb3d4aae2013-12-06 13:27:09 +0100357 if (!CONFIG_QEMU)
358 return;
359
Gerd Hoffmannce39bd42013-10-18 12:22:36 +0200360 // "etc/e820" has both ram and reservations
361 table = romfile_loadfile("etc/e820", &size);
362 if (table) {
363 for (i = 0; i < size / sizeof(struct e820_reservation); i++) {
364 switch (table[i].type) {
365 case E820_RAM:
366 dprintf(1, "RamBlock: addr 0x%016llx len 0x%016llx [e820]\n",
367 table[i].address, table[i].length);
368 if (table[i].address < RamSize)
369 // ignore, preinit got it from cmos already and
370 // adding this again would ruin any reservations
371 // done so far
372 continue;
373 if (table[i].address < 0x100000000LL) {
374 // below 4g -- adjust RamSize to mark highest lowram addr
375 if (RamSize < table[i].address + table[i].length)
376 RamSize = table[i].address + table[i].length;
377 } else {
378 // above 4g -- adjust RamSizeOver4G to mark highest ram addr
379 if (0x100000000LL + RamSizeOver4G < table[i].address + table[i].length)
380 RamSizeOver4G = table[i].address + table[i].length - 0x100000000LL;
381 }
382 /* fall through */
383 case E820_RESERVED:
Kevin O'Connorc167e542015-09-29 09:40:46 -0400384 e820_add(table[i].address, table[i].length, table[i].type);
Gerd Hoffmannce39bd42013-10-18 12:22:36 +0200385 break;
386 default:
387 /*
388 * Qemu 1.7 uses RAM + RESERVED only. Ignore
389 * everything else, so we have the option to
390 * extend this in the future without breakage.
391 */
392 break;
393 }
394 }
395 return;
396 }
397
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200398 // QEMU_CFG_E820_TABLE has reservations only
399 u32 count32;
400 qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32));
401 if (count32) {
402 struct e820_reservation entry;
403 int i;
404 for (i = 0; i < count32; i++) {
405 qemu_cfg_read(&entry, sizeof(entry));
Kevin O'Connorc167e542015-09-29 09:40:46 -0400406 e820_add(entry.address, entry.length, entry.type);
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200407 }
408 } else if (runningOnKVM()) {
409 // Backwards compatibility - provide hard coded range.
410 // 4 pages before the bios, 3 pages for vmx tss pages, the
411 // other page for EPT real mode pagetable
Kevin O'Connorc167e542015-09-29 09:40:46 -0400412 e820_add(0xfffbc000, 4*4096, E820_RESERVED);
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200413 }
414
415 // Check for memory over 4Gig in cmos
416 u64 high = ((rtc_read(CMOS_MEM_HIGHMEM_LOW) << 16)
417 | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24)
418 | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32));
419 RamSizeOver4G = high;
Kevin O'Connorc167e542015-09-29 09:40:46 -0400420 e820_add(0x100000000ull, high, E820_RAM);
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200421 dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G);
422}
423
Kevin O'Connor188d9942013-02-09 15:24:08 -0500424// Populate romfile entries for legacy fw_cfg ports (that predate the
425// "file" interface).
426static void
427qemu_cfg_legacy(void)
428{
Kevin O'Connor7507ce22013-06-13 20:04:31 -0400429 if (!CONFIG_QEMU)
430 return;
431
Kevin O'Connor56c50892013-02-09 19:25:51 -0500432 // Misc config items.
433 qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2);
434 qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1);
435 qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2);
436
Kevin O'Connorf9e4e372013-02-09 19:45:45 -0500437 // NUMA data
438 u64 numacount;
439 qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount));
Kevin O'Connorfb76cff2013-03-23 11:38:45 -0400440 int max_cpu = romfile_loadint("etc/max-cpus", 0);
441 qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount)
442 , max_cpu*sizeof(u64));
443 qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA
444 , sizeof(numacount) + max_cpu*sizeof(u64)
Kevin O'Connorf9e4e372013-02-09 19:45:45 -0500445 , numacount*sizeof(u64));
446
Kevin O'Connor188d9942013-02-09 15:24:08 -0500447 // ACPI tables
448 char name[128];
449 u16 cnt;
450 qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
451 int i, offset = sizeof(cnt);
452 for (i = 0; i < cnt; i++) {
453 u16 len;
454 qemu_cfg_read(&len, sizeof(len));
455 offset += sizeof(len);
456 snprintf(name, sizeof(name), "acpi/table%d", i);
457 qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len);
458 qemu_cfg_skip(len);
459 offset += len;
460 }
Kevin O'Connorde9e7052013-02-09 19:09:20 -0500461
462 // SMBIOS info
463 qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
464 offset = sizeof(cnt);
465 for (i = 0; i < cnt; i++) {
466 struct qemu_smbios_header header;
467 qemu_cfg_read(&header, sizeof(header));
468 if (header.headertype == SMBIOS_FIELD_ENTRY) {
469 snprintf(name, sizeof(name), "smbios/field%d-%d"
470 , header.tabletype, header.fieldoffset);
471 qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
472 , offset + sizeof(header)
473 , header.length - sizeof(header));
474 } else {
475 snprintf(name, sizeof(name), "smbios/table%d-%d"
476 , header.tabletype, i);
477 qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
478 , offset + 3, header.length - 3);
479 }
480 qemu_cfg_skip(header.length - sizeof(header));
481 offset += header.length;
482 }
Kevin O'Connor188d9942013-02-09 15:24:08 -0500483}
484
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400485struct QemuCfgFile {
486 u32 size; /* file size */
487 u16 select; /* write this to 0x510 to read it */
488 u16 reserved;
489 char name[56];
490};
491
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500492void qemu_cfg_init(void)
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400493{
Kevin O'Connor7507ce22013-06-13 20:04:31 -0400494 if (!runningOnQEMU())
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400495 return;
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100496
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500497 // Detect fw_cfg interface.
498 qemu_cfg_select(QEMU_CFG_SIGNATURE);
499 char *sig = "QEMU";
500 int i;
501 for (i = 0; i < 4; i++)
502 if (inb(PORT_QEMU_CFG_DATA) != sig[i])
503 return;
Marc Marí06316c92015-10-08 17:03:26 +0200504
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500505 dprintf(1, "Found QEMU fw_cfg\n");
506
Marc Marí06316c92015-10-08 17:03:26 +0200507 // Detect DMA interface.
508 u32 id;
509 qemu_cfg_read_entry(&id, QEMU_CFG_ID, sizeof(id));
510
511 if (id & QEMU_CFG_VERSION_DMA) {
512 dprintf(1, "QEMU fw_cfg DMA interface supported\n");
513 cfg_dma_enabled = 1;
514 }
515
Kevin O'Connor188d9942013-02-09 15:24:08 -0500516 // Populate romfiles for legacy fw_cfg entries
517 qemu_cfg_legacy();
518
519 // Load files found in the fw_cfg file directory
Kevin O'Connore2304262010-06-13 16:05:17 -0400520 u32 count;
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100521 qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
Kevin O'Connorb3064592012-08-14 21:20:10 -0400522 count = be32_to_cpu(count);
Kevin O'Connore2304262010-06-13 16:05:17 -0400523 u32 e;
524 for (e = 0; e < count; e++) {
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400525 struct QemuCfgFile qfile;
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500526 qemu_cfg_read(&qfile, sizeof(qfile));
527 qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select)
528 , 0, be32_to_cpu(qfile.size));
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100529 }
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200530
531 qemu_cfg_e820();
Gerd Hoffmann7eac0c42014-05-13 14:09:00 +0200532
533 if (romfile_find("etc/table-loader")) {
534 acpi_pm_base = 0x0600;
535 dprintf(1, "Moving pm_base to 0x%x\n", acpi_pm_base);
536 }
Kevin O'Connor8b565782011-07-05 20:32:44 -0400537}