Gaggery Tsai has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/77255?usp=email )
Change subject: src/soc/intel/common: Add ACPI BDAT support ......................................................................
src/soc/intel/common: Add ACPI BDAT support
This patch adds ACPI BDAT support. It parses the data from HOB and and fills with a BDAT header.
BUG=b:293441360 TEST=1. Add -DBDAT_SUPPORT=1 to build FSP packages. 2. Enable SOC_INTEL_RMT_PLUS flag with Brya. 3. Flash the image on Brya and ensure BDAT ACPI table is available under /sys/firmware/acpi/tables/.
Change-Id: I5eb57f65ef5f24458f09587b7c7694156f2ed1ce Signed-off-by: Gaggery Tsai gaggery.tsai@intel.com --- M src/soc/intel/common/Kconfig.common M src/soc/intel/common/block/acpi/Makefile.inc A src/soc/intel/common/block/acpi/acpi_bdat.c A src/soc/intel/common/block/include/intelblocks/acpi_bdat.h 4 files changed, 261 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/55/77255/1
diff --git a/src/soc/intel/common/Kconfig.common b/src/soc/intel/common/Kconfig.common index ed6068d..0d2ff57 100644 --- a/src/soc/intel/common/Kconfig.common +++ b/src/soc/intel/common/Kconfig.common @@ -69,6 +69,13 @@ help Provide a mechanism for serial console based ACPI debug.
+config SOC_INTEL_COMMON_ACPI_BDAT + bool + default n + select ACPI_BDAT + help + Export BIOS Data to ACPI space. + config PAVP bool "Enable PAVP (Protected Audio-Video Path) support" default y diff --git a/src/soc/intel/common/block/acpi/Makefile.inc b/src/soc/intel/common/block/acpi/Makefile.inc index 0375ce9..0fb96dc 100644 --- a/src/soc/intel/common/block/acpi/Makefile.inc +++ b/src/soc/intel/common/block/acpi/Makefile.inc @@ -3,6 +3,7 @@ ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_GPIO) += gpio.c ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_LPIT) += lpit.c ramstage-$(CONFIG_ACPI_BERT) += acpi_bert.c +ramstage-$(CONFIG_ACPI_BDAT) += acpi_bdat.c ramstage-$(CONFIG_SOC_INTEL_COMMON_ACPI_WAKE_SOURCE) += acpi_wake_source.c ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_PEP) += pep.c ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SGX_ENABLE) += sgx.c diff --git a/src/soc/intel/common/block/acpi/acpi_bdat.c b/src/soc/intel/common/block/acpi/acpi_bdat.c new file mode 100644 index 0000000..8922896 --- /dev/null +++ b/src/soc/intel/common/block/acpi/acpi_bdat.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <acpi/acpi.h> +#include <acpi/acpigen.h> +#include <console/console.h> +#include <fsp/api.h> +#include <fsp/util.h> +#include <intelblocks/acpi.h> +#include <intelblocks/acpi_bdat.h> +#include <uuid.h> + +#define INTEL_FSP_BDAT_SCHEMA_LIST_HOB_GUID \ + GUID_INIT(0x3047C2AC, 0x5E8E, 0x4C55, \ + 0xA1, 0xCB, 0xEA, 0xAD, 0x0A, 0x88, 0x86, 0x1B ) + +static void print_guid(EFI_GUID *guid) { + int i; + if (guid != NULL) { + printk(BIOS_DEBUG, "GUID = "); + printk(BIOS_DEBUG, "0x%08x-", guid->Data1); + printk(BIOS_DEBUG, "0x%04x-", guid->Data2); + printk(BIOS_DEBUG, "0x%04x-", guid->Data3); + for (i=0; i<8; i++) { + printk(BIOS_DEBUG, "0x%02x", guid->Data4[i]); + if (i != 7) + printk(BIOS_DEBUG, "-"); + } + printk(BIOS_DEBUG, "\n"); + } +} + +static uint16_t get_crc16(const uint8_t *ptr, int32_t n_crc) +{ + int i; + uint16_t crc = 0; + + while (--n_crc >= 0) { + crc = crc ^ ((int)*ptr++ << 8); + for (i = 0; i < 8; ++i) + if (crc & 0x8000) + crc = (crc << 1) ^ 0x1021; + else + crc = crc << 1; + } + return crc; +} + +enum cb_err acpi_soc_get_bdat_region(void **region, size_t *length) { + size_t hob_size = 0; + static const bdat_schema_list_hob *schema_list_hob; + void *buffer = NULL; + bdat_structure *bdat; + EFI_GUID *guid; + const uint32_t *schema[MAX_SCHEMA_LIST_LENGTH]; + uint32_t schema_size[MAX_SCHEMA_LIST_LENGTH]; + uint32_t *schema_offset_list; + uint8_t *next_block,*schema_data; + uint32_t data_size, buffer_size=0, header_size, index; + uint8_t schema_count=0; + const uint8_t bdat_header_sign[] = {'B','D','A','T','H','E','A','D'}; + bdat_header_structure *bdat_header; + + schema_list_hob = fsp_find_extension_hob_by_guid( + INTEL_FSP_BDAT_SCHEMA_LIST_HOB_GUID.b, &hob_size); + + if (schema_list_hob == NULL || hob_size == 0) { + printk(BIOS_ERR, "No BDAT data exists.\n"); + return CB_ERR; + } + printk(BIOS_INFO, "Found Schema List HOB, address=0x%p, hob_size=%ld\n", + (void *)&schema_list_hob, hob_size); + + /* Determin the buffer size. */ + for (index = 0; index < schema_list_hob->schema_hob_count; index++) { + guid = (EFI_GUID *) &(schema_list_hob->schema_hob_guids[index]); + schema[index] = NULL; + if (guid != NULL) { + print_guid(guid); + uint8_t *p = (uint8_t *)guid; + schema[index] = fsp_find_extension_hob_by_guid(p, &hob_size); + printk(BIOS_DEBUG, "Schema HOB pointer: %x, size = %ld\n", + (uint32_t) (uintptr_t) schema[index], hob_size); + if (schema[index] != NULL) { + schema_size[index] = hob_size; + buffer_size += hob_size; + schema_count++; + } + } + } + printk(BIOS_DEBUG, "schema_hob_count = %d, schema_count = %d\n", + (uint32_t) schema_list_hob->schema_hob_count, (uint32_t) schema_count); + + /* Check if we did not find any schemas */ + if (schema_count == 0) { + printk(BIOS_ERR, "No BDAT data exists.\n"); + return CB_ERR; + } + + /* + * Request the memory from CBMEM and clear it. + * This memory is used to store the BDAT into the ACPI table. + * --------------------------------- + * /| BDAT header structure | + * / |-------------------------------| + * / | BDAT schema list structure | + * / |-------------------------------| + * / | Schemas[0] |-------- + * Header |-------------------------------| | + * \ | Schemas[1] |-------|------ + * \ |-------------------------------| | | + * \ | ...... | | | + * \ |-------------------------------| | | + * | Schemas[N] |-------|-----|------ + * |-------------------------------| | | | + * | Schema[0] header structure |/______| | | + * |-------------------------------|\ | | + * | SSA result data | | | + * | ................ | | | + * |-------------------------------| | | + * | Schema[1] header structure |/____________| | + * |-------------------------------|\ | + * | SSA result data | | + * | ................ | | + * |-------------------------------| | + * | ................ | | + * |-------------------------------| | + * | Schema[N] header structure |/__________________| + * |-------------------------------|\ + * | SSA result data | + * | ................ | + * |-------------------------------| + */ + header_size = sizeof (bdat_header_structure) + + sizeof (bdat_schema_list_structure) + + (schema_count * sizeof (uint32_t)); + /* Add header size to the total requested buffer size. */ + buffer_size += header_size; + printk(BIOS_DEBUG, "BDAT buffer size = %d\n", buffer_size); + buffer = cbmem_add(CBMEM_ID_ACPI_BDAT, buffer_size); + if (buffer == NULL) { + printk(BIOS_ERR, "CBMEM entry for BDAT info missing.\n"); + return CB_ERR; + } + memset(buffer, 0, buffer_size); + + /* Copy the RMT data to BDAT structure. */ + bdat = (bdat_structure *) buffer; + next_block = (uint8_t *) ((uintptr_t) buffer + header_size); + schema_offset_list = (uint32_t*) (((uintptr_t) buffer) + + sizeof (bdat_structure)); + + /* Initialize the BDAT structure header. */ + bdat_header = &bdat->header; + /* Defined in BDAT spec chapter 4. */ + memcpy (&bdat_header->bios_data_sig[0], + (uint8_t *) bdat_header_sign, sizeof (bdat_header->bios_data_sig)); + bdat_header->bios_data_size = sizeof (bdat_structure) + + (schema_count * sizeof (uint32_t)); + bdat_header->primary_rev = BDAT_PRIMARY_VERSION; + bdat_header->secondary_rev = BDAT_SECONDARY_VERSION; + /* Initialize the schema list. */ + bdat->schemas->schema_list_length = schema_count; + + /* Copy the RMT data from each schema location*/ + for (index = 0; index < schema_count; index++) { + if (schema[index] != NULL) { + data_size = schema_size[index]; + schema_data = (uint8_t*) schema[index]; + memcpy (next_block, schema_data, data_size); + schema_offset_list[index++] = + (uint32_t) ((uintptr_t) next_block - (uintptr_t) bdat); + next_block = (uint8_t *) ((uintptr_t) next_block + data_size); + } + } + + /* Fill the size and CRC of the BDAT structure. */ + bdat->header.bios_data_size = buffer_size; + bdat->header.crc16 = get_crc16 ((const uint8_t * const) bdat, header_size); + *length = buffer_size; + *region = (void *)buffer; + + return CB_SUCCESS; +} diff --git a/src/soc/intel/common/block/include/intelblocks/acpi_bdat.h b/src/soc/intel/common/block/include/intelblocks/acpi_bdat.h new file mode 100644 index 0000000..3286646 --- /dev/null +++ b/src/soc/intel/common/block/include/intelblocks/acpi_bdat.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SOC_INTEL_COMMON_BLOCK_ACPI_BDAT_H +#define SOC_INTEL_COMMON_BLOCK_ACPI_BDAT_H + +#include <acpi/acpi.h> +#include <fsp/api.h> +#include <fsp/util.h> + +#define BDAT_PRIMARY_VERSION 4 +#define BDAT_SECONDARY_VERSION 0 + +/* + * The header information is from + * BDAT interface spec 4.0. + */ +typedef struct { + /* "BDATHEAD" */ + uint8_t bios_data_sig[8]; + uint32_t bios_data_size; + uint16_t crc16; + uint16_t reserved; + uint16_t primary_rev; + uint16_t secondary_rev; + uint32_t ome_offset; + uint32_t reserved1; + uint32_t reserved2; +} bdat_header_structure; + +typedef struct { + uint16_t schema_list_length; + uint16_t reserved1; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t reserved2; +} bdat_schema_list_structure; + +typedef struct { + bdat_header_structure header; + bdat_schema_list_structure schemas; +} bdat_structure; + +#define MAX_SCHEMA_LIST_LENGTH (10) + +/* + * Not strictly part of the BDAT spec. This HOB is used to identify which HOBs + * contain data that should be copied into the final BDAT structure as a schema. + */ +typedef struct { + /* + * Number of HOBs that exist which contain data that should be + * copied to the BDAT structure. + */ + uint16_t schema_hob_count; + uint16_t reserved; + /* + * Array of GUIDs which identify HOBs that contain data + * that should be copied into the BDAT structure. The contents + * of the HOB contains a schema. The GUID for the HOB is the + * same as the SchemaId GUID. + */ + EFI_GUID schema_hob_guids[MAX_SCHEMA_LIST_LENGTH]; +} bdat_schema_list_hob; + +#endif /* SOC_INTEL_COMMON_BLOCK_ACPI_BDAT_H */ +