Guest User

Untitled

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