1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2004, Intel Corporation.
4 * Copyright (c) 2006, Keir Fraser, XenSource Inc.
5 */
6
7 #include LIBACPI_STDUTILS
8 #include "acpi2_0.h"
9 #include "libacpi.h"
10 #include "ssdt_s3.h"
11 #include "ssdt_s4.h"
12 #include "ssdt_tpm.h"
13 #include "ssdt_tpm2.h"
14 #include "ssdt_pm.h"
15 #include "ssdt_laptop_slate.h"
16 #include <xen/hvm/hvm_info_table.h>
17 #include <xen/hvm/hvm_xs_strings.h>
18 #include <xen/hvm/params.h>
19 #include <xen/memory.h>
20
21 #define ACPI_MAX_SECONDARY_TABLES 16
22
23 #define align16(sz) (((sz) + 15) & ~15)
24 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
25
26 extern struct acpi_20_rsdp Rsdp;
27 extern struct acpi_20_rsdt Rsdt;
28 extern struct acpi_20_xsdt Xsdt;
29 extern struct acpi_fadt Fadt;
30 extern struct acpi_20_facs Facs;
31 extern struct acpi_20_waet Waet;
32
33 /*
34 * Located at ACPI_INFO_PHYSICAL_ADDRESS.
35 *
36 * This must match the Field("BIOS"....) definition in the DSDT.
37 */
38 struct acpi_info {
39 uint8_t com1_present:1; /* 0[0] - System has COM1? */
40 uint8_t com2_present:1; /* 0[1] - System has COM2? */
41 uint8_t lpt1_present:1; /* 0[2] - System has LPT1? */
42 uint8_t hpet_present:1; /* 0[3] - System has HPET? */
43 uint16_t nr_cpus; /* 2 - Number of CPUs */
44 uint32_t pci_min, pci_len; /* 4, 8 - PCI I/O hole boundaries */
45 uint32_t madt_csum_addr; /* 12 - Address of MADT checksum */
46 uint32_t madt_lapic0_addr; /* 16 - Address of first MADT LAPIC struct */
47 uint32_t vm_gid_addr; /* 20 - Address of VM generation id buffer */
48 uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI I/O hole boundaries */
49 };
50
set_checksum(void * table,uint32_t checksum_offset,uint32_t length)51 static void set_checksum(
52 void *table, uint32_t checksum_offset, uint32_t length)
53 {
54 uint8_t *p, sum = 0;
55
56 p = table;
57 p[checksum_offset] = 0;
58
59 while ( length-- )
60 sum = sum + *p++;
61
62 p = table;
63 p[checksum_offset] = -sum;
64 }
65
construct_madt(struct acpi_ctxt * ctxt,const struct acpi_config * config,struct acpi_info * info)66 static struct acpi_20_madt *construct_madt(struct acpi_ctxt *ctxt,
67 const struct acpi_config *config,
68 struct acpi_info *info)
69 {
70 struct acpi_20_madt *madt;
71 struct acpi_20_madt_intsrcovr *intsrcovr;
72 struct acpi_20_madt_ioapic *io_apic;
73 struct acpi_20_madt_lapic *lapic;
74 const struct hvm_info_table *hvminfo = config->hvminfo;
75 int i, sz;
76
77 if ( config->lapic_id == NULL )
78 return NULL;
79
80 sz = sizeof(struct acpi_20_madt);
81 sz += sizeof(struct acpi_20_madt_intsrcovr) * 16;
82 sz += sizeof(struct acpi_20_madt_ioapic);
83 sz += sizeof(struct acpi_20_madt_lapic) * hvminfo->nr_vcpus;
84
85 madt = ctxt->mem_ops.alloc(ctxt, sz, 16);
86 if (!madt) return NULL;
87
88 memset(madt, 0, sizeof(*madt));
89 madt->header.signature = ACPI_2_0_MADT_SIGNATURE;
90 madt->header.revision = ACPI_2_0_MADT_REVISION;
91 fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID);
92 fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID);
93 madt->header.oem_revision = ACPI_OEM_REVISION;
94 madt->header.creator_id = ACPI_CREATOR_ID;
95 madt->header.creator_revision = ACPI_CREATOR_REVISION;
96 madt->lapic_addr = config->lapic_base_address;
97 madt->flags = ACPI_PCAT_COMPAT;
98
99 if ( config->table_flags & ACPI_HAS_IOAPIC )
100 {
101 intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
102 for ( i = 0; i < 16; i++ )
103 {
104 memset(intsrcovr, 0, sizeof(*intsrcovr));
105 intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE;
106 intsrcovr->length = sizeof(*intsrcovr);
107 intsrcovr->source = i;
108
109 if ( i == 0 )
110 {
111 /* ISA IRQ0 routed to IOAPIC GSI 2. */
112 intsrcovr->gsi = 2;
113 intsrcovr->flags = 0x0;
114 }
115 else if ( config->pci_isa_irq_mask & (1U << i) )
116 {
117 /* PCI: active-low level-triggered. */
118 intsrcovr->gsi = i;
119 intsrcovr->flags = 0xf;
120 }
121 else
122 {
123 /* No need for a INT source override structure. */
124 continue;
125 }
126
127 intsrcovr++;
128 }
129
130 io_apic = (struct acpi_20_madt_ioapic *)intsrcovr;
131 memset(io_apic, 0, sizeof(*io_apic));
132 io_apic->type = ACPI_IO_APIC;
133 io_apic->length = sizeof(*io_apic);
134 io_apic->ioapic_id = config->ioapic_id;
135 io_apic->ioapic_addr = config->ioapic_base_address;
136
137 lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
138 }
139 else
140 lapic = (struct acpi_20_madt_lapic *)(madt + 1);
141
142 info->nr_cpus = hvminfo->nr_vcpus;
143 info->madt_lapic0_addr = ctxt->mem_ops.v2p(ctxt, lapic);
144 for ( i = 0; i < hvminfo->nr_vcpus; i++ )
145 {
146 memset(lapic, 0, sizeof(*lapic));
147 lapic->type = ACPI_PROCESSOR_LOCAL_APIC;
148 lapic->length = sizeof(*lapic);
149 /* Processor ID must match processor-object IDs in the DSDT. */
150 lapic->acpi_processor_id = i;
151 lapic->apic_id = config->lapic_id(i);
152 lapic->flags = (test_bit(i, hvminfo->vcpu_online)
153 ? ACPI_LOCAL_APIC_ENABLED : 0);
154 lapic++;
155 }
156
157 madt->header.length = (unsigned char *)lapic - (unsigned char *)madt;
158 set_checksum(madt, offsetof(struct acpi_header, checksum),
159 madt->header.length);
160 info->madt_csum_addr =
161 ctxt->mem_ops.v2p(ctxt, &madt->header.checksum);
162
163 return madt;
164 }
165
construct_hpet(struct acpi_ctxt * ctxt,const struct acpi_config * config)166 static struct acpi_20_hpet *construct_hpet(struct acpi_ctxt *ctxt,
167 const struct acpi_config *config)
168 {
169 struct acpi_20_hpet *hpet;
170
171 hpet = ctxt->mem_ops.alloc(ctxt, sizeof(*hpet), 16);
172 if (!hpet) return NULL;
173
174 memset(hpet, 0, sizeof(*hpet));
175 hpet->header.signature = ACPI_2_0_HPET_SIGNATURE;
176 hpet->header.revision = ACPI_2_0_HPET_REVISION;
177 fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);
178 fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID);
179 hpet->header.oem_revision = ACPI_OEM_REVISION;
180 hpet->header.creator_id = ACPI_CREATOR_ID;
181 hpet->header.creator_revision = ACPI_CREATOR_REVISION;
182 hpet->timer_block_id = 0x8086a201;
183 hpet->addr.address = ACPI_HPET_ADDRESS;
184
185 hpet->header.length = sizeof(*hpet);
186 set_checksum(hpet, offsetof(struct acpi_header, checksum), sizeof(*hpet));
187 return hpet;
188 }
189
construct_waet(struct acpi_ctxt * ctxt,const struct acpi_config * config)190 static struct acpi_20_waet *construct_waet(struct acpi_ctxt *ctxt,
191 const struct acpi_config *config)
192 {
193 struct acpi_20_waet *waet;
194
195 waet = ctxt->mem_ops.alloc(ctxt, sizeof(*waet), 16);
196 if (!waet) return NULL;
197
198 memcpy(waet, &Waet, sizeof(*waet));
199
200 waet->header.length = sizeof(*waet);
201 set_checksum(waet, offsetof(struct acpi_header, checksum), sizeof(*waet));
202
203 return waet;
204 }
205
construct_srat(struct acpi_ctxt * ctxt,const struct acpi_config * config)206 static struct acpi_20_srat *construct_srat(struct acpi_ctxt *ctxt,
207 const struct acpi_config *config)
208 {
209 struct acpi_20_srat *srat;
210 struct acpi_20_srat_processor *processor;
211 struct acpi_20_srat_memory *memory;
212 unsigned int size;
213 void *p;
214 unsigned int i;
215
216 size = sizeof(*srat) + sizeof(*processor) * config->hvminfo->nr_vcpus +
217 sizeof(*memory) * config->numa.nr_vmemranges;
218
219 p = ctxt->mem_ops.alloc(ctxt, size, 16);
220 if ( !p )
221 return NULL;
222
223 srat = memset(p, 0, size);
224 srat->header.signature = ACPI_2_0_SRAT_SIGNATURE;
225 srat->header.revision = ACPI_2_0_SRAT_REVISION;
226 fixed_strcpy(srat->header.oem_id, ACPI_OEM_ID);
227 fixed_strcpy(srat->header.oem_table_id, ACPI_OEM_TABLE_ID);
228 srat->header.oem_revision = ACPI_OEM_REVISION;
229 srat->header.creator_id = ACPI_CREATOR_ID;
230 srat->header.creator_revision = ACPI_CREATOR_REVISION;
231 srat->table_revision = ACPI_SRAT_TABLE_REVISION;
232
233 processor = (struct acpi_20_srat_processor *)(srat + 1);
234 for ( i = 0; i < config->hvminfo->nr_vcpus; i++ )
235 {
236 processor->type = ACPI_PROCESSOR_AFFINITY;
237 processor->length = sizeof(*processor);
238 processor->domain = config->numa.vcpu_to_vnode[i];
239 processor->apic_id = config->lapic_id(i);
240 processor->flags = ACPI_LOCAL_APIC_AFFIN_ENABLED;
241 processor++;
242 }
243
244 memory = (struct acpi_20_srat_memory *)processor;
245 for ( i = 0; i < config->numa.nr_vmemranges; i++ )
246 {
247 memory->type = ACPI_MEMORY_AFFINITY;
248 memory->length = sizeof(*memory);
249 memory->domain = config->numa.vmemrange[i].nid;
250 memory->flags = ACPI_MEM_AFFIN_ENABLED;
251 memory->base_address = config->numa.vmemrange[i].start;
252 memory->mem_length = config->numa.vmemrange[i].end -
253 config->numa.vmemrange[i].start;
254 memory++;
255 }
256
257 ASSERT(((unsigned long)memory) - ((unsigned long)p) == size);
258
259 srat->header.length = size;
260 set_checksum(srat, offsetof(struct acpi_header, checksum), size);
261
262 return srat;
263 }
264
construct_slit(struct acpi_ctxt * ctxt,const struct acpi_config * config)265 static struct acpi_20_slit *construct_slit(struct acpi_ctxt *ctxt,
266 const struct acpi_config *config)
267 {
268 struct acpi_20_slit *slit;
269 unsigned int i, num, size;
270
271 num = config->numa.nr_vnodes * config->numa.nr_vnodes;
272 size = sizeof(*slit) + num * sizeof(uint8_t);
273
274 slit = ctxt->mem_ops.alloc(ctxt, size, 16);
275 if ( !slit )
276 return NULL;
277
278 memset(slit, 0, size);
279 slit->header.signature = ACPI_2_0_SLIT_SIGNATURE;
280 slit->header.revision = ACPI_2_0_SLIT_REVISION;
281 fixed_strcpy(slit->header.oem_id, ACPI_OEM_ID);
282 fixed_strcpy(slit->header.oem_table_id, ACPI_OEM_TABLE_ID);
283 slit->header.oem_revision = ACPI_OEM_REVISION;
284 slit->header.creator_id = ACPI_CREATOR_ID;
285 slit->header.creator_revision = ACPI_CREATOR_REVISION;
286
287 for ( i = 0; i < num; i++ )
288 slit->entry[i] = config->numa.vdistance[i];
289
290 slit->localities = config->numa.nr_vnodes;
291
292 slit->header.length = size;
293 set_checksum(slit, offsetof(struct acpi_header, checksum), size);
294
295 return slit;
296 }
297
construct_passthrough_tables(struct acpi_ctxt * ctxt,unsigned long * table_ptrs,int nr_tables,struct acpi_config * config)298 static int construct_passthrough_tables(struct acpi_ctxt *ctxt,
299 unsigned long *table_ptrs,
300 int nr_tables,
301 struct acpi_config *config)
302 {
303 unsigned long pt_addr;
304 struct acpi_header *header;
305 int nr_added;
306 int nr_max = (ACPI_MAX_SECONDARY_TABLES - nr_tables - 1);
307 uint32_t total = 0;
308 uint8_t *buffer;
309
310 if ( config->pt.addr == 0 )
311 return 0;
312
313 pt_addr = config->pt.addr;
314
315 for ( nr_added = 0; nr_added < nr_max; nr_added++ )
316 {
317 if ( (config->pt.length - total) < sizeof(struct acpi_header) )
318 break;
319
320 header = (struct acpi_header*)pt_addr;
321
322 buffer = ctxt->mem_ops.alloc(ctxt, header->length, 16);
323 if ( buffer == NULL )
324 break;
325 memcpy(buffer, header, header->length);
326
327 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, buffer);
328 total += header->length;
329 pt_addr += header->length;
330 }
331
332 return nr_added;
333 }
334
construct_secondary_tables(struct acpi_ctxt * ctxt,unsigned long * table_ptrs,struct acpi_config * config,struct acpi_info * info)335 static int construct_secondary_tables(struct acpi_ctxt *ctxt,
336 unsigned long *table_ptrs,
337 struct acpi_config *config,
338 struct acpi_info *info)
339 {
340 int nr_tables = 0;
341 struct acpi_20_madt *madt;
342 struct acpi_20_hpet *hpet;
343 struct acpi_20_waet *waet;
344 struct acpi_20_tcpa *tcpa;
345 struct acpi_20_tpm2 *tpm2;
346 unsigned char *ssdt;
347 void *lasa;
348
349 /* MADT. */
350 if ( (config->hvminfo->nr_vcpus > 1) || config->hvminfo->apic_mode )
351 {
352 madt = construct_madt(ctxt, config, info);
353 if (!madt) return -1;
354 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, madt);
355 }
356
357 /* HPET. */
358 if ( info->hpet_present )
359 {
360 hpet = construct_hpet(ctxt, config);
361 if (!hpet) return -1;
362 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, hpet);
363 }
364
365 /* WAET. */
366 if ( config->table_flags & ACPI_HAS_WAET )
367 {
368 waet = construct_waet(ctxt, config);
369 if ( !waet )
370 return -1;
371 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, waet);
372 }
373
374 if ( config->table_flags & ACPI_HAS_SSDT_PM )
375 {
376 ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_pm), 16);
377 if (!ssdt) return -1;
378 memcpy(ssdt, ssdt_pm, sizeof(ssdt_pm));
379 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
380 }
381
382 if ( config->table_flags & ACPI_HAS_SSDT_S3 )
383 {
384 ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_s3), 16);
385 if (!ssdt) return -1;
386 memcpy(ssdt, ssdt_s3, sizeof(ssdt_s3));
387 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
388 }
389
390 if ( config->table_flags & ACPI_HAS_SSDT_S4 )
391 {
392 ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_s4), 16);
393 if (!ssdt) return -1;
394 memcpy(ssdt, ssdt_s4, sizeof(ssdt_s4));
395 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
396 }
397
398 if ( config->table_flags & ACPI_HAS_SSDT_LAPTOP_SLATE )
399 {
400 ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_laptop_slate), 16);
401 if (!ssdt) return -1;
402 memcpy(ssdt, ssdt_laptop_slate, sizeof(ssdt_laptop_slate));
403 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
404 }
405 /* TPM and its SSDT. */
406 if ( config->table_flags & ACPI_HAS_TPM )
407 {
408 switch ( config->tpm_version )
409 {
410 case 1:
411 if ( config->tis_hdr[0] == 0 || config->tis_hdr[0] == 0xffff ||
412 config->tis_hdr[1] == 0 || config->tis_hdr[1] == 0xffff )
413 break;
414
415 ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_tpm), 16);
416 if (!ssdt) return -1;
417 memcpy(ssdt, ssdt_tpm, sizeof(ssdt_tpm));
418 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
419
420 tcpa = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_tcpa), 16);
421 if (!tcpa) return -1;
422 memset(tcpa, 0, sizeof(*tcpa));
423 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, tcpa);
424
425 tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
426 tcpa->header.length = sizeof(*tcpa);
427 tcpa->header.revision = ACPI_2_0_TCPA_REVISION;
428 fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);
429 fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID);
430 tcpa->header.oem_revision = ACPI_OEM_REVISION;
431 tcpa->header.creator_id = ACPI_CREATOR_ID;
432 tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
433
434 lasa = ctxt->mem_ops.alloc(ctxt, ACPI_2_0_TCPA_LAML_SIZE, 16);
435 if ( lasa )
436 {
437 tcpa->lasa = ctxt->mem_ops.v2p(ctxt, lasa);
438 tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
439 memset(lasa, 0, tcpa->laml);
440 set_checksum(tcpa,
441 offsetof(struct acpi_header, checksum),
442 tcpa->header.length);
443 }
444 break;
445
446 case 2:
447 /*
448 * Check VID stored in bits 37:32 (3rd 16 bit word) of CRB
449 * identifier register. See table 16 of TCG PC client platform
450 * TPM profile specification for TPM 2.0.
451 */
452 if ( config->crb_id[2] == 0 || config->crb_id[2] == 0xffff )
453 break;
454
455 ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_tpm2), 16);
456 if (!ssdt) return -1;
457 memcpy(ssdt, ssdt_tpm2, sizeof(ssdt_tpm2));
458 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
459
460 tpm2 = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_tpm2), 16);
461 if (!tpm2) return -1;
462 memset(tpm2, 0, sizeof(*tpm2));
463 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, tpm2);
464
465 tpm2->header.signature = ACPI_2_0_TPM2_SIGNATURE;
466 tpm2->header.length = sizeof(*tpm2);
467 tpm2->header.revision = ACPI_2_0_TPM2_REVISION;
468 fixed_strcpy(tpm2->header.oem_id, ACPI_OEM_ID);
469 fixed_strcpy(tpm2->header.oem_table_id, ACPI_OEM_TABLE_ID);
470 tpm2->header.oem_revision = ACPI_OEM_REVISION;
471 tpm2->header.creator_id = ACPI_CREATOR_ID;
472 tpm2->header.creator_revision = ACPI_CREATOR_REVISION;
473 tpm2->platform_class = TPM2_ACPI_CLASS_CLIENT;
474 tpm2->control_area_address = TPM_CRB_CTRL_REQ;
475 tpm2->start_method = TPM2_START_METHOD_CRB;
476 tpm2->log_area_minimum_length = TPM_LOG_AREA_MINIMUM_SIZE;
477 tpm2->log_area_start_address = TPM_LOG_AREA_ADDRESS;
478
479 set_checksum(tpm2,
480 offsetof(struct acpi_header, checksum),
481 tpm2->header.length);
482 break;
483 }
484 }
485
486 /* SRAT and SLIT */
487 if ( config->numa.nr_vnodes > 0 )
488 {
489 struct acpi_20_srat *srat = construct_srat(ctxt, config);
490 struct acpi_20_slit *slit = construct_slit(ctxt, config);
491
492 if ( srat )
493 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, srat);
494 else
495 printf("Failed to build SRAT, skipping...\n");
496 if ( slit )
497 table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, slit);
498 else
499 printf("Failed to build SLIT, skipping...\n");
500 }
501
502 /* Load any additional tables passed through. */
503 nr_tables += construct_passthrough_tables(ctxt, table_ptrs,
504 nr_tables, config);
505
506 table_ptrs[nr_tables] = 0;
507 return nr_tables;
508 }
509
510 /**
511 * Allocate and initialize Windows Generation ID
512 * If value is not present in the XenStore or if all zeroes
513 * the device will be not active
514 *
515 * Return 0 if memory failure, != 0 if success
516 */
new_vm_gid(struct acpi_ctxt * ctxt,struct acpi_config * config,struct acpi_info * info)517 static int new_vm_gid(struct acpi_ctxt *ctxt,
518 struct acpi_config *config,
519 struct acpi_info *info)
520 {
521 uint64_t *buf;
522
523 info->vm_gid_addr = 0;
524
525 /* check for 0 ID*/
526 if ( !config->vm_gid[0] && !config->vm_gid[1] )
527 return 1;
528
529 /* copy to allocate BIOS memory */
530 buf = ctxt->mem_ops.alloc(ctxt, sizeof(config->vm_gid), 8);
531 if ( !buf )
532 return 0;
533 memcpy(buf, config->vm_gid, sizeof(config->vm_gid));
534
535 /* set the address into ACPI table and also pass it back to the caller */
536 info->vm_gid_addr = ctxt->mem_ops.v2p(ctxt, buf);
537 config->vm_gid_addr = info->vm_gid_addr;
538
539 return 1;
540 }
541
acpi_build_tables(struct acpi_ctxt * ctxt,struct acpi_config * config)542 int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config)
543 {
544 struct acpi_info *acpi_info;
545 struct acpi_20_rsdp *rsdp;
546 struct acpi_20_rsdt *rsdt;
547 struct acpi_20_xsdt *xsdt;
548 struct acpi_fadt *fadt;
549 struct acpi_10_fadt *fadt_10;
550 struct acpi_20_facs *facs;
551 unsigned char *dsdt;
552 unsigned long secondary_tables[ACPI_MAX_SECONDARY_TABLES];
553 int nr_secondaries, i;
554 unsigned int fadt_size;
555
556 acpi_info = (struct acpi_info *)config->infop;
557 memset(acpi_info, 0, sizeof(*acpi_info));
558 acpi_info->com1_present = !!(config->table_flags & ACPI_HAS_COM1);
559 acpi_info->com2_present = !!(config->table_flags & ACPI_HAS_COM2);
560 acpi_info->lpt1_present = !!(config->table_flags & ACPI_HAS_LPT1);
561 acpi_info->hpet_present = !!(config->table_flags & ACPI_HAS_HPET);
562 acpi_info->pci_min = config->pci_start;
563 acpi_info->pci_len = config->pci_len;
564 if ( config->pci_hi_len )
565 {
566 acpi_info->pci_hi_min = config->pci_hi_start;
567 acpi_info->pci_hi_len = config->pci_hi_len;
568 }
569
570 /*
571 * Fill in high-memory data structures, starting at @buf.
572 */
573
574 facs = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_facs), 64);
575 if (!facs) goto oom;
576 memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
577
578 /*
579 * Alternative DSDTs we get linked against. A cover-all DSDT for up to the
580 * implementation-defined maximum number of VCPUs, and an alternative for use
581 * when a guest can only have up to 15 VCPUs.
582 *
583 * The latter is required for Windows 2000, which experiences a BSOD of
584 * KMODE_EXCEPTION_NOT_HANDLED if it sees more than 15 processor objects.
585 */
586 if ( config->hvminfo->nr_vcpus <= 15 && config->dsdt_15cpu)
587 {
588 dsdt = ctxt->mem_ops.alloc(ctxt, config->dsdt_15cpu_len, 16);
589 if (!dsdt) goto oom;
590 memcpy(dsdt, config->dsdt_15cpu, config->dsdt_15cpu_len);
591 }
592 else
593 {
594 dsdt = ctxt->mem_ops.alloc(ctxt, config->dsdt_anycpu_len, 16);
595 if (!dsdt) goto oom;
596 memcpy(dsdt, config->dsdt_anycpu, config->dsdt_anycpu_len);
597 }
598
599 /*
600 * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
601 * or above properly, notably Windows 2000, which tries to copy FADT
602 * into a 116 bytes buffer thus causing an overflow. The solution is to
603 * link the higher revision FADT with the XSDT only and introduce a
604 * compatible revision 1 FADT that is linked with the RSDT. Refer to:
605 * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
606 */
607 fadt_10 = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_10_fadt), 16);
608 if (!fadt_10) goto oom;
609 memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
610 fadt_10->header.length = sizeof(struct acpi_10_fadt);
611 fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
612 fadt_10->dsdt = ctxt->mem_ops.v2p(ctxt, dsdt);
613 fadt_10->firmware_ctrl = ctxt->mem_ops.v2p(ctxt, facs);
614 set_checksum(fadt_10,
615 offsetof(struct acpi_header, checksum),
616 sizeof(struct acpi_10_fadt));
617
618 switch ( config->acpi_revision )
619 {
620 case 4:
621 /*
622 * NB: we can use offsetof because there's no padding between
623 * x_gpe1_blk and sleep_control.
624 */
625 fadt_size = offsetof(struct acpi_fadt, sleep_control);
626 break;
627 case 5:
628 fadt_size = sizeof(*fadt);
629 break;
630 default:
631 printf("ACPI revision %u not supported\n", config->acpi_revision);
632 return -1;
633 }
634 fadt = ctxt->mem_ops.alloc(ctxt, fadt_size, 16);
635 if (!fadt) goto oom;
636 if ( !(config->table_flags & ACPI_HAS_PMTIMER) )
637 {
638 Fadt.pm_tmr_blk = Fadt.pm_tmr_len = 0;
639 memset(&Fadt.x_pm_tmr_blk, 0, sizeof(Fadt.x_pm_tmr_blk));
640 }
641 if ( !(config->table_flags & ACPI_HAS_BUTTONS) )
642 Fadt.flags |= (ACPI_PWR_BUTTON | ACPI_SLP_BUTTON);
643 memcpy(fadt, &Fadt, fadt_size);
644 /*
645 * For both ACPI 4 and 5 the revision of the FADT matches the ACPI
646 * revision.
647 */
648 fadt->header.revision = config->acpi_revision;
649 fadt->header.length = fadt_size;
650 fadt->dsdt = ctxt->mem_ops.v2p(ctxt, dsdt);
651 fadt->x_dsdt = ctxt->mem_ops.v2p(ctxt, dsdt);
652 fadt->firmware_ctrl = ctxt->mem_ops.v2p(ctxt, facs);
653 fadt->x_firmware_ctrl = ctxt->mem_ops.v2p(ctxt, facs);
654 if ( !(config->table_flags & ACPI_HAS_VGA) )
655 fadt->iapc_boot_arch |= ACPI_FADT_NO_VGA;
656 if ( config->table_flags & ACPI_HAS_8042 )
657 fadt->iapc_boot_arch |= ACPI_FADT_8042;
658 if ( !(config->table_flags & ACPI_HAS_CMOS_RTC) )
659 {
660 if ( fadt->header.revision < 5 )
661 {
662 printf("ACPI_FADT_NO_CMOS_RTC requires FADT revision 5\n");
663 return -1;
664 }
665 fadt->iapc_boot_arch |= ACPI_FADT_NO_CMOS_RTC;
666 }
667 set_checksum(fadt, offsetof(struct acpi_header, checksum), fadt_size);
668
669 nr_secondaries = construct_secondary_tables(ctxt, secondary_tables,
670 config, acpi_info);
671 if ( nr_secondaries < 0 )
672 goto oom;
673
674 xsdt = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_xsdt) +
675 sizeof(uint64_t) * nr_secondaries,
676 16);
677 if (!xsdt) goto oom;
678 memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
679 xsdt->entry[0] = ctxt->mem_ops.v2p(ctxt, fadt);
680 for ( i = 0; secondary_tables[i]; i++ )
681 xsdt->entry[i+1] = secondary_tables[i];
682 xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
683 set_checksum(xsdt,
684 offsetof(struct acpi_header, checksum),
685 xsdt->header.length);
686
687 rsdt = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_rsdt) +
688 sizeof(uint32_t) * nr_secondaries,
689 16);
690 if (!rsdt) goto oom;
691 memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
692 rsdt->entry[0] = ctxt->mem_ops.v2p(ctxt, fadt_10);
693 for ( i = 0; secondary_tables[i]; i++ )
694 rsdt->entry[i+1] = secondary_tables[i];
695 rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
696 set_checksum(rsdt,
697 offsetof(struct acpi_header, checksum),
698 rsdt->header.length);
699
700 /*
701 * Fill in low-memory data structures: acpi_info and RSDP.
702 */
703 rsdp = (struct acpi_20_rsdp *)config->rsdp;
704
705 memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
706 rsdp->rsdt_address = ctxt->mem_ops.v2p(ctxt, rsdt);
707 rsdp->xsdt_address = ctxt->mem_ops.v2p(ctxt, xsdt);
708 set_checksum(rsdp,
709 offsetof(struct acpi_10_rsdp, checksum),
710 sizeof(struct acpi_10_rsdp));
711 set_checksum(rsdp,
712 offsetof(struct acpi_20_rsdp, extended_checksum),
713 sizeof(struct acpi_20_rsdp));
714
715 if ( !new_vm_gid(ctxt, config, acpi_info) )
716 goto oom;
717
718 return 0;
719
720 oom:
721 printf("unable to build ACPI tables: out of memory\n");
722 return -1;
723 }
724
725 /*
726 * Local variables:
727 * mode: C
728 * c-file-style: "BSD"
729 * c-basic-offset: 4
730 * tab-width: 4
731 * indent-tabs-mode: nil
732 * End:
733 */
734