diff options
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/boot/acpi.c | 83 | ||||
-rw-r--r-- | src/arch/x86/include/arch/acpi.h | 35 |
2 files changed, 118 insertions, 0 deletions
diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index f17e73e3f6..010ba9f6ff 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -467,6 +467,89 @@ void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt, acpi_xsdt_t *xsdt) rsdp->ext_checksum = acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t)); } +unsigned long __attribute__((weak)) acpi_fill_hest(acpi_hest_t *hest) +{ + return (unsigned long)hest; +} + +unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, acpi_hest_esd_t *esd, u16 type, void *data, u16 data_len) +{ + acpi_header_t *header = &(hest->header); + acpi_hest_hen_t *hen; + void *pos; + u16 len; + + pos = esd; + memset(pos, 0, sizeof(acpi_hest_esd_t)); + len = 0; + esd->type = type; /* MCE */ + esd->source_id = hest->error_source_count; + esd->flags = 0; /* FIRMWARE_FIRST */ + esd->enabled = 1; + esd->prealloc_erecords = 1; + esd->max_section_per_record = 0x1; + + len += sizeof(acpi_hest_esd_t); + pos = esd + 1; + + switch (type) { + case 0: /* MCE */ + break; + case 1: /* CMC */ + hen = (acpi_hest_hen_t *) (pos); + memset(pos, 0, sizeof(acpi_hest_hen_t)); + hen->type = 3; /* SCI? */ + hen->length = sizeof(acpi_hest_hen_t); + hen->conf_we = 0; /* Configuration Write Enable. */ + hen->poll_interval = 0; + hen->vector = 0; + hen->sw2poll_threshold_val = 0; + hen->sw2poll_threshold_win = 0; + hen->error_threshold_val = 0; + hen->error_threshold_win = 0; + len += sizeof(acpi_hest_hen_t); + pos = hen + 1; + break; + case 2: /* NMI */ + case 6: /* AER Root Port */ + case 7: /* AER Endpoint */ + case 8: /* AER Bridge */ + case 9: /* Generic Hardware Error Source. */ + /* TODO: */ + break; + default: + printk(BIOS_DEBUG, "Invalid type of Error Source."); + break; + } + hest->error_source_count ++; + + memcpy(pos, data, data_len); + len += data_len; + header->length += len; + + return len; +} + +/* ACPI 4.0 */ +void acpi_write_hest(acpi_hest_t *hest) +{ + acpi_header_t *header = &(hest->header); + + memset(hest, 0, sizeof(acpi_hest_t)); + + memcpy(header->signature, "HEST", 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->length += sizeof(acpi_hest_t); + header->revision = 1; + + acpi_fill_hest(hest); + + /* Calculate checksums. */ + header->checksum = acpi_checksum((void *)hest, header->length); +} + #if CONFIG_HAVE_ACPI_RESUME == 1 void suspend_resume(void) { diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h index 8c521af0b2..60e400da78 100644 --- a/src/arch/x86/include/arch/acpi.h +++ b/src/arch/x86/include/arch/acpi.h @@ -357,6 +357,37 @@ typedef struct acpi_ecdt { u8 ec_id[]; /* EC ID */ } __attribute__ ((packed)) acpi_ecdt_t; +/* HEST (Hardware Error Source Table) */ +typedef struct acpi_hest { + struct acpi_table_header header; + u32 error_source_count; + /* error_source_struct(s) */ +} __attribute__ ((packed)) acpi_hest_t; + +/* Error Source Descriptors */ +typedef struct acpi_hest_esd { + u16 type; + u16 source_id; + u16 resv; + u8 flags; + u8 enabled; + u32 prealloc_erecords; /* The number of error records to pre-allocate for this error source. */ + u32 max_section_per_record; +} __attribute__ ((packed)) acpi_hest_esd_t; + +/* Hardware Error Notification */ +typedef struct acpi_hest_hen { + u8 type; + u8 length; + u16 conf_we; /* Configuration Write Enable */ + u32 poll_interval; + u32 vector; + u32 sw2poll_threshold_val; + u32 sw2poll_threshold_win; + u32 error_threshold_val; + u32 error_threshold_win; +} __attribute__ ((packed)) acpi_hest_hen_t; + /* These are implemented by the target port or north/southbridge. */ unsigned long write_acpi_tables(unsigned long addr); unsigned long acpi_fill_madt(unsigned long current); @@ -412,6 +443,10 @@ void acpi_write_rsdt(acpi_rsdt_t *rsdt); void acpi_write_xsdt(acpi_xsdt_t *xsdt); void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt, acpi_xsdt_t *xsdt); +void acpi_write_hest(acpi_hest_t *hest); +unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, acpi_hest_esd_t *esd, u16 type, void *data, u16 len); +unsigned long acpi_fill_hest(acpi_hest_t *hest); + #if CONFIG_HAVE_ACPI_RESUME /* 0 = S0, 1 = S1 ...*/ extern u8 acpi_slp_type; |