summaryrefslogtreecommitdiff
path: root/lib/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'lib/acpi')
-rw-r--r--lib/acpi/acpi.c7
-rw-r--r--lib/acpi/acpi_table.c52
-rw-r--r--lib/acpi/base.c6
-rw-r--r--lib/acpi/csrt.c2
-rw-r--r--lib/acpi/mcfg.c2
-rw-r--r--lib/acpi/ssdt.c2
6 files changed, 50 insertions, 21 deletions
diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c
index f4d5c1e25d0..596301a43fe 100644
--- a/lib/acpi/acpi.c
+++ b/lib/acpi/acpi.c
@@ -6,11 +6,18 @@
*/
#include <mapmem.h>
+#include <tables_csum.h>
#include <acpi/acpi_table.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
+void acpi_update_checksum(struct acpi_table_header *header)
+{
+ header->checksum = 0;
+ header->checksum = table_compute_checksum(header, header->length);
+}
+
struct acpi_table_header *acpi_find_table(const char *sig)
{
struct acpi_rsdp *rsdp;
diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c
index c0ed24984af..43b71182133 100644
--- a/lib/acpi/acpi_table.c
+++ b/lib/acpi/acpi_table.c
@@ -66,6 +66,7 @@ int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags)
dmar->host_address_width = info.address_width - 1;
dmar->flags = flags;
+ header->checksum = table_compute_checksum(dmar, header->length);
return 0;
}
@@ -195,9 +196,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
(sizeof(u32) * (i + 1));
/* Re-calculate checksum */
- rsdt->header.checksum = 0;
- rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
- rsdt->header.length);
+ acpi_update_checksum(&rsdt->header);
}
if (ctx->xsdt) {
@@ -228,9 +227,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
(sizeof(u64) * (i + 1));
/* Re-calculate checksum */
- xsdt->header.checksum = 0;
- xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
- xsdt->header.length);
+ acpi_update_checksum(&xsdt->header);
}
return 0;
@@ -255,8 +252,8 @@ int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
header->creator_revision = 1;
fadt->minor_revision = 2;
- fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
- fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
+ fadt->x_firmware_ctrl = nomap_to_sysmem(ctx->facs);
+ fadt->x_dsdt = nomap_to_sysmem(ctx->dsdt);
if (fadt->x_firmware_ctrl < 0x100000000ULL)
fadt->firmware_ctrl = fadt->x_firmware_ctrl;
@@ -268,7 +265,7 @@ int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
acpi_fill_fadt(fadt);
- header->checksum = table_compute_checksum(fadt, header->length);
+ acpi_update_checksum(header);
return acpi_add_fadt(ctx, fadt);
}
@@ -303,7 +300,7 @@ int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
if (IS_ENABLED(CONFIG_ACPI_PARKING_PROTOCOL))
acpi_write_park(madt);
- header->checksum = table_compute_checksum((void *)madt, header->length);
+ acpi_update_checksum(header);
acpi_add_table(ctx, madt);
ctx->current = (void *)madt + madt->header.length;
@@ -374,7 +371,7 @@ void acpi_create_dbg2(struct acpi_dbg2_header *dbg2,
/* Update structure lengths and checksum */
device->length = current - (uintptr_t)device;
header->length = current - (uintptr_t)dbg2;
- header->checksum = table_compute_checksum(dbg2, header->length);
+ acpi_update_checksum(header);
}
int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
@@ -549,7 +546,7 @@ static int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry
spcr->baud_rate = 0;
/* Fix checksum */
- header->checksum = table_compute_checksum((void *)spcr, header->length);
+ acpi_update_checksum(header);
acpi_add_table(ctx, spcr);
acpi_inc(ctx, spcr->header.length);
@@ -615,6 +612,7 @@ int acpi_iort_add_named_component(struct acpi_ctx *ctx,
node->length += strlen(device_name) + 1;
comp = (struct acpi_iort_named_component *)node->node_data;
+ memset(comp, '\0', sizeof(struct acpi_iort_named_component));
comp->node_flags = node_flags;
comp->memory_properties = memory_properties;
@@ -635,6 +633,7 @@ int acpi_iort_add_rc(struct acpi_ctx *ctx,
const struct acpi_iort_id_mapping *map)
{
struct acpi_iort_id_mapping *mapping;
+ struct acpi_iort_node *output_node;
struct acpi_iort_node *node;
struct acpi_iort_rc *rc;
int offset;
@@ -646,12 +645,18 @@ int acpi_iort_add_rc(struct acpi_ctx *ctx,
node->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
node->revision = 2;
+ node->mapping_count = num_mappings;
+ if (num_mappings)
+ node->mapping_offset = sizeof(struct acpi_iort_node) +
+ sizeof(struct acpi_iort_rc);
node->length = sizeof(struct acpi_iort_node);
node->length += sizeof(struct acpi_iort_rc);
node->length += sizeof(struct acpi_iort_id_mapping) * num_mappings;
rc = (struct acpi_iort_rc *)node->node_data;
+ memset(rc, '\0', sizeof(struct acpi_iort_rc));
+
rc->mem_access_properties = mem_access_properties;
rc->ats_attributes = ats_attributes;
rc->pci_segment_number = pci_segment_number;
@@ -659,6 +664,13 @@ int acpi_iort_add_rc(struct acpi_ctx *ctx,
mapping = (struct acpi_iort_id_mapping *)(rc + 1);
for (int i = 0; i < num_mappings; i++) {
+ /* Validate input */
+ output_node = (struct acpi_iort_node *)ctx->tab_start + map[i].output_reference;
+ /* ID mappings can use SMMUs or ITS groups as output references */
+ assert(output_node && ((output_node->type == ACPI_IORT_NODE_ITS_GROUP) ||
+ (output_node->type == ACPI_IORT_NODE_SMMU) ||
+ (output_node->type == ACPI_IORT_NODE_SMMU_V3)));
+
memcpy(mapping, &map[i], sizeof(struct acpi_iort_id_mapping));
mapping++;
}
@@ -683,6 +695,7 @@ int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
const struct acpi_iort_id_mapping *map)
{
struct acpi_iort_node *node;
+ struct acpi_iort_node *output_node;
struct acpi_iort_smmu_v3 *smmu;
struct acpi_iort_id_mapping *mapping;
int offset;
@@ -695,13 +708,16 @@ int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
node->type = ACPI_IORT_NODE_SMMU_V3;
node->revision = 5;
node->mapping_count = num_mappings;
- node->mapping_offset = sizeof(struct acpi_iort_node) + sizeof(struct acpi_iort_smmu_v3);
+ if (num_mappings)
+ node->mapping_offset = sizeof(struct acpi_iort_node) +
+ sizeof(struct acpi_iort_smmu_v3);
node->length = sizeof(struct acpi_iort_node);
node->length += sizeof(struct acpi_iort_smmu_v3);
node->length += sizeof(struct acpi_iort_id_mapping) * num_mappings;
smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+ memset(smmu, '\0', sizeof(struct acpi_iort_smmu_v3));
smmu->base_address = base_address;
smmu->flags = flags;
@@ -716,6 +732,14 @@ int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
mapping = (struct acpi_iort_id_mapping *)(smmu + 1);
for (int i = 0; i < num_mappings; i++) {
+ /* Validate input */
+ output_node = (struct acpi_iort_node *)ctx->tab_start + map[i].output_reference;
+ /*
+ * ID mappings of an SMMUv3 node can only have ITS group nodes
+ * as output references.
+ */
+ assert(output_node && output_node->type == ACPI_IORT_NODE_ITS_GROUP);
+
memcpy(mapping, &map[i], sizeof(struct acpi_iort_id_mapping));
mapping++;
}
@@ -759,7 +783,7 @@ static int acpi_write_iort(struct acpi_ctx *ctx, const struct acpi_writer *entry
/* (Re)calculate length and checksum */
iort->header.length = ctx->current - (void *)iort;
- iort->header.checksum = table_compute_checksum((void *)iort, iort->header.length);
+ acpi_update_checksum(&iort->header);
log_debug("IORT at %p, length %x\n", iort, iort->header.length);
/* Drop the table if it is empty */
diff --git a/lib/acpi/base.c b/lib/acpi/base.c
index 8b6af2bc43a..5c755b14c16 100644
--- a/lib/acpi/base.c
+++ b/lib/acpi/base.c
@@ -50,8 +50,7 @@ static void acpi_write_rsdt(struct acpi_rsdt *rsdt)
/* Entries are filled in later, we come with an empty set */
/* Fix checksum */
- header->checksum = table_compute_checksum(rsdt,
- sizeof(struct acpi_rsdt));
+ acpi_update_checksum(header);
}
static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
@@ -66,8 +65,7 @@ static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
/* Entries are filled in later, we come with an empty set */
/* Fix checksum */
- header->checksum = table_compute_checksum(xsdt,
- sizeof(struct acpi_xsdt));
+ acpi_update_checksum(header);
}
static int acpi_write_base(struct acpi_ctx *ctx,
diff --git a/lib/acpi/csrt.c b/lib/acpi/csrt.c
index 00927e53406..b863c644c07 100644
--- a/lib/acpi/csrt.c
+++ b/lib/acpi/csrt.c
@@ -40,7 +40,7 @@ int acpi_write_csrt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
/* (Re)calculate length and checksum */
header->length = (ulong)ctx->current - (ulong)csrt;
- header->checksum = table_compute_checksum(csrt, header->length);
+ acpi_update_checksum(header);
acpi_add_table(ctx, csrt);
diff --git a/lib/acpi/mcfg.c b/lib/acpi/mcfg.c
index 8b8a5bfafae..e21fe7ce123 100644
--- a/lib/acpi/mcfg.c
+++ b/lib/acpi/mcfg.c
@@ -57,7 +57,7 @@ int acpi_write_mcfg(struct acpi_ctx *ctx, const struct acpi_writer *entry)
/* (Re)calculate length and checksum */
header->length = (ulong)ctx->current - (ulong)mcfg;
- header->checksum = table_compute_checksum(mcfg, header->length);
+ acpi_update_checksum(header);
acpi_add_table(ctx, mcfg);
diff --git a/lib/acpi/ssdt.c b/lib/acpi/ssdt.c
index df1d739d117..41e2d3c2f6c 100644
--- a/lib/acpi/ssdt.c
+++ b/lib/acpi/ssdt.c
@@ -35,7 +35,7 @@ int acpi_write_ssdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
/* (Re)calculate length and checksum */
ssdt->length = ctx->current - (void *)ssdt;
- ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
+ acpi_update_checksum(ssdt);
log_debug("SSDT at %p, length %x\n", ssdt, ssdt->length);
/* Drop the table if it is empty */