acpi_table.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Based on acpi.c from coreboot
  4. *
  5. * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com>
  6. * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
  7. */
  8. #define LOG_CATEGORY LOGC_ACPI
  9. #include <common.h>
  10. #include <bloblist.h>
  11. #include <cpu.h>
  12. #include <dm.h>
  13. #include <log.h>
  14. #include <dm/uclass-internal.h>
  15. #include <mapmem.h>
  16. #include <serial.h>
  17. #include <acpi/acpigen.h>
  18. #include <acpi/acpi_device.h>
  19. #include <acpi/acpi_table.h>
  20. #include <asm/acpi/global_nvs.h>
  21. #include <asm/ioapic.h>
  22. #include <asm/global_data.h>
  23. #include <asm/lapic.h>
  24. #include <asm/mpspec.h>
  25. #include <asm/tables.h>
  26. #include <asm/arch/global_nvs.h>
  27. #include <dm/acpi.h>
  28. #include <linux/err.h>
  29. static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
  30. u8 cpu, u8 apic)
  31. {
  32. lapic->type = ACPI_APIC_LAPIC;
  33. lapic->length = sizeof(struct acpi_madt_lapic);
  34. lapic->flags = LOCAL_APIC_FLAG_ENABLED;
  35. lapic->processor_id = cpu;
  36. lapic->apic_id = apic;
  37. return lapic->length;
  38. }
  39. int acpi_create_madt_lapics(u32 current)
  40. {
  41. struct udevice *dev;
  42. int total_length = 0;
  43. int cpu_num = 0;
  44. for (uclass_find_first_device(UCLASS_CPU, &dev);
  45. dev;
  46. uclass_find_next_device(&dev)) {
  47. struct cpu_plat *plat = dev_get_parent_plat(dev);
  48. int length;
  49. length = acpi_create_madt_lapic(
  50. (struct acpi_madt_lapic *)current, cpu_num++,
  51. plat->cpu_id);
  52. current += length;
  53. total_length += length;
  54. }
  55. return total_length;
  56. }
  57. int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
  58. u32 addr, u32 gsi_base)
  59. {
  60. ioapic->type = ACPI_APIC_IOAPIC;
  61. ioapic->length = sizeof(struct acpi_madt_ioapic);
  62. ioapic->reserved = 0x00;
  63. ioapic->gsi_base = gsi_base;
  64. ioapic->ioapic_id = id;
  65. ioapic->ioapic_addr = addr;
  66. return ioapic->length;
  67. }
  68. int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
  69. u8 bus, u8 source, u32 gsirq, u16 flags)
  70. {
  71. irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
  72. irqoverride->length = sizeof(struct acpi_madt_irqoverride);
  73. irqoverride->bus = bus;
  74. irqoverride->source = source;
  75. irqoverride->gsirq = gsirq;
  76. irqoverride->flags = flags;
  77. return irqoverride->length;
  78. }
  79. int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
  80. u8 cpu, u16 flags, u8 lint)
  81. {
  82. lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
  83. lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
  84. lapic_nmi->flags = flags;
  85. lapic_nmi->processor_id = cpu;
  86. lapic_nmi->lint = lint;
  87. return lapic_nmi->length;
  88. }
  89. static int acpi_create_madt_irq_overrides(u32 current)
  90. {
  91. struct acpi_madt_irqoverride *irqovr;
  92. u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
  93. int length = 0;
  94. irqovr = (void *)current;
  95. length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
  96. irqovr = (void *)(current + length);
  97. length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
  98. return length;
  99. }
  100. __weak u32 acpi_fill_madt(u32 current)
  101. {
  102. current += acpi_create_madt_lapics(current);
  103. current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
  104. io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
  105. current += acpi_create_madt_irq_overrides(current);
  106. return current;
  107. }
  108. int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
  109. {
  110. struct acpi_table_header *header;
  111. struct acpi_madt *madt;
  112. u32 current;
  113. madt = ctx->current;
  114. memset(madt, '\0', sizeof(struct acpi_madt));
  115. header = &madt->header;
  116. /* Fill out header fields */
  117. acpi_fill_header(header, "APIC");
  118. header->length = sizeof(struct acpi_madt);
  119. header->revision = ACPI_MADT_REV_ACPI_3_0;
  120. madt->lapic_addr = LAPIC_DEFAULT_BASE;
  121. madt->flags = ACPI_MADT_PCAT_COMPAT;
  122. current = (u32)madt + sizeof(struct acpi_madt);
  123. current = acpi_fill_madt(current);
  124. /* (Re)calculate length and checksum */
  125. header->length = current - (u32)madt;
  126. header->checksum = table_compute_checksum((void *)madt, header->length);
  127. acpi_add_table(ctx, madt);
  128. acpi_inc(ctx, madt->header.length);
  129. return 0;
  130. }
  131. ACPI_WRITER(5x86, NULL, acpi_write_madt, 0);
  132. /**
  133. * acpi_create_tcpa() - Create a TCPA table
  134. *
  135. * Trusted Computing Platform Alliance Capabilities Table
  136. * TCPA PC Specific Implementation SpecificationTCPA is defined in the PCI
  137. * Firmware Specification 3.0
  138. */
  139. int acpi_write_tcpa(struct acpi_ctx *ctx, const struct acpi_writer *entry)
  140. {
  141. struct acpi_table_header *header;
  142. struct acpi_tcpa *tcpa;
  143. u32 current;
  144. int size = 0x10000; /* Use this as the default size */
  145. void *log;
  146. int ret;
  147. if (!IS_ENABLED(CONFIG_TPM_V1))
  148. return -ENOENT;
  149. if (!CONFIG_IS_ENABLED(BLOBLIST))
  150. return -ENXIO;
  151. tcpa = ctx->current;
  152. header = &tcpa->header;
  153. memset(tcpa, '\0', sizeof(struct acpi_tcpa));
  154. /* Fill out header fields */
  155. acpi_fill_header(header, "TCPA");
  156. header->length = sizeof(struct acpi_tcpa);
  157. header->revision = 1;
  158. ret = bloblist_ensure_size_ret(BLOBLISTT_TCPA_LOG, &size, &log);
  159. if (ret)
  160. return log_msg_ret("blob", ret);
  161. tcpa->platform_class = 0;
  162. tcpa->laml = size;
  163. tcpa->lasa = map_to_sysmem(log);
  164. /* (Re)calculate length and checksum */
  165. current = (u32)tcpa + sizeof(struct acpi_tcpa);
  166. header->length = current - (u32)tcpa;
  167. header->checksum = table_compute_checksum(tcpa, header->length);
  168. acpi_inc(ctx, tcpa->header.length);
  169. acpi_add_table(ctx, tcpa);
  170. return 0;
  171. }
  172. ACPI_WRITER(5tcpa, "TCPA", acpi_write_tcpa, 0);
  173. static int get_tpm2_log(void **ptrp, int *sizep)
  174. {
  175. const int tpm2_default_log_len = 0x10000;
  176. int size;
  177. int ret;
  178. *sizep = 0;
  179. size = tpm2_default_log_len;
  180. ret = bloblist_ensure_size_ret(BLOBLISTT_TPM2_TCG_LOG, &size, ptrp);
  181. if (ret)
  182. return log_msg_ret("blob", ret);
  183. *sizep = size;
  184. return 0;
  185. }
  186. static int acpi_write_tpm2(struct acpi_ctx *ctx,
  187. const struct acpi_writer *entry)
  188. {
  189. struct acpi_table_header *header;
  190. struct acpi_tpm2 *tpm2;
  191. int tpm2_log_len;
  192. void *lasa;
  193. int ret;
  194. if (!IS_ENABLED(CONFIG_TPM_V2))
  195. return log_msg_ret("none", -ENOENT);
  196. tpm2 = ctx->current;
  197. header = &tpm2->header;
  198. memset(tpm2, '\0', sizeof(struct acpi_tpm2));
  199. /*
  200. * Some payloads like SeaBIOS depend on log area to use TPM2.
  201. * Get the memory size and address of TPM2 log area or initialize it.
  202. */
  203. ret = get_tpm2_log(&lasa, &tpm2_log_len);
  204. if (ret)
  205. return log_msg_ret("log", ret);
  206. /* Fill out header fields. */
  207. acpi_fill_header(header, "TPM2");
  208. memcpy(header->aslc_id, ASLC_ID, 4);
  209. header->length = sizeof(struct acpi_tpm2);
  210. header->revision = acpi_get_table_revision(ACPITAB_TPM2);
  211. /* Hard to detect for U-Boot. Just set it to 0 */
  212. tpm2->platform_class = 0;
  213. /* Must be set to 0 for FIFO-interface support */
  214. tpm2->control_area = 0;
  215. tpm2->start_method = 6;
  216. memset(tpm2->msp, 0, sizeof(tpm2->msp));
  217. /* Fill the log area size and start address fields. */
  218. tpm2->laml = tpm2_log_len;
  219. tpm2->lasa = map_to_sysmem(lasa);
  220. /* Calculate checksum. */
  221. header->checksum = table_compute_checksum(tpm2, header->length);
  222. acpi_inc(ctx, tpm2->header.length);
  223. acpi_add_table(ctx, tpm2);
  224. return 0;
  225. }
  226. ACPI_WRITER(5tpm2, "TPM2", acpi_write_tpm2, 0);
  227. int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry)
  228. {
  229. struct serial_device_info serial_info = {0};
  230. ulong serial_address, serial_offset;
  231. struct acpi_table_header *header;
  232. struct acpi_spcr *spcr;
  233. struct udevice *dev;
  234. uint serial_config;
  235. uint serial_width;
  236. int access_size;
  237. int space_id;
  238. int ret = -ENODEV;
  239. spcr = ctx->current;
  240. header = &spcr->header;
  241. memset(spcr, '\0', sizeof(struct acpi_spcr));
  242. /* Fill out header fields */
  243. acpi_fill_header(header, "SPCR");
  244. header->length = sizeof(struct acpi_spcr);
  245. header->revision = 2;
  246. /* Read the device once, here. It is reused below */
  247. dev = gd->cur_serial_dev;
  248. if (dev)
  249. ret = serial_getinfo(dev, &serial_info);
  250. if (ret)
  251. serial_info.type = SERIAL_CHIP_UNKNOWN;
  252. /* Encode chip type */
  253. switch (serial_info.type) {
  254. case SERIAL_CHIP_16550_COMPATIBLE:
  255. spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
  256. break;
  257. case SERIAL_CHIP_UNKNOWN:
  258. default:
  259. spcr->interface_type = ACPI_DBG2_UNKNOWN;
  260. break;
  261. }
  262. /* Encode address space */
  263. switch (serial_info.addr_space) {
  264. case SERIAL_ADDRESS_SPACE_MEMORY:
  265. space_id = ACPI_ADDRESS_SPACE_MEMORY;
  266. break;
  267. case SERIAL_ADDRESS_SPACE_IO:
  268. default:
  269. space_id = ACPI_ADDRESS_SPACE_IO;
  270. break;
  271. }
  272. serial_width = serial_info.reg_width * 8;
  273. serial_offset = serial_info.reg_offset << serial_info.reg_shift;
  274. serial_address = serial_info.addr + serial_offset;
  275. /* Encode register access size */
  276. switch (serial_info.reg_shift) {
  277. case 0:
  278. access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
  279. break;
  280. case 1:
  281. access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
  282. break;
  283. case 2:
  284. access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
  285. break;
  286. case 3:
  287. access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
  288. break;
  289. default:
  290. access_size = ACPI_ACCESS_SIZE_UNDEFINED;
  291. break;
  292. }
  293. debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
  294. /* Fill GAS */
  295. spcr->serial_port.space_id = space_id;
  296. spcr->serial_port.bit_width = serial_width;
  297. spcr->serial_port.bit_offset = 0;
  298. spcr->serial_port.access_size = access_size;
  299. spcr->serial_port.addrl = lower_32_bits(serial_address);
  300. spcr->serial_port.addrh = upper_32_bits(serial_address);
  301. /* Encode baud rate */
  302. switch (serial_info.baudrate) {
  303. case 9600:
  304. spcr->baud_rate = 3;
  305. break;
  306. case 19200:
  307. spcr->baud_rate = 4;
  308. break;
  309. case 57600:
  310. spcr->baud_rate = 6;
  311. break;
  312. case 115200:
  313. spcr->baud_rate = 7;
  314. break;
  315. default:
  316. spcr->baud_rate = 0;
  317. break;
  318. }
  319. serial_config = SERIAL_DEFAULT_CONFIG;
  320. if (dev)
  321. ret = serial_getconfig(dev, &serial_config);
  322. spcr->parity = SERIAL_GET_PARITY(serial_config);
  323. spcr->stop_bits = SERIAL_GET_STOP(serial_config);
  324. /* No PCI devices for now */
  325. spcr->pci_device_id = 0xffff;
  326. spcr->pci_vendor_id = 0xffff;
  327. /*
  328. * SPCR has no clue if the UART base clock speed is different
  329. * to the default one. However, the SPCR 1.04 defines baud rate
  330. * 0 as a preconfigured state of UART and OS is supposed not
  331. * to touch the configuration of the serial device.
  332. */
  333. if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
  334. spcr->baud_rate = 0;
  335. /* Fix checksum */
  336. header->checksum = table_compute_checksum((void *)spcr, header->length);
  337. acpi_add_table(ctx, spcr);
  338. acpi_inc(ctx, spcr->header.length);
  339. return 0;
  340. }
  341. ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0);
  342. int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry)
  343. {
  344. ulong addr;
  345. if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
  346. int i;
  347. /* We need the DSDT to be done */
  348. if (!ctx->dsdt)
  349. return log_msg_ret("dsdt", -EAGAIN);
  350. /* Pack GNVS into the ACPI table area */
  351. for (i = 0; i < ctx->dsdt->length; i++) {
  352. u32 *gnvs = (u32 *)((u32)ctx->dsdt + i);
  353. if (*gnvs == ACPI_GNVS_ADDR) {
  354. *gnvs = map_to_sysmem(ctx->current);
  355. log_debug("Fix up global NVS in DSDT to %#08x\n",
  356. *gnvs);
  357. break;
  358. }
  359. }
  360. /*
  361. * Recalculate the length and update the DSDT checksum since we
  362. * patched the GNVS address. Set the checksum to zero since it
  363. * is part of the region being checksummed.
  364. */
  365. ctx->dsdt->checksum = 0;
  366. ctx->dsdt->checksum = table_compute_checksum((void *)ctx->dsdt,
  367. ctx->dsdt->length);
  368. }
  369. /* Fill in platform-specific global NVS variables */
  370. addr = acpi_create_gnvs(ctx->current);
  371. if (IS_ERR_VALUE(addr))
  372. return log_msg_ret("gnvs", (int)addr);
  373. acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
  374. return 0;
  375. }
  376. ACPI_WRITER(4gnvs, "GNVS", acpi_write_gnvs, 0);
  377. static int acpi_write_fadt(struct acpi_ctx *ctx,
  378. const struct acpi_writer *entry)
  379. {
  380. struct acpi_fadt *fadt;
  381. fadt = ctx->current;
  382. acpi_create_fadt(fadt, ctx->facs, ctx->dsdt);
  383. acpi_add_table(ctx, fadt);
  384. acpi_inc(ctx, sizeof(struct acpi_fadt));
  385. return 0;
  386. }
  387. ACPI_WRITER(5fact, "FADT", acpi_write_fadt, 0);
  388. /**
  389. * acpi_write_hpet() - Write out a HPET table
  390. *
  391. * Write out the table for High-Precision Event Timers
  392. *
  393. * @hpet: Place to put HPET table
  394. */
  395. static int acpi_create_hpet(struct acpi_hpet *hpet)
  396. {
  397. struct acpi_table_header *header = &hpet->header;
  398. struct acpi_gen_regaddr *addr = &hpet->addr;
  399. /*
  400. * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
  401. * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
  402. */
  403. memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
  404. /* Fill out header fields. */
  405. acpi_fill_header(header, "HPET");
  406. header->aslc_revision = ASL_REVISION;
  407. header->length = sizeof(struct acpi_hpet);
  408. header->revision = acpi_get_table_revision(ACPITAB_HPET);
  409. /* Fill out HPET address */
  410. addr->space_id = 0; /* Memory */
  411. addr->bit_width = 64;
  412. addr->bit_offset = 0;
  413. addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
  414. addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
  415. hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
  416. hpet->number = 0;
  417. hpet->min_tick = 0; /* HPET_MIN_TICKS */
  418. header->checksum = table_compute_checksum(hpet,
  419. sizeof(struct acpi_hpet));
  420. return 0;
  421. }
  422. int acpi_write_hpet(struct acpi_ctx *ctx)
  423. {
  424. struct acpi_hpet *hpet;
  425. int ret;
  426. log_debug("ACPI: * HPET\n");
  427. hpet = ctx->current;
  428. acpi_inc_align(ctx, sizeof(struct acpi_hpet));
  429. acpi_create_hpet(hpet);
  430. ret = acpi_add_table(ctx, hpet);
  431. if (ret)
  432. return log_msg_ret("add", ret);
  433. return 0;
  434. }
  435. int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
  436. uint access_size)
  437. {
  438. struct acpi_dbg2_header *dbg2 = ctx->current;
  439. char path[ACPI_PATH_MAX];
  440. struct acpi_gen_regaddr address;
  441. phys_addr_t addr;
  442. int ret;
  443. if (!device_active(dev)) {
  444. log_info("Device not enabled\n");
  445. return -EACCES;
  446. }
  447. /*
  448. * PCI devices don't remember their resource allocation information in
  449. * U-Boot at present. We assume that MMIO is used for the UART and that
  450. * the address space is 32 bytes: ns16550 uses 8 registers of up to
  451. * 32-bits each. This is only for debugging so it is not a big deal.
  452. */
  453. addr = dm_pci_read_bar32(dev, 0);
  454. log_debug("UART addr %lx\n", (ulong)addr);
  455. memset(&address, '\0', sizeof(address));
  456. address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
  457. address.addrl = (uint32_t)addr;
  458. address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
  459. address.access_size = access_size;
  460. ret = acpi_device_path(dev, path, sizeof(path));
  461. if (ret)
  462. return log_msg_ret("path", ret);
  463. acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
  464. ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
  465. acpi_inc_align(ctx, dbg2->header.length);
  466. acpi_add_table(ctx, dbg2);
  467. return 0;
  468. }
  469. void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
  470. void *dsdt)
  471. {
  472. struct acpi_table_header *header = &fadt->header;
  473. memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
  474. acpi_fill_header(header, "FACP");
  475. header->length = sizeof(struct acpi_fadt);
  476. header->revision = 4;
  477. memcpy(header->oem_id, OEM_ID, 6);
  478. memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
  479. memcpy(header->aslc_id, ASLC_ID, 4);
  480. header->aslc_revision = 1;
  481. fadt->firmware_ctrl = (unsigned long)facs;
  482. fadt->dsdt = (unsigned long)dsdt;
  483. fadt->x_firmware_ctl_l = (unsigned long)facs;
  484. fadt->x_firmware_ctl_h = 0;
  485. fadt->x_dsdt_l = (unsigned long)dsdt;
  486. fadt->x_dsdt_h = 0;
  487. fadt->preferred_pm_profile = ACPI_PM_MOBILE;
  488. /* Use ACPI 3.0 revision */
  489. fadt->header.revision = 4;
  490. }
  491. void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
  492. u64 bar)
  493. {
  494. struct dmar_entry *drhd = ctx->current;
  495. memset(drhd, '\0', sizeof(*drhd));
  496. drhd->type = DMAR_DRHD;
  497. drhd->length = sizeof(*drhd); /* will be fixed up later */
  498. drhd->flags = flags;
  499. drhd->segment = segment;
  500. drhd->bar = bar;
  501. acpi_inc(ctx, drhd->length);
  502. }
  503. void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
  504. u64 limit)
  505. {
  506. struct dmar_rmrr_entry *rmrr = ctx->current;
  507. memset(rmrr, '\0', sizeof(*rmrr));
  508. rmrr->type = DMAR_RMRR;
  509. rmrr->length = sizeof(*rmrr); /* will be fixed up later */
  510. rmrr->segment = segment;
  511. rmrr->bar = bar;
  512. rmrr->limit = limit;
  513. acpi_inc(ctx, rmrr->length);
  514. }
  515. void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base)
  516. {
  517. struct dmar_entry *drhd = base;
  518. drhd->length = ctx->current - base;
  519. }
  520. void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base)
  521. {
  522. struct dmar_rmrr_entry *rmrr = base;
  523. rmrr->length = ctx->current - base;
  524. }
  525. static int acpi_create_dmar_ds(struct acpi_ctx *ctx, enum dev_scope_type type,
  526. uint enumeration_id, pci_dev_t bdf)
  527. {
  528. /* we don't support longer paths yet */
  529. const size_t dev_scope_length = sizeof(struct dev_scope) + 2;
  530. struct dev_scope *ds = ctx->current;
  531. memset(ds, '\0', dev_scope_length);
  532. ds->type = type;
  533. ds->length = dev_scope_length;
  534. ds->enumeration = enumeration_id;
  535. ds->start_bus = PCI_BUS(bdf);
  536. ds->path[0].dev = PCI_DEV(bdf);
  537. ds->path[0].fn = PCI_FUNC(bdf);
  538. return ds->length;
  539. }
  540. int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf)
  541. {
  542. return acpi_create_dmar_ds(ctx, SCOPE_PCI_SUB, 0, bdf);
  543. }
  544. int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf)
  545. {
  546. return acpi_create_dmar_ds(ctx, SCOPE_PCI_ENDPOINT, 0, bdf);
  547. }
  548. int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
  549. pci_dev_t bdf)
  550. {
  551. return acpi_create_dmar_ds(ctx, SCOPE_IOAPIC, enumeration_id, bdf);
  552. }
  553. int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
  554. pci_dev_t bdf)
  555. {
  556. return acpi_create_dmar_ds(ctx, SCOPE_MSI_HPET, enumeration_id, bdf);
  557. }