summaryrefslogtreecommitdiff
path: root/src/acpi
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2023-06-27 11:58:04 +0200
committerFelix Held <felix-coreboot@felixheld.de>2023-07-03 22:03:06 +0000
commit01af0f8ac80384d23abc99860f2c5d605a1aa540 (patch)
treea65a2751b0953586af21999962f0e643536ff7f0 /src/acpi
parent5b9957be0a7014dbcf14b6fe42f1273c763c3768 (diff)
acpi/acpi.c: Reduce boilerplate
Adding tables to R/XSDT, aligning current pointer, computing checksum is a lot of boilerplate that needs to be done for each table. TESTED on foxconn/g41. Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Change-Id: If4915b8cdfcfdbb34284ea75fa8a0fd23554152d Reviewed-on: https://review.coreboot.org/c/coreboot/+/76127 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Diffstat (limited to 'src/acpi')
-rw-r--r--src/acpi/acpi.c319
1 files changed, 118 insertions, 201 deletions
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c
index 267a989573..36556afe5c 100644
--- a/src/acpi/acpi.c
+++ b/src/acpi/acpi.c
@@ -338,13 +338,11 @@ static unsigned long acpi_create_madt_lapics_with_nmis(unsigned long current)
return current;
}
-static void acpi_create_madt(acpi_madt_t *madt)
+static void acpi_create_madt(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(madt->header);
+ acpi_madt_t *madt = (acpi_madt_t *)header;
unsigned long current = (unsigned long)madt + sizeof(acpi_madt_t);
- memset((void *)madt, 0, sizeof(acpi_madt_t));
-
if (!header)
return;
@@ -371,10 +369,8 @@ static void acpi_create_madt(acpi_madt_t *madt)
if (CONFIG(ACPI_CUSTOM_MADT))
current = acpi_fill_madt(current);
- /* (Re)calculate length and checksum. */
+ /* (Re)calculate length . */
header->length = current - (unsigned long)madt;
-
- header->checksum = acpi_checksum((void *)madt, header->length);
}
static unsigned long acpi_fill_mcfg(unsigned long current)
@@ -386,13 +382,11 @@ static unsigned long acpi_fill_mcfg(unsigned long current)
}
/* MCFG is defined in the PCI Firmware Specification 3.0. */
-static void acpi_create_mcfg(acpi_mcfg_t *mcfg)
+static void acpi_create_mcfg(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(mcfg->header);
+ acpi_mcfg_t *mcfg = (acpi_mcfg_t *)header;
unsigned long current = (unsigned long)mcfg + sizeof(acpi_mcfg_t);
- memset((void *)mcfg, 0, sizeof(acpi_mcfg_t));
-
if (!header)
return;
@@ -409,9 +403,8 @@ static void acpi_create_mcfg(acpi_mcfg_t *mcfg)
if (CONFIG(ECAM_MMCONF_SUPPORT))
current = acpi_fill_mcfg(current);
- /* (Re)calculate length and checksum. */
+ /* (Re)calculate length */
header->length = current - (unsigned long)mcfg;
- header->checksum = acpi_checksum((void *)mcfg, header->length);
}
static void *get_tcpa_log(u32 *size)
@@ -439,14 +432,15 @@ static void *get_tcpa_log(u32 *size)
return lasa;
}
-static void acpi_create_tcpa(acpi_tcpa_t *tcpa)
+static void acpi_create_tcpa(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(tcpa->header);
+ if (!CONFIG(TPM1))
+ return;
+
+ acpi_tcpa_t *tcpa = (acpi_tcpa_t *)header;
u32 tcpa_log_len;
void *lasa;
- memset((void *)tcpa, 0, sizeof(acpi_tcpa_t));
-
lasa = get_tcpa_log(&tcpa_log_len);
if (!lasa)
return;
@@ -467,9 +461,6 @@ static void acpi_create_tcpa(acpi_tcpa_t *tcpa)
tcpa->platform_class = 0;
tcpa->laml = tcpa_log_len;
tcpa->lasa = (uintptr_t)lasa;
-
- /* Calculate checksum. */
- header->checksum = acpi_checksum((void *)tcpa, header->length);
}
static void *get_tpm2_log(u32 *size)
@@ -497,14 +488,15 @@ static void *get_tpm2_log(u32 *size)
return lasa;
}
-static void acpi_create_tpm2(acpi_tpm2_t *tpm2)
+static void acpi_create_tpm2(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(tpm2->header);
+ if (!CONFIG(TPM2))
+ return;
+
+ acpi_tpm2_t *tpm2 = (acpi_tpm2_t *)header;
u32 tpm2_log_len;
void *lasa;
- memset((void *)tpm2, 0, sizeof(acpi_tpm2_t));
-
/*
* Some payloads like SeaBIOS depend on log area to use TPM2.
* Get the memory size and address of TPM2 log area or initialize it.
@@ -542,9 +534,6 @@ static void acpi_create_tpm2(acpi_tpm2_t *tpm2)
/* Fill the log area size and start address fields. */
tpm2->laml = tpm2_log_len;
tpm2->lasa = (uintptr_t)lasa;
-
- /* Calculate checksum. */
- header->checksum = acpi_checksum((void *)tpm2, header->length);
}
static void acpi_ssdt_write_cbtable(void)
@@ -570,7 +559,7 @@ static void acpi_ssdt_write_cbtable(void)
acpigen_pop_len();
}
-static void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id)
+static void acpi_create_ssdt_generator(acpi_header_t *ssdt, void *unused)
{
unsigned long current = (unsigned long)ssdt + sizeof(acpi_header_t);
@@ -579,7 +568,7 @@ static void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_tabl
memcpy(&ssdt->signature, "SSDT", 4);
ssdt->revision = get_acpi_table_revision(SSDT);
memcpy(&ssdt->oem_id, OEM_ID, 6);
- memcpy(&ssdt->oem_table_id, oem_table_id, 8);
+ memcpy(&ssdt->oem_table_id, ACPI_TABLE_CREATOR, 8);
ssdt->oem_revision = 42;
memcpy(&ssdt->asl_compiler_id, ASLC, 4);
ssdt->asl_compiler_revision = asl_revision;
@@ -600,7 +589,6 @@ static void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_tabl
/* (Re)calculate length and checksum. */
ssdt->length = current - (unsigned long)ssdt;
- ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
}
int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
@@ -1504,9 +1492,9 @@ unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
return current;
}
-static void acpi_create_facs(acpi_facs_t *facs)
+static void acpi_create_facs(void *header)
{
- memset((void *)facs, 0, sizeof(acpi_facs_t));
+ acpi_facs_t *facs = header;
memcpy(facs->signature, "FACS", 4);
facs->length = sizeof(acpi_facs_t);
@@ -1681,15 +1669,21 @@ void acpi_write_hest(acpi_hest_t *hest,
}
/* ACPI 3.0b */
-static void acpi_write_bert(acpi_bert_t *bert, uintptr_t region, size_t length)
+static void acpi_create_bert(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(bert->header);
+ if (!CONFIG(ACPI_BERT))
+ return;
- memset(bert, 0, sizeof(acpi_bert_t));
+ acpi_bert_t *bert = (acpi_bert_t *)header;
if (!header)
return;
+ void *region;
+ size_t size;
+ if (acpi_soc_get_bert_region(&region, &size) != CB_SUCCESS)
+ return;
+
memcpy(header->signature, "BERT", 4);
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
@@ -1698,22 +1692,19 @@ static void acpi_write_bert(acpi_bert_t *bert, uintptr_t region, size_t length)
header->length += sizeof(acpi_bert_t);
header->revision = get_acpi_table_revision(BERT);
- bert->error_region = region;
- bert->region_length = length;
-
- /* Calculate checksums. */
- header->checksum = acpi_checksum((void *)bert, header->length);
+ bert->error_region = (uintptr_t)region;
+ bert->region_length = (size_t)size;
}
__weak void arch_fill_fadt(acpi_fadt_t *fadt) { }
__weak void soc_fill_fadt(acpi_fadt_t *fadt) { }
__weak void mainboard_fill_fadt(acpi_fadt_t *fadt) { }
-static void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
+static acpi_header_t *dsdt;
+static void acpi_create_fadt(acpi_header_t *header, void *arg1)
{
- acpi_header_t *header = &(fadt->header);
-
- memset((void *)fadt, 0, sizeof(acpi_fadt_t));
+ acpi_fadt_t *fadt = (acpi_fadt_t *)header;
+ acpi_facs_t *facs = (acpi_facs_t *)(*(acpi_facs_t **)arg1);
if (!header)
return;
@@ -1756,17 +1747,15 @@ static void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
soc_fill_fadt(fadt);
mainboard_fill_fadt(fadt);
-
- header->checksum =
- acpi_checksum((void *)fadt, header->length);
}
-static void acpi_create_lpit(acpi_lpit_t *lpit)
+static void acpi_create_lpit(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(lpit->header);
- unsigned long current = (unsigned long)lpit + sizeof(acpi_lpit_t);
+ if (!CONFIG(ACPI_LPIT))
+ return;
- memset((void *)lpit, 0, sizeof(acpi_lpit_t));
+ acpi_lpit_t *lpit = (acpi_lpit_t *)header;
+ unsigned long current = (unsigned long)lpit + sizeof(acpi_lpit_t);
if (!header)
return;
@@ -1784,9 +1773,8 @@ static void acpi_create_lpit(acpi_lpit_t *lpit)
current = acpi_fill_lpit(current);
- /* (Re)calculate length and checksum. */
+ /* (Re)calculate length. */
header->length = current - (unsigned long)lpit;
- header->checksum = acpi_checksum((void *)lpit, header->length);
}
unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t uid)
@@ -1811,14 +1799,11 @@ static uint8_t acpi_spcr_type(void)
return 0xff;
}
-static void acpi_create_spcr(acpi_spcr_t *spcr)
+static void acpi_create_spcr(acpi_header_t *header, void *unused)
{
- acpi_header_t *header = &(spcr->header);
+ acpi_spcr_t *spcr = (acpi_spcr_t *)header;
struct lb_serial serial;
- /* The caller checks the header size, so call this first */
- memset((void *)spcr, 0, sizeof(acpi_spcr_t));
-
if (!CONFIG(CONSOLE_SERIAL))
return;
@@ -1886,6 +1871,46 @@ void preload_acpi_dsdt(void)
cbfs_preload(file);
}
+static void acpi_create_dsdt(acpi_header_t *header, void *dsdt_file_arg)
+{
+ dsdt = header;
+ acpi_header_t *dsdt_file = *(acpi_header_t **)dsdt_file_arg;
+ unsigned long current = (unsigned long)header;
+
+ dsdt = (acpi_header_t *)current;
+ memcpy(dsdt, dsdt_file, sizeof(acpi_header_t));
+ if (dsdt->length >= sizeof(acpi_header_t)) {
+ current += sizeof(acpi_header_t);
+
+ acpigen_set_current((char *)current);
+
+ if (CONFIG(ACPI_SOC_NVS))
+ acpi_fill_gnvs();
+ if (CONFIG(CHROMEOS_NVS))
+ acpi_fill_cnvs();
+
+ for (const struct device *dev = all_devices; dev; dev = dev->next)
+ if (dev->ops && dev->ops->acpi_inject_dsdt)
+ dev->ops->acpi_inject_dsdt(dev);
+ current = (unsigned long)acpigen_get_current();
+ memcpy((char *)current,
+ (char *)dsdt_file + sizeof(acpi_header_t),
+ dsdt->length - sizeof(acpi_header_t));
+ current += dsdt->length - sizeof(acpi_header_t);
+
+ /* (Re)calculate length. */
+ dsdt->length = current - (unsigned long)dsdt;
+ }
+}
+
+static void acpi_create_slic(acpi_header_t *header, void *slic_file_arg)
+{
+ acpi_header_t *slic_file = *(acpi_header_t **)slic_file_arg;
+ acpi_header_t *slic = header;
+ if (slic_file)
+ memcpy(slic, slic_file, slic_file->length);
+}
+
static uintptr_t coreboot_rsdp;
uintptr_t get_coreboot_rsdp(void)
@@ -1931,22 +1956,33 @@ unsigned long write_acpi_tables(const unsigned long start)
acpi_rsdp_t *rsdp;
acpi_rsdt_t *rsdt = NULL;
acpi_xsdt_t *xsdt = NULL;
- acpi_fadt_t *fadt = NULL;
acpi_facs_t *facs = NULL;
- acpi_header_t *slic_file, *slic = NULL;
+ acpi_header_t *slic_file;
acpi_header_t *ssdt = NULL;
- acpi_header_t *dsdt_file, *dsdt = NULL;
- acpi_mcfg_t *mcfg = NULL;
- acpi_tcpa_t *tcpa = NULL;
- acpi_tpm2_t *tpm2 = NULL;
- acpi_madt_t *madt = NULL;
- acpi_lpit_t *lpit = NULL;
- acpi_bert_t *bert = NULL;
+ acpi_header_t *dsdt_file;
struct device *dev;
unsigned long fw;
size_t slic_size, dsdt_size;
char oem_id[6], oem_table_id[8];
+ const struct acpi_table_generator {
+ void (*create_table)(acpi_header_t *table, void *arg);
+ void *args;
+ size_t min_size;
+ } tables[] = {
+ { acpi_create_dsdt, &dsdt_file, sizeof(acpi_header_t) },
+ { acpi_create_fadt, &facs, sizeof(acpi_fadt_t) },
+ { acpi_create_slic, &slic_file, sizeof(acpi_header_t) },
+ { acpi_create_ssdt_generator, NULL, sizeof(acpi_header_t) },
+ { acpi_create_mcfg, NULL, sizeof(acpi_mcfg_t) },
+ { acpi_create_tcpa, NULL, sizeof(acpi_tcpa_t) },
+ { acpi_create_tpm2, NULL, sizeof(acpi_tpm2_t) },
+ { acpi_create_lpit, NULL, sizeof(acpi_lpit_t) },
+ { acpi_create_madt, NULL, sizeof(acpi_header_t) },
+ { acpi_create_bert, NULL, sizeof(acpi_bert_t) },
+ { acpi_create_spcr, NULL, sizeof(acpi_spcr_t) },
+ };
+
current = start;
/* Align ACPI tables to 16byte */
@@ -1992,7 +2028,7 @@ unsigned long write_acpi_tables(const unsigned long start)
ssdt->length = current - (unsigned long)ssdt;
ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
- acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
+ acpi_create_ssdt_generator(ssdt, NULL);
acpi_add_table(rsdp, ssdt);
@@ -2052,59 +2088,26 @@ unsigned long write_acpi_tables(const unsigned long start)
acpi_write_rsdt(rsdt, oem_id, oem_table_id);
acpi_write_xsdt(xsdt, oem_id, oem_table_id);
- printk(BIOS_DEBUG, "ACPI: * FACS\n");
current = ALIGN_UP(current, 64);
+
+ printk(BIOS_DEBUG, "ACPI: * FACS\n");
facs = (acpi_facs_t *)current;
current += sizeof(acpi_facs_t);
current = acpi_align_current(current);
acpi_create_facs(facs);
- printk(BIOS_DEBUG, "ACPI: * DSDT\n");
- dsdt = (acpi_header_t *)current;
- memcpy(dsdt, dsdt_file, sizeof(acpi_header_t));
- if (dsdt->length >= sizeof(acpi_header_t)) {
- current += sizeof(acpi_header_t);
-
- acpigen_set_current((char *)current);
-
- if (CONFIG(ACPI_SOC_NVS))
- acpi_fill_gnvs();
- if (CONFIG(CHROMEOS_NVS))
- acpi_fill_cnvs();
-
- for (dev = all_devices; dev; dev = dev->next)
- if (dev->ops && dev->ops->acpi_inject_dsdt)
- dev->ops->acpi_inject_dsdt(dev);
- current = (unsigned long)acpigen_get_current();
- memcpy((char *)current,
- (char *)dsdt_file + sizeof(acpi_header_t),
- dsdt->length - sizeof(acpi_header_t));
- current += dsdt->length - sizeof(acpi_header_t);
-
- /* (Re)calculate length and checksum. */
- dsdt->length = current - (unsigned long)dsdt;
- dsdt->checksum = 0;
- dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
- }
-
- current = acpi_align_current(current);
-
- printk(BIOS_DEBUG, "ACPI: * FADT\n");
- fadt = (acpi_fadt_t *)current;
- current += sizeof(acpi_fadt_t);
- current = acpi_align_current(current);
-
- acpi_create_fadt(fadt, facs, dsdt);
- acpi_add_table(rsdp, fadt);
-
- if (slic_file) {
- printk(BIOS_DEBUG, "ACPI: * SLIC\n");
- slic = (acpi_header_t *)current;
- memcpy(slic, slic_file, slic_file->length);
- current += slic_file->length;
+ for (size_t i = 0; i < ARRAY_SIZE(tables); i++) {
+ acpi_header_t *header = (acpi_header_t *)current;
+ memset(header, 0, tables[i].min_size);
+ tables[i].create_table(header, tables[i].args);
+ if (header->length < tables[i].min_size)
+ continue;
+ header->checksum = 0;
+ header->checksum = acpi_checksum((void *)header, header->length);
+ current += header->length;
current = acpi_align_current(current);
- acpi_add_table(rsdp, slic);
- cbfs_unmap(slic_file);
+ printk(BIOS_DEBUG, "ACPI: * %.4s\n", header->signature);
+ acpi_add_table(rsdp, header);
}
/*
@@ -2113,95 +2116,9 @@ unsigned long write_acpi_tables(const unsigned long start)
* This is why unmapping of dsdt_file must be done after
* unmapping slic file.
*/
+ cbfs_unmap(slic_file);
cbfs_unmap(dsdt_file);
- printk(BIOS_DEBUG, "ACPI: * SSDT\n");
- ssdt = (acpi_header_t *)current;
- acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
- if (ssdt->length > sizeof(acpi_header_t)) {
- current += ssdt->length;
- acpi_add_table(rsdp, ssdt);
- current = acpi_align_current(current);
- }
-
- printk(BIOS_DEBUG, "ACPI: * MCFG\n");
- mcfg = (acpi_mcfg_t *)current;
- acpi_create_mcfg(mcfg);
- if (mcfg->header.length > sizeof(acpi_mcfg_t)) {
- current += mcfg->header.length;
- current = acpi_align_current(current);
- acpi_add_table(rsdp, mcfg);
- }
-
- if (CONFIG(TPM1)) {
- printk(BIOS_DEBUG, "ACPI: * TCPA\n");
- tcpa = (acpi_tcpa_t *)current;
- acpi_create_tcpa(tcpa);
- if (tcpa->header.length >= sizeof(acpi_tcpa_t)) {
- current += tcpa->header.length;
- current = acpi_align_current(current);
- acpi_add_table(rsdp, tcpa);
- }
- }
-
- if (CONFIG(TPM2)) {
- printk(BIOS_DEBUG, "ACPI: * TPM2\n");
- tpm2 = (acpi_tpm2_t *)current;
- acpi_create_tpm2(tpm2);
- if (tpm2->header.length >= sizeof(acpi_tpm2_t)) {
- current += tpm2->header.length;
- current = acpi_align_current(current);
- acpi_add_table(rsdp, tpm2);
- }
- }
-
- if (CONFIG(ACPI_LPIT)) {
- printk(BIOS_DEBUG, "ACPI: * LPIT\n");
-
- lpit = (acpi_lpit_t *)current;
- acpi_create_lpit(lpit);
- if (lpit->header.length >= sizeof(acpi_lpit_t)) {
- current += lpit->header.length;
- current = acpi_align_current(current);
- acpi_add_table(rsdp, lpit);
- }
- }
-
- printk(BIOS_DEBUG, "ACPI: * MADT\n");
-
- madt = (acpi_madt_t *)current;
- acpi_create_madt(madt);
- if (madt->header.length > sizeof(acpi_madt_t)) {
- current += madt->header.length;
- acpi_add_table(rsdp, madt);
- }
-
- current = acpi_align_current(current);
-
- if (CONFIG(ACPI_BERT)) {
- void *region;
- size_t size;
- bert = (acpi_bert_t *)current;
- if (acpi_soc_get_bert_region(&region, &size) == CB_SUCCESS) {
- printk(BIOS_DEBUG, "ACPI: * BERT\n");
- acpi_write_bert(bert, (uintptr_t)region, size);
- if (bert->header.length >= sizeof(acpi_bert_t)) {
- current += bert->header.length;
- acpi_add_table(rsdp, bert);
- }
- current = acpi_align_current(current);
- }
- }
-
- printk(BIOS_DEBUG, "ACPI: * SPCR\n");
- acpi_spcr_t * const spcr = (acpi_spcr_t *)current;
- acpi_create_spcr(spcr);
- if (spcr->header.length >= sizeof(acpi_spcr_t)) {
- current += spcr->header.length;
- acpi_add_table(rsdp, spcr);
- }
- current = acpi_align_current(current);
-
printk(BIOS_DEBUG, "current = %lx\n", current);
for (dev = all_devices; dev; dev = dev->next) {