aboutsummaryrefslogtreecommitdiff
path: root/src/acpi/acpi_dmar.c
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2023-06-22 21:30:58 +0200
committerLean Sheng Tan <sheng.tan@9elements.com>2023-07-21 07:33:37 +0000
commit92a3b67eaea08b54252a5f18b53ce3e287380365 (patch)
treea69c99bd32ad4a0579b6eff693ede6f0b726488b /src/acpi/acpi_dmar.c
parent9c1f78d3e599a62b64a943297ff8693b4b6cacd7 (diff)
acpi/acpi.c: Split of ACPI table generation into separate files
acpi.c contains architectural specific things like IOAPIC, legacy IRQ, DMAR, HPET, ... all which require the presence of architectural headers. Instead of littering the code with #if ENV_X86 move the functions to different compilation units. Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Change-Id: I5083b26c0d4cc6764b4e3cb0ff586797cae7e3af Reviewed-on: https://review.coreboot.org/c/coreboot/+/76008 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Diffstat (limited to 'src/acpi/acpi_dmar.c')
-rw-r--r--src/acpi/acpi_dmar.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/acpi/acpi_dmar.c b/src/acpi/acpi_dmar.c
new file mode 100644
index 0000000000..83a876c287
--- /dev/null
+++ b/src/acpi/acpi_dmar.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <arch/ioapic.h>
+#include <cpu/cpu.h>
+#include <version.h>
+
+void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
+ unsigned long (*acpi_fill_dmar)(unsigned long))
+{
+ acpi_header_t *header = &(dmar->header);
+ unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
+
+ memset((void *)dmar, 0, sizeof(acpi_dmar_t));
+
+ if (!header)
+ return;
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "DMAR", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->asl_compiler_revision = asl_revision;
+ header->length = sizeof(acpi_dmar_t);
+ header->revision = get_acpi_table_revision(DMAR);
+
+ dmar->host_address_width = cpu_phys_address_size() - 1;
+ dmar->flags = flags;
+
+ current = acpi_fill_dmar(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)dmar;
+ header->checksum = acpi_checksum((void *)dmar, header->length);
+}
+
+unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
+ u16 segment, u64 bar)
+{
+ dmar_entry_t *drhd = (dmar_entry_t *)current;
+ memset(drhd, 0, sizeof(*drhd));
+ drhd->type = DMAR_DRHD;
+ drhd->length = sizeof(*drhd); /* will be fixed up later */
+ drhd->flags = flags;
+ drhd->segment = segment;
+ drhd->bar = bar;
+
+ return drhd->length;
+}
+
+unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment,
+ u64 bar, u64 limit)
+{
+ dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)current;
+ memset(rmrr, 0, sizeof(*rmrr));
+ rmrr->type = DMAR_RMRR;
+ rmrr->length = sizeof(*rmrr); /* will be fixed up later */
+ rmrr->segment = segment;
+ rmrr->bar = bar;
+ rmrr->limit = limit;
+
+ return rmrr->length;
+}
+
+unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags,
+ u16 segment)
+{
+ dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)current;
+ memset(atsr, 0, sizeof(*atsr));
+ atsr->type = DMAR_ATSR;
+ atsr->length = sizeof(*atsr); /* will be fixed up later */
+ atsr->flags = flags;
+ atsr->segment = segment;
+
+ return atsr->length;
+}
+
+unsigned long acpi_create_dmar_rhsa(unsigned long current, u64 base_addr,
+ u32 proximity_domain)
+{
+ dmar_rhsa_entry_t *rhsa = (dmar_rhsa_entry_t *)current;
+ memset(rhsa, 0, sizeof(*rhsa));
+ rhsa->type = DMAR_RHSA;
+ rhsa->length = sizeof(*rhsa);
+ rhsa->base_address = base_addr;
+ rhsa->proximity_domain = proximity_domain;
+
+ return rhsa->length;
+}
+
+unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
+ const char *device_name)
+{
+ dmar_andd_entry_t *andd = (dmar_andd_entry_t *)current;
+ int andd_len = sizeof(dmar_andd_entry_t) + strlen(device_name) + 1;
+ memset(andd, 0, andd_len);
+ andd->type = DMAR_ANDD;
+ andd->length = andd_len;
+ andd->device_number = device_number;
+ memcpy(&andd->device_name, device_name, strlen(device_name));
+
+ return andd->length;
+}
+
+unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags, u16 segment)
+{
+ dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
+ int satc_len = sizeof(dmar_satc_entry_t);
+ memset(satc, 0, satc_len);
+ satc->type = DMAR_SATC;
+ satc->length = satc_len;
+ satc->flags = flags;
+ satc->segment_number = segment;
+
+ return satc->length;
+}
+
+void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
+{
+ dmar_entry_t *drhd = (dmar_entry_t *)base;
+ drhd->length = current - base;
+}
+
+void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current)
+{
+ dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)base;
+ rmrr->length = current - base;
+}
+
+void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current)
+{
+ dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)base;
+ atsr->length = current - base;
+}
+
+void acpi_dmar_satc_fixup(unsigned long base, unsigned long current)
+{
+ dmar_satc_entry_t *satc = (dmar_satc_entry_t *)base;
+ satc->length = current - base;
+}
+
+static unsigned long acpi_create_dmar_ds(unsigned long current,
+ enum dev_scope_type type, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
+{
+ /* we don't support longer paths yet */
+ const size_t dev_scope_length = sizeof(dev_scope_t) + 2;
+
+ dev_scope_t *ds = (dev_scope_t *)current;
+ memset(ds, 0, dev_scope_length);
+ ds->type = type;
+ ds->length = dev_scope_length;
+ ds->enumeration = enumeration_id;
+ ds->start_bus = bus;
+ ds->path[0].dev = dev;
+ ds->path[0].fn = fn;
+
+ return ds->length;
+}
+
+unsigned long acpi_create_dmar_ds_pci_br(unsigned long current, u8 bus,
+ u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_PCI_SUB, 0, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_pci(unsigned long current, u8 bus,
+ u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_PCI_ENDPOINT, 0, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_ioapic(unsigned long current,
+ u8 enumeration_id, u8 bus, u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,
+ u32 addr, u8 bus, u8 dev, u8 fn)
+{
+ u8 enumeration_id = get_ioapic_id((void *)(uintptr_t)addr);
+ return acpi_create_dmar_ds(current,
+ SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current,
+ u8 enumeration_id, u8 bus, u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_MSI_HPET, enumeration_id, bus, dev, fn);
+}